Reputation: 13
I have a playbook that loops through a shell command for the values in a csv, modifies the results of the shell command with another loop and then prints them with a debug message.
I cannot seem to figure out how to output values from both loops into a single debug task. The tasks doing the work of the playbook are:
#get url certificate
- name: get url certificate
become: false
shell: echo | openssl s_client -showcerts -servername {{ loop_var_openssl_get_certificate_csv.url_base }} -connect {{ loop_var_openssl_get_certificate_csv.url_base }}:{{ loop_var_openssl_get_certificate_csv.url_port }} 2>/dev/null | openssl x509 -inform pem -noout -text
loop: "{{ register_read_csv.list }}"
loop_control:
loop_var: loop_var_openssl_get_certificate_csv
register: register_certificate
#extract cn from certificate
- name: extract cn from certificate
set_fact:
certificate_cn: "{{ item | regex_replace('\\s', '') | regex_search(regex_certificate_cn, '\\2') }}"
loop: "{{ register_certificate.results }}"
register: register_certificate_cn
no_log: true
where the contents of my SCV are:
url_base,url_port
www.google.com,443
www.youtube.com,443
The first attempt at my debug message is looping through loop number 2, so I understand that I'm getting the entirety of loop 1's output, with the debug task looking like this sitting just below the extract cn from certificate
task:
#print detailed list
- name: print detailed list
debug:
msg: "{{ register_read_csv.list }},{{ item.ansible_facts}}"
loop: "{{ register_certificate_cn.results }}"
loop_control:
label: "{{ item.ansible_facts}}"
which outputs the following:
ok: [localhost] => (item={'certificate_cn': ['www.google.com']}) =>
msg:
- - url_base: www.google.com
url_port: '443'
- url_base: www.youtube.com
url_port: '443'
- certificate_cn:
- www.google.com
ok: [localhost] => (item={'certificate_cn': ['*.google.com']}) =>
msg:
- - url_base: www.google.com
url_port: '443'
- url_base: www.youtube.com
url_port: '443'
- certificate_cn:
- '*.google.com'
In the end I would like the msg to read something like:
ok: [localhost] =>
msg:
- - url_base: www.google.com
url_port: 443
certificate_cn: www.google.com
ok: [localhost] =>
msg:
- url_base: www.youtube.com
url_port: 443
certificate_cn: '*.google.com'
but I'm not quite sure how to get both loops' content to output how I'd like it to.
Upvotes: 1
Views: 2975
Reputation: 39139
You can always access the item that was used at the creation of a results
set via the item
property — or the name you gave in the loop_var
parameter — of the items in results
.
So, in your actual trial, you could do something like this (without the need of the set_fact
):
- debug:
msg: >-
{{
item.loop_var_openssl_get_certificate_csv
| combine({
'certificate_cn': item.stdout_lines
| select('contains', 'Subject: CN =')
| first
| replace('Subject: CN =', '')
| trim
})
}}
loop: "{{ register_certificate.results }}"
loop_control:
label: >-
{{ item.loop_var_openssl_get_certificate_csv.url_base }}
{{ item.loop_var_openssl_get_certificate_csv.url_port }}
This said, I would recommend you to reconsider your approach, as, feeding shell commands to Ansible, when there are dedicated modules doing what you need is not the good solution.
Here, the module community.crypto.get_certificate
is exactly what you need, and it formats the certificat information in a dictionary already, so you don't have to process the result of it.
Given the playbook:
- hosts: localhost
gather_facts: no
tasks:
- community.crypto.get_certificate:
host: "{{ item.url_base }}"
port: "{{ item.url_port }}"
loop: "{{ urls }}"
loop_control:
label: "{{ item.url_base }}:{{ item.url_port }}"
register: register_certificate
vars:
urls:
- url_base: www.google.com
url_port: 443
- url_base: www.youtube.com
url_port: 443
- debug:
msg: "{{ item.item | combine({'certificate_cn': item.subject.CN}) }}"
loop: "{{ register_certificate.results }}"
loop_control:
label: "{{ item.item.url_base }}:{{ item.item.url_port }}"
This yields the expected:
TASK [community.crypto.get_certificate] *************************************
ok: [localhost] => (item=www.google.com:443)
ok: [localhost] => (item=www.youtube.com:443)
TASK [debug] ****************************************************************
ok: [localhost] => (item=www.google.com:443) =>
msg:
certificate_cn: www.google.com
url_base: www.google.com
url_port: 443
ok: [localhost] => (item=www.youtube.com:443) =>
msg:
certificate_cn: '*.google.com'
url_base: www.youtube.com
url_port: 443
Upvotes: 1