2017-10-30 8 views
0

のリスト内の更新値が、私はそのようなこの一つとして、実際に辞書のリストである変数を持っている:Ansible:私のペイロード内の辞書

myvar: 
    - name: name1 
    ip_addresses: 
     - 10.10.10.10 
     - 11.11.11.11 
    nat_destination_addresses: 
     - host: 12.12.12.12 
     destination: 13.13.13.13 
     - host: 14.14.14.14 
     destination: 15.15.15.15 
    nat_source_address: 16.16.16.16 
    applications: 
     - protocol: tcp 
     port: 8302 
     - protocol: udp 
     port: 2000 
     - protocol: tcp 
     port: 2000-5600 

    - name: name2 
    ip_addresses: 
     - 17.17.17.17 

    - name: name3 
    ip_addresses: 
     - 18.18.18.18 
     - 19.19.19.19 

myvarにおける各要素のすべての値はオプションですただし、必須の名前は除きます。

私は、IPアドレス(ip_addressesnat_destination_addressesおよびnat_source_address)とポートをパディングしようとしています。ポートは、最初にゼロで5文字の長さにする必要があります(2000はになり、2000-560002000-05600になります)。また、各サブセクションには3文字の文字が必要です。18.18.18.18018.018.018.018になります。

問題は私がmyvarのサブセクションだけを変更することができないということです。

merging dictionaries in ansible

Using set_facts and with_items together in Ansible

しかし無駄に:

私のような、ここで他の質問を、読みました。私が何をしても元の辞書を保持できないので、2番目のStackOverflowリンクからcombineフィルタを使用すると、ip_addressesのリストになります。

予想される結果は、更新されたIPアドレスとポートを持つ元のmyvar変数です。

答えて

2

これは、あなたのロジックをカスタムAnsibleモジュールに投げ込むのに適しているようです。私はlibrary/pad_data.pyに上記ドロップして、次の脚本実行する場合

from ansible.module_utils.basic import AnsibleModule 


def pad_addr(addr): 
    return '.'.join('%03d' % int(x) for x in addr.split('.')) 


def main(): 
    module_args = dict(
     data=dict(type='list', required=True), 
    ) 

    module = AnsibleModule(
     argument_spec=module_args, 
     supports_check_mode=True 
    ) 

    data = module.params['data'] 

    for d in data: 
     if 'ip_addresses' in d: 
      d['ip_addresses'] = [pad_addr(x) for x in d['ip_addresses']] 

     if 'nat_destination_addresses' in d: 
      for dest in d['nat_destination_addresses']: 
       dest['host'] = pad_addr(dest['host']) 
       dest['destination'] = pad_addr(dest['destination']) 

     if 'nat_source_address' in d: 
      d['nat_source_address'] = pad_addr(d['nat_source_address']) 

     if 'applications' in d: 
      for service in d['applications']: 
       service['port'] = '%05d' % service['port'] 

    module.exit_json(changed=False, 
        result=data) 

if __name__ == '__main__': 
    main() 

- hosts: localhost 
    gather_facts: false 

    vars: 
    myvar: 
     - name: name1 
     ip_addresses: 
      - 10.10.10.10 
      - 11.11.11.11 
     nat_destination_addresses: 
      - host: 12.12.12.12 
      destination: 13.13.13.13 
      - host: 14.14.14.14 
      destination: 15.15.15.15 
     nat_source_address: 16.16.16.16 
     applications: 
      - protocol: tcp 
      port: 8302 
      - protocol: udp 
      port: 2000 
      - protocol: tcp 
      port: 2000 

     - name: name2 
     ip_addresses: 
      - 17.17.17.17 

     - name: name3 
     ip_addresses: 
      - 18.18.18.18 
      - 19.19.19.19 

    tasks: 

    - pad_data: 
     data: "{{ myvar }}" 
     register: padded 

    - debug: 
     var: padded.result 

私は結果として得る:

をそれは例えば、何も空想である必要はありません。
TASK [debug] ******************************************************************* 
ok: [localhost] => { 
    "padded.result": [ 
     { 
      "applications": [ 
       { 
        "port": "08302", 
        "protocol": "tcp" 
       }, 
       { 
        "port": "02000", 
        "protocol": "udp" 
       }, 
       { 
        "port": "02000", 
        "protocol": "tcp" 
       } 
      ], 
      "ip_addresses": [ 
       "010.010.010.010", 
       "011.011.011.011" 
      ], 
      "name": "name1", 
      "nat_destination_addresses": [ 
       { 
        "destination": "013.013.013.013", 
        "host": "012.012.012.012" 
       }, 
       { 
        "destination": "015.015.015.015", 
        "host": "014.014.014.014" 
       } 
      ], 
      "nat_source_address": "016.016.016.016" 
     }, 
     { 
      "ip_addresses": [ 
       "017.017.017.017" 
      ], 
      "name": "name2" 
     }, 
     { 
      "ip_addresses": [ 
       "018.018.018.018", 
       "019.019.019.019" 
      ], 
      "name": "name3" 
     } 
    ] 
} 
+0

感謝を使用して、古いmyvar変数を置き換えるリロード!そのソリューションをテストしたところ、うまく動作していましたが、残念ながら、私たちが作成するPythonモジュールの数を制限しようとしています(私の決定ではありません)。私と同じ要件を持っています。 – Drizzt

0

Larsksの回答がポイントであり、おそらくほとんどの人に最適な解決策ですが、私の要件はこのプロジェクトでPythonで作成されるモジュールの数を制限することです。参考のために。

基本的に、私はこのサンプルでやっていることは次のとおりです。ローカル

:私はmyvar取る

、YMLファイルへのI出力、それを(と '---' ファイルの先頭に

regexpとreplaceモジュールを使用して、置き換えたいファイルの部分を置き換えます。私のすべてのホスト上で

私は(今)、正しくmyvarをフォーマットし、あなたの答えのためのinclude_vars

--- 

- name: Customer {{ customer_id }} - Format the ip addresses and ports 
    hosts: localhost 
    gather_facts: no 
    connection: local 
    tags: [format_vars] 

    tasks: 
    - name: Copy the 'myvar' content to a local file to allow ip addresses 
and ports formatting 
     copy: 
     content: "---\n{{ { 'myvar': myvar} | to_nice_yaml(indent=2) }}" 
     dest: "{{ formatted_myvar_file }}" 

    - name: Pad all ip addresses parts with two zeroes to ensure that all parts have at least three numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})' 
     replace: '00\1.00\2.00\3.00\4' 

    - name: Remove extra zeroes from ip addresses to ensure that all of their parts have exactly three numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: '\d{0,2}(\d{3})\.\d{0,2}(\d{3})\.\d{0,2}(\d{3})\.\d{0,2}(\d{3})' 
     replace: '\1.\2.\3.\4' 

    - name: Pad all ports with four zeroes to ensure that they all have at least five numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: 'port: (\d{1,5})' 
     replace: 'port: 0000\1' 

    - name: Remove extra zeroes from ports to ensure that they all have exactly five numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: 'port: \d{0,4}(\d{5})' 
     replace: 'port: \1' 

    - name: Pad all second parts of port ranges with four zeroes to ensure that they all have at least five numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: 'port: (\d{5})-(\d{1,5})' 
     replace: 'port: \1-0000\2' 

    - name: Remove extra zeroes from second parts of port ranges to ensure that they all have exactly five numbers 
     replace: 
     path: "{{ formatted_myvar_file }}" 
     regexp: 'port: (\d{5})-\d{0,4}(\d{5})' 
     replace: 'port: \1-\2' 

- name: Customer {{ customer_id }} - Load the properly formatted ip addresses and ports 
    hosts: localhost:all-n7k:srx-clu:all-mx80:all-vsrx 
    gather_facts: no 
    connection: local 
    tags: [format_vars] 

    tasks: 
    - include_vars: 
     file: "{{ formatted_myvar_file }}" 
     ignore_errors: yes 
関連する問題