简体   繁体   中英

Problems with Jinja2 and ansible making a sub dict

I need to read a csv file with diferent IPs and make a dictionary with a jinja2 filter for modificate the IP depending the IPNumber value. The yml file is like:

- read_csv:
    path: vms.csv
    key: Number
    fieldnames: Name,IP1,IP2,IP3,IP4,IPNumber 
    delimiter: ';'
  register: vms

- name: vms to dict
  debug:
    msg:
      - {{'Name':{{ item.value.Name }},
          {% if item.value.IPNumber == "1" %}
          'IP':{{ item.value.IP1 }},
          {% endif %}
          {% if item.value.IPNumber ==  "2"%}
          'IP':{{ item.value.IP2 }},
          {% endif %}
          {% if item.value.IPNumber ==  "3"%}
          'IP':{{ item.value.IP3 }},
          {% endif %}
          {% if item.value.IPNumber ==  "4"%}
          'IP':{{ item.value.IP4 }},
          {% endif %}}}
  loop: "{{ vms.dict | dict2items }}"
  register: vms2

But I get the error:

The error appears to be in '/etc/ansible/roles/vms.yml': line 17, column 16, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

              'Name':{{ item.value.Name}},
              {% if item.value.IPNumber == "1" %}
               ^ here

I know is a syntax problem but I dont guess where the problem is.

I need some help.

You should put only variables/expressions within {{ or {% . To me 'Name' looks like normal text and should be outside.

Example:

# Notice the quotes `"` symbol at the beginning and end of debug message

- debug:
    msg:
    - "Name: {{ item.value.Name }},
       {% if item.value.IPNumber == "1" %}
       IP: {{ item.value.IP1 }}
        # and so on... 
       {% endif %}"

This at least should address the error message.

The following task should create your dictionary as per your requirement inside a var you can reuse elsewhere. Rename my_ip_dict to whatever suits your project better.

- name: Create my IP dictionary
  set_fact:
    my_ip_dict: >-
      {{
        my_ip_dict | default({})
        | combine({item.value.Name: item.value['IP' + item.value.IPNumber]})
      }}
  loop: "{{ vms.dict | dict2items }}"

- name: Check the result:
  debug:
    var: my_ip_dict

Note that I have dropped all the if/else structures by calling directly the correct field depending on IPNumber . I took for granted it always has a value in the valid scope or the other existing IP* fields. If this is not the case, you can always default that value eg item.value['IP' + item.value.IPNumber] | default('N/A') item.value['IP' + item.value.IPNumber] | default('N/A')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM