Unable to add string between variables in Ansible lineinfile module - ansible

I want my filedet.yaml to look like
10.9.75.78: /app/tmp/tmp.log, /vars/tmp/test.out
10.9.55.74: /app/tmp/tmp1.log, /vars/tmp/admin.out
The below works fine and logs the data correctly but when i add ': ' the syntax breaks and I get error
- name: Logging the deployment's file details to a Ansible variable file
local_action: lineinfile line={{ inventory_hostname }}': '{{ vars['fdetails_' + Layer].results|map(attribute='stdout')|list }} path={{ playbook_dir }}/vars/filedets.yaml
Output Error:
The offending line appears to be:
local_action: lineinfile line={{ inventory_hostname }}': '{{ > vars['fdetails_' + Layer].results|map(attribute='stdout')|list > }} path={{ playbook_dir }}/vars/filedets.yaml
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
I also tried this code but it too fails with syntax error:
line="{{ inventory_hostname }}': '{{ vars['fdetails_' + Layer].results|map(attribute='stdout')|list }}" path="{{ playbook_dir }}/vars/filedets.yaml"
Can you please suggest how can I inject the colons and space ': ' between the the variable in line ?

Just wrap the strings you want to insert between the variables in {{ }}
line="{{ inventory_hostname }}{{': '}}{{ vars['fdetails_' + Layer].results|map(attribute='stdout')|list }}" path="{{ playbook_dir }}/vars/filedets.yaml"
If the : colon is a problem you can mask it by using:
line="{{ inventory_hostname }}{{'%c '%58}}{{ vars['fdetails_' + Layer].results|map(attribute='stdout')|list }}" path="{{ playbook_dir }}/vars/filedets.yaml"
58 is the ASCII Code of :.

Related

Ansible play fails with_items FOO

- name: Debug msg for imagepull {{ ansible_operator_meta.name }}
debug:
msg: "{{ final_resource_checks_pod_status_check_filtered_image }}"
I got an error with below
- name: Debug msg for imagepull {{ ansible_operator_meta.name }}
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"

How to use ansible when condition when string contains '#'

I am writing playbook to check user principal in kerberos servers. If principal exists it should skip task and if not it should create user principal. I am not sure how to use string with when condition I am trying below but getting errors
"ERROR! Syntax Error while loading YAML.
expected <block end>, but found '<scalar>'
The error appears to be in '/home/revyas/RHELProjects/Atlas/eda-datalake/playbooks/provision-emr.yml': line 42, column 31, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
stat:
path: "{{ user_dir }}"/"{{ keytab_name }}"
^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
Playbook:
- name: Check if user principals exist
command: 'kadmin -w "{{ emr_kdc_admin_password }}" -p kadmin/admin listprincs'
register: user_princs
delegate_to : "{{ emr_kerberos_master }}"
tags: "emr_acct"
- name: Create user kerberos principal if not exist
command: 'kadmin -w {{ emr_kdc_admin_password }} -p kadmin/admin addprinc -randkey {{ kerberos_username }}#{{ emr_kerberos_realm }}'
when: "{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout
delegate_to: "{{ emr_kerberos_master }}"
tags: "emr_acct"
User principal from kdc have format given below:
emr-test1-aren-reetika#abd.xyz.com
emr-test-aren#bd.xyz.com
emr-test-integration-test#bd.xyz.com
For the first cited issue, yaml doesn't behave like python or shell which automatically concatenate string literals together
You'll want:
stat:
path: "{{ user_dir }}/{{ keytab_name }}"
And the second error is because yaml believes the leading " is the start of a YAML literal, but in fact it's the start of a Jinja2 literal, thus:
when: '"{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout'
Or you can use any of the scalar folding syntaxes, if you prefer that:
when: >-
"{{ kerberos_username }}#{{ emr_kerberos_realm }}"
not in user_princs.stdout
when: "{{ kerberos_username }}#{{ emr_kerberos_realm }}" not in user_princs.stdout
change to
when: "{{ kerberos_username }}\\#{{ emr_kerberos_realm }}" not in user_princs.stdout

How to register with_items and act on conditional check result for each item

I'd like to register the contents of bashrc for two users and edit as/if required. My play is as follows.
- name: Check bashrc
shell: cat {{ item }}/.bashrc
register: bashrc
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Configure bashrc
shell:
cmd: |
cat >> {{ item }}/.bashrc <<EOF
STUFF
EOF
with_items:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
when: '"STUFF" not in bashrc.stdout'
It fails as follows:
fatal: [ca-o3lscizuul]: FAILED! => {"failed": true, "msg": "The conditional check '\"STUFF\" not in bashrc.stdout' failed. The error was: error while evaluating conditional (\"STUFF\" not in bashrc.stdout): Unable to look up a name or access an attribute in template string ({% if \"STUFF\" not in bashrc.stdout %} True {% else %} False {% endif %}).\nMake sure your variable name does not contain invalid characters like '-': argument of type 'StrictUndefined' is not iterable\n\nThe error appears to have been in '/root/openstack-ci/infrastructure-setup/staging/zuul/create-user.yml': line 35, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Configure bashrc\n ^ here\n"}
I think, if I understand your requirement correctly, you can use the 'lineinfile' or 'blockinfile' modules and save yourself the hassle of testing for the existence of the content:
- name: Noddy example data
set_fact:
single_line: "STUFF"
multi_line: |
STUFF
STUFF
profile_dirs:
- "{{ nodepool_home }}"
- "{{ zuul_home }}"
- name: Ensure STUFF exists in file
lineinfile:
path: "{{ item }}/.bashrc"
line: "{{ single_line }}"
loop: "{{ profile_dirs }}"
- name: Ensure block of STUFF exists in file
blockinfile:
path: "{{ item }}/.bashrc"
block: "{{ multi_line }}"
loop: "{{ profile_dirs }}"
Both modules give a lot more control and you can find their docs here: lineinfile | blockinfile

Ansible condition on dictionary item

I have one dictionary list defined:
members_list:
any:
name: any
username: any
anyone:
name:
username: anyone
In my Ansible playbook, I am running multiple docker containers:
docker_container:
name: "{{ item.key }}"
when: "{{ item.key }} != any"
with_dict: "{{ members_list }}"
But I am getting following error:
The conditional check '{{ item.key }} != any' failed. The
error was: error while evaluating conditional ({{ item.key
}} != any): 'any' is undefined
When I run the playbook without when conditional operator it works fine.
Thanks in advance.
You need to quote the word any, because otherwise it is interpreted as a variable reference. Also, you don't need Jinja templating markers in a when expression (the expression is already evaluated as a jinja expression):
- docker_container:
name: "{{ item.key }}"
when: "item.key != 'any'"
with_dict: "{{ members_list }}"
I find nested quotes like this can be confusing, and often opt for one
of YAMLs alternative quoting mechanisms, e.g.:
- docker_container:
name: "{{ item.key }}"
when: >-
item.key != 'any'
with_dict: "{{ members_list }}"
This is identical to the previous version; I just find it easier to
read and understand.

Ansible playbook, difficults with with_items multiples vars

I use ansible to configure a server. I have to see if some line exist and if I have to change them so I use lineinfile module. To have a code more clean I would use with_items like this:
- name: Postegresql configuration
lineinfile: dest={{ item.dest }} line={{ item.line }} regexp={{ item.regexp }}
with_items:
- { dest: '/var/lib/pgsql/data/postgresql.conf', line: 'port = 5433', regexp: '^port =' }
- { dest: '/var/lib/pgsql/data/postgresql.conf', line: 'log_truncate_on_rotation = on', regexp: '^log_truncate_on_rotation =' }
- { dest: '/var/lib/pgsql/data/postgresql.conf', line: 'log_rotation_age = 1d', regexp: '^log_rotation_age =' }
- { dest: '/var/lib/pgsql/data/postgresql.conf', line: 'log_rotation_size = 0MB', regexp: '^log_rotation_size =' }
notify: restart postgresql
tags: verif
But it doesn't work. I he=ave this error:
a duplicate parameter was found in the argument string ()
I this it's a syntax error, can you help me ?
Try putting quotes around any inserted variables that you use. This will ensure that they are treated as a whole together and get parsed as you intend.
lineinfile: dest="{{ item.dest }}" line="{{ item.line }}" regexp="{{ item.regexp }}"

Resources