Ansible - looping over dynamically generated list items [duplicate] - list

I have an Ansible playbook like the one below, I want use nested variable like this:
msg={{{{Component}}.community_release_num}}, but when I run playbook:
ansible-playbook vartest.yml -e 'version=version_402', it not work
[es#vpn-server nested-var]$ tree
.
├── vars
│   ├── horizon.yml
│   └── version_402.yml
└── vartest.yml
1 directory, 3 files
[es#vpn-server nested-var]$ cat vartest.yml
---
- name: test
hosts: localhost
vars_files:
- vars/{{version}}.yml
tasks:
- debug: msg={{{{Component}}.community_release_num}}
- debug: msg={{{{Component}}.release_num}}
[es#vpn-server nested-var]$ cat vars/horizon.yml
Component: horizon
[es#vpn-server nested-var]$ cat vars/version_402.yml
- horizon:
community_release_num: '9.0.1'
release_num: '4.0.2'
[es#vpn-server nested-var]$
error messages
[es#vpn-server nested-var]$ ansible-playbook vartest.yml -e 'version=version_402'
/usr/lib64/python2.6/site-packages/cryptography/__init__.py:25: DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python.
DeprecationWarning
PLAY [test] *******************************************************************************************************
/usr/lib64/python2.6/site-packages/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
_warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
TASK [debug] ******************************************************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "template error while templating string: expected token 'colon', got '}'. String: {{{{Component}}.community_release_num}}"}
to retry, use: --limit #/data/wangqian/artemis-code-test/artemis/ansible/update/nested-var/vartest.retry
PLAY RECAP ********************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1
Can Ansible use nested variable, if yes, how to use it?

Per Ansible FAQ:
Another rule is ‘moustaches don’t stack’. We often see this:
{{ somevar_{{other_var}} }}
The above DOES NOT WORK, if you need to use a dynamic variable use the
hostvars or vars dictionary as appropriate:
{{ hostvars[inventory_hostname]['somevar_' + other_var] }}
So in your case:
- debug: msg={{hostvars[inventory_hostname][Component].community_release_num}}
Or:
- debug: msg={{vars[Component].community_release_num}}
Or (since Ansible 2.5):
- debug: msg={{(lookup('vars', Component)).community_release_num}}

Run this command:
ansible-playbook 1_lambda-facts.yml -e "func_name=mylambdaFunctionName"
- name: get lamda Info
hosts: localhost
connection: local
become: yes
gather_facts: true
tasks:
- name: List all for a specific function
lambda_facts:
query: all
function_name: "{{func_name}}"
- name: debug info
debug:
msg: "{{lambda_facts}}"
msg: "variable name is: {{vars['func_name']}}"
msg: "{{lambda_facts['function'][vars['func_name']]['function_arn']}}"

Related

How can I use regex in when condition

On an Ansible playbook, I'm trying to execute a shell command only if a service exist on the remote server.
I have 3 tasks :
service_facts
execution of shell command if tomcat is installed
display the output of the shell command if tomcat is installed
Here is my code :
- name: Get Infos
hosts: all
gather_facts: yes
become: false
remote_user: [MY_USER]
tasks:
- name: Get the list of services
service_facts:
- name: Get version of Tomcat if installed
become: true
shell: 'java -cp /opt/tomcat/lib/catalina.jar org.apache.catalina.util.ServerInfo | grep "Server version"'
register: tomcat_version
when: "'tomcat.service' in services"
- debug: msg="{{ tomcat_version.stdout_lines }}"
when: "'tomcat.service' in services"
The problem is on certains servers the service name is, for example, tomcat-8.1
How can i use regex in the when condition?
I tried regex(), regex_search(), either I'm doing it wrong or I don't know how to do it.
Have you any idea how to do it?
Thanks in advance!
Count matching items. For example
- service_facts:
- block:
- shell: smartctl --version | head -1
register: smart_version
- debug:
msg: "{{ smart_version.stdout_lines }}"
when: _srvcs|length > 0
vars:
_regex: '.*smart.*'
_srvcs: "{{ services|select('match', _regex) }}"
gives
msg:
- smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.4.0-73-generic] (local build)
The next option is to intersect the list of services, e.g.
when: _srvcs|length > 0
vars:
my_services:
- smartmontools.service
- smart-8.1
- smart-devel.0.0.1
_srvcs: "{{ my_services|intersect(services) }}"
Debug
Q: "It gives me a failure on the server where my service doesn't exist, cause the playbook still tries to execute the shell. Is it normal?"
A: No. It is not normal. Print debug and find out why the condition evaluates to true, i.e. what service(s) match either the regex or the list. For example
- debug:
msg: |
_srvcs:
{{ _srvcs|to_nice_yaml|indent(2) }}
when: debug|d(false)|bool
vars:
my_services:
- smartmontools.service
- smart-8.1
- smart-devel.0.0.1
_srvcs: "{{ my_services|intersect(services) }}"
gives
msg: |-
_srvcs:
- smartmontools.service
To enable the task run the playbook with the option -e debug=true.

ANSIBLE - getting output from command and assign to ansible replace command

I'm trying to get the value of value.txt which I think works well in ansible, the file value looks exactly like this
[ec2-user#ip-192-168-1-45]$ cat value.txt
this-is-the-value
I would like to assign the output value as the replacement of the "CHANGE_ME" keywords from file.txt
[ec2-user#ip-192-168-1-45]$ cat file.txt
asdasdh kajsdlkjasdlk CHANGE_ME ajsdlkjasdlkjasd
asdkjhakjsd: CHANGE_ME
jasdlkjadsl{
aksldjlkasd: CHANGE_ME
}
I'm using this ansible playbook to combine the 2 process however it seems it doesn't replace the the "CHANGE_ME" when I try to verify the file.txt
- name: check output
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: cat the file
shell: "cat value.txt"
register: cat_value
- debug: var=cat_value.stdout
- name: modify file.txt
replace:
regexp: "{{ cat_value.stdout }}"
replace: "CHANGE_ME"
path: "{{ playbook_dir }}/file.txt"
The OUTPUT goes like this
[ec2-user#ip-192-168-1-45]$ ansible-playbook ansible.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [check output] ******************************************************************************************************************************************************************************
TASK [cat the file] ******************************************************************************************************************************************************************************
changed: [localhost]
TASK [debug] *************************************************************************************************************************************************************************************
ok: [localhost] => {
"cat_value.stdout": "this-is-the-value"
}
TASK [modify file.txt] ***************************************************************************************************************************************************************************
ok: [localhost]
PLAY RECAP ***************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ec2-user#ip-192-168-1-45]$ cat file.txt
asdasdh kajsdlkjasdlk CHANGE_ME ajsdlkjasdlkjasd
asdkjhakjsd: CHANGE_ME
jasdlkjadsl{
aksldjlkasd: CHANGE_ME
}

Adding paths to config file in most efficent way via Ansible

I wrote a task that is responsible for changing supervisor config file. The case is that on some servers we have more than one app running workers, so sometimes more than one path needs to be added to include section of supervisor.conf.
Currently I wrote this task in /roles/supervisor/tasks/main.yml/:
- name: Add apps paths in include section
lineinfile:
dest: /etc/supervisor/supervisord.conf
regex: '^files ='
line: 'files = /etc/supervisor/conf.d/*.conf /home/app/{{ app_name }}/releases/app/shared/supervisor/*.conf /home/dev/{{ app_name2 }}/releases/dev/shared/supervisor/*.conf'
when: ansible_hostname = 'ser-db-10'
notify: restart supervisor
tags: multi_workers
... and added in /roles/supervisor/defaults/main.yml/ this:
app_name: bla
app_name2: blabla
It works, but I don't like the thing that there are two application paths hardcoded in line and maybe I should also add variable in place of ser-db-10.
I am wondering how to rebuild this task to make it more independent.
What I mean is, if there are 4 apps, add 4 paths, if there are 2 apps, add 2 paths.
What is the most efficient way to do this?
As an example of how to put together the parameter line, the play below
- hosts: test_01
vars:
app_name1: A
app_name2: B
my_conf:
test_01:
lines:
- '/etc/*.conf'
- '/etc/{{ app_name1 }}/*.conf'
- '/etc/{{ app_name2 }}/*.conf'
tasks:
- debug:
msg: "files = {{ my_conf[inventory_hostname].lines|join(' ') }}"
gives
"msg": "files = /etc/*.conf /etc/A/*.conf /etc/B/*.conf"
With appropriate dictionary my_conf the task below should do the job
- name: Add apps paths in include section
lineinfile:
dest: /etc/supervisor/supervisord.conf
regex: '^files ='
line: "files = {{ my_conf[inventory_hostname].lines|join(' ') }}"
notify: restart supervisor
tags: multi_workers
(not tested)

How to use ansible nested variables in jinja2 with regular expressions and replace [duplicate]

I have an Ansible playbook like the one below, I want use nested variable like this:
msg={{{{Component}}.community_release_num}}, but when I run playbook:
ansible-playbook vartest.yml -e 'version=version_402', it not work
[es#vpn-server nested-var]$ tree
.
├── vars
│   ├── horizon.yml
│   └── version_402.yml
└── vartest.yml
1 directory, 3 files
[es#vpn-server nested-var]$ cat vartest.yml
---
- name: test
hosts: localhost
vars_files:
- vars/{{version}}.yml
tasks:
- debug: msg={{{{Component}}.community_release_num}}
- debug: msg={{{{Component}}.release_num}}
[es#vpn-server nested-var]$ cat vars/horizon.yml
Component: horizon
[es#vpn-server nested-var]$ cat vars/version_402.yml
- horizon:
community_release_num: '9.0.1'
release_num: '4.0.2'
[es#vpn-server nested-var]$
error messages
[es#vpn-server nested-var]$ ansible-playbook vartest.yml -e 'version=version_402'
/usr/lib64/python2.6/site-packages/cryptography/__init__.py:25: DeprecationWarning: Python 2.6 is no longer supported by the Python core team, please upgrade your Python.
DeprecationWarning
PLAY [test] *******************************************************************************************************
/usr/lib64/python2.6/site-packages/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
_warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
TASK [debug] ******************************************************************************************************
fatal: [localhost]: FAILED! => {"failed": true, "msg": "template error while templating string: expected token 'colon', got '}'. String: {{{{Component}}.community_release_num}}"}
to retry, use: --limit #/data/wangqian/artemis-code-test/artemis/ansible/update/nested-var/vartest.retry
PLAY RECAP ********************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1
Can Ansible use nested variable, if yes, how to use it?
Per Ansible FAQ:
Another rule is ‘moustaches don’t stack’. We often see this:
{{ somevar_{{other_var}} }}
The above DOES NOT WORK, if you need to use a dynamic variable use the
hostvars or vars dictionary as appropriate:
{{ hostvars[inventory_hostname]['somevar_' + other_var] }}
So in your case:
- debug: msg={{hostvars[inventory_hostname][Component].community_release_num}}
Or:
- debug: msg={{vars[Component].community_release_num}}
Or (since Ansible 2.5):
- debug: msg={{(lookup('vars', Component)).community_release_num}}
Run this command:
ansible-playbook 1_lambda-facts.yml -e "func_name=mylambdaFunctionName"
- name: get lamda Info
hosts: localhost
connection: local
become: yes
gather_facts: true
tasks:
- name: List all for a specific function
lambda_facts:
query: all
function_name: "{{func_name}}"
- name: debug info
debug:
msg: "{{lambda_facts}}"
msg: "variable name is: {{vars['func_name']}}"
msg: "{{lambda_facts['function'][vars['func_name']]['function_arn']}}"

I want to print the names of files present in a directory as a list using ansible

---
- hosts: localhost
user: root
tasks:
- command: "ls /root/Tmp/Deployment/script_files/Hotfix"
register: dir_out
- debug: msg="The hotfix ids are: {{dir_out.stdout_lines}}"
The output I got was:
but I want it as
The hotfix ids are :["1001","1002"]
How do I do this?
I needed to change: {{dir_out.stdout_lines}} to {{dir_out.stdout_lines|join(',')}}