I am working with nested dicts and have multiple dictionary files with identical key's. The dict and task itself is working, but I need to add the following condition. Dont run the task, if the subelement's state == absent
My dict:
qualitygate:
- qualitygate_name: QA-dev
operators:
- metric: coverage
operator: CT
error: 1
state: present
- qualitygate_name: Department-xyc
operators:
- metric: coverage
operator: CT
error: 10
state: absent
- metric: duplicated_lines
operator: GT
error: 5
state: present
Using my task:
- ansible.builtin.uri:
url: "{{ protocol }}://{{ server_fqdn }}/api/qualitygates/create_condition"
user: "{{ token }}"
method: POST
body_format: form-urlencoded
body:
error: "{{ item.1.error }}"
metric: "{{ item.1.metric }}"
gateName: "{{ item.0.qualitygate_name }}"
op: "{{ item.1.operator }}"
loop: "{{ qualitygate | subelements('operators', 'skip_missing=True') }}"
when: qualitygate[item]['state'] is match("present")
How can I change the filter to only match the value "present"
The issue here is that item
in your loop is not a single value. If you perform some simple diagnostics, like this:
- loop: "{{ qualitygate | subelements('operators', 'skip_missing=True') }}"
debug:
msg: "{{ item }}"
You'll see that item
looks like this:
[
{
"operators": [
{
"error": 1,
"metric": "coverage",
"operator": "CT",
"state": "present"
}
],
"qualitygate_name": "QA-dev"
},
{
"error": 1,
"metric": "coverage",
"operator": "CT",
"state": "present"
}
]
This is described in the documentation:
The ansible.builtin.subelements filter produces a product of an object and the subelement values of that object, similar to the ansible.builtin.subelements lookup. This lets you specify individual subelements to use in a template. For example, this expression:
You want to use the second value in item
-- which for each iteration represents a value from one of the operators
lists -- in your conditional. That gives you something like this:
- ansible.builtin.uri:
url: "{{ protocol }}://{{ server_fqdn }}/api/qualitygates/create_condition"
user: "{{ token }}"
method: POST
body_format: form-urlencoded
body:
error: "{{ item.1.error }}"
metric: "{{ item.1.metric }}"
gateName: "{{ item.0.qualitygate_name }}"
op: "{{ item.1.operator }}"
loop: "{{ qualitygate | subelements('operators', 'skip_missing=True') }}"
when: item.1.state == "present"
If we wrap everything in a debug
task, like this:
- debug:
msg:
ansible.builtin.uri:
url: "{{ protocol }}://{{ server_fqdn }}/api/qualitygates/create_condition"
user: "{{ token }}"
method: POST
body_format: form-urlencoded
body:
error: "{{ item.1.error }}"
metric: "{{ item.1.metric }}"
gateName: "{{ item.0.qualitygate_name }}"
op: "{{ item.1.operator }}"
loop: "{{ qualitygate | subelements('operators', 'skip_missing=True') }}"
when: item.1.state == "present"
That gives us:
TASK [debug] **********************************************************************************************************************************************
ok: [localhost] => (item=[{'qualitygate_name': 'QA-dev', 'operators': [{'metric': 'coverage', 'operator': 'CT', 'error': 1, 'state': 'present'}]}, {'metric': 'coverage', 'operator': 'CT', 'error': 1, 'state': 'present'}]) => {
"msg": {
"ansible.builtin.uri": {
"body": {
"error": "1",
"gateName": "QA-dev",
"metric": "coverage",
"op": "CT"
},
"body_format": "form-urlencoded",
"method": "POST",
"url": "https://www.example.com/api/qualitygates/create_condition",
"user": "mytoken"
}
}
}
skipping: [localhost] => (item=[{'qualitygate_name': 'Department-xyc', 'operators': [{'metric': 'coverage', 'operator': 'CT', 'error': 10, 'state': 'absent'}, {'metric': 'duplicated_lines', 'operator': 'GT', 'error': 5, 'state': 'present'}]}, {'metric': 'coverage', 'operator': 'CT', 'error': 10, 'state': 'absent'}])
ok: [localhost] => (item=[{'qualitygate_name': 'Department-xyc', 'operators': [{'metric': 'coverage', 'operator': 'CT', 'error': 10, 'state': 'absent'}, {'metric': 'duplicated_lines', 'operator': 'GT', 'error': 5, 'state': 'present'}]}, {'metric': 'duplicated_lines', 'operator': 'GT', 'error': 5, 'state': 'present'}]) => {
"msg": {
"ansible.builtin.uri": {
"body": {
"error": "5",
"gateName": "Department-xyc",
"metric": "duplicated_lines",
"op": "GT"
},
"body_format": "form-urlencoded",
"method": "POST",
"url": "https://www.example.com/api/qualitygates/create_condition",
"user": "mytoken"
}
}
}
Which I think demonstrates exactly what you want.