0

I am trying to get data from json data (below) using a loop with a variable (instead of hard coding a value). In the json data (below), 'cluster' can change therefore I cannot simply use: loop: "{{ drs_rule_jsondata.drs_rule_info.cluster }}" -- which works as I expect it would and produces the expected results.

However, when I use the play below (using vars in the loop and when {{ cluster_info.name }} = cluster), I get "msg": "'dict object' has no attribute 'drs_rule_jsondata.drs_rule_info.cluster'". The confusing part is, it produces the same syntax as the one that works.... should using vars this way in the loop not work? Is there another way to get the expected results given the 'cluster' can change?

Play:

- name: Set drs rule info
  set_fact:
    drs_rule: "{{ drs_rule|default([]) + [ {
      'rule_name': item | json_query('rule_name'),
      'rule_affinity': item | json_query('rule_affinity'),
      'rule_vms': item | json_query('rule_vms[*]')
      } ] }}"
  vars:
    path: drs_rule_jsondata.drs_rule_info
    cluster_name: "{{ cluster_info.name }}"
  loop: "{{ vars[path + '.' + cluster_name] }}"

json data:

{
  "ansible_facts": {
    "drs_rule_jsondata": {
      "changed": false,
      "drs_rule_info": {
        "cluster": [
          {
            "rule_affinity": true,
            "rule_enabled": true,
            "rule_key": 1,
            "rule_mandatory": null,
            "rule_name": "DEMO_REP_DRS_1",
            "rule_type": "vm_vm_rule",
            "rule_uuid": "522d41eb-4acb-afbf-9f37-15a1651ccf45",
            "rule_vms": [
              "VM1",
              "VM2",
              "VM3",
              "VM4"
            ]

        ]
      },
      "failed": false
    }
  },
  "_ansible_no_log": false,
  "changed": false
}

Expected results:

{
  "drs_rule": [
    {
      "rule_name": "DEMO_REP_DRS_1",
      "rule_affinity": true,
      "rule_vms": [
        "VM1",
        "VM2",
        "VM3",
        "VM4"
      ]
    }
  ]
}
larsks
  • 43,623
  • 14
  • 121
  • 180
BrillCom
  • 139
  • 2
  • 9

2 Answers2

0

This expression doesn't make sense:

vars[path + '.' + cluster_name]

Here you're asking for a variable with the literal name drs_rule_jsondata.drs_rule_info.<value of cluster_name>, but there is no such variable -- that's not even a valid variable name.

You don't need to use vars here in any case; you can just refer to the top-level dns_rule_jsondata variable directly.

It's also not clear why you're using json_query in your playbook, since you're only asking for individual, static keys.

I think what you're trying to do is this:

- hosts: localhost
  gather_facts: false
  vars:
    cluster_info:
      name: cluster
    drs_rule_jsondata:
      changed: false
      drs_rule_info:
        cluster:
          - rule_affinity: true
            rule_enabled: true
            rule_key: 1
            rule_mandatory: null
            rule_name: DEMO_REP_DRS_1
            rule_type: vm_vm_rule
            rule_uuid: 522d41eb-4acb-afbf-9f37-15a1651ccf45
            rule_vms:
              - VM1
              - VM2
              - VM3
              - VM4

  tasks:
  - name: Set drs rule info
    set_fact:
      drs_rule: >-
        {{
           drs_rule + [
             {
            'rule_name': item.rule_name,
            'rule_affinity': item.rule_affinity,
            'rule_vms': item.rule_vms
            }
          ]
        }}
    vars:
      drs_rule: []
      cluster_name: "{{ cluster_info.name }}"
    loop: "{{ drs_rule_jsondata.drs_rule_info[cluster_name] }}"

  - debug:
      var: drs_rule

Running the above playbook produces as output:


PLAY [localhost] ***************************************************************

TASK [Set drs rule info] *******************************************************
ok: [localhost] => (item={'rule_affinity': True, 'rule_enabled': True, 'rule_key': 1, 'rule_mandatory': None, 'rule_name': 'DEMO_REP_DRS_1', 'rule_type': 'vm_vm_rule', 'rule_uuid': '522d41eb-4acb-afbf-9f37-15a1651ccf45', 'rule_vms': ['VM1', 'VM2', 'VM3', 'VM4']})

TASK [debug] *******************************************************************
ok: [localhost] => {
    "drs_rule": [
        {
            "rule_affinity": true,
            "rule_name": "DEMO_REP_DRS_1",
            "rule_vms": [
                "VM1",
                "VM2",
                "VM3",
                "VM4"
            ]
        }
    ]
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
larsks
  • 43,623
  • 14
  • 121
  • 180
  • Thanks for your help, larsks. Here is where I got the idea to try to use vars: https://stackoverflow.com/questions/29276198/ansible-how-to-construct-a-variable-from-another-variable-and-then-fetch-its-v. Using your playbook gave me: {"msg": "Unexpected templating type error occurred on ({{ drs_rule|default([]) + [ { 'rule_name': item.rule_name, 'rule_affinity': item.rule_affinity, 'rule_vms': item.rule_vms } ] }}): can only concatenate str (not \"list\") to str"}. And I don't uderstand the point of using drs_rules: []. Neverthless, I got there with your help so thank you. – BrillCom Dec 12 '22 at 21:00
  • The point of setting `drs_rules: []` in the `vars:` section of the task is that it lets us drop the use of the `default` filter in `set_fact`. The playbook I've posted here runs without errors (and produces the output shown in the answer). – larsks Dec 12 '22 at 21:06
  • Ah, kinda figured it was the same as using default in set_fact. And I'm going to guess why your playbook worked for you but not me, is because I am pulling from json and your vars are not json. Again, thanks for your help. – BrillCom Dec 12 '22 at 21:27
0

Here is what ultimately worked in the end (which I though I had already tried):

              set_fact:
                drs_rule: "{{ drs_rule|default([]) + [ {
                  'rule_name': item | json_query('rule_name'),
                  'rule_affinity': item | json_query('rule_affinity'),
                  'rule_vms': item | json_query('rule_vms[*]')
                  } ] }}"
              vars:
                cluster_name: "{{ cluster_info.name }}"
              loop: "{{ drs_rule_jsondata.drs_rule_info[cluster_name] }}"
BrillCom
  • 139
  • 2
  • 9