ansible conditional check a item's attribute exist - ansible

I want to create users using ansible and want to set their shell and sudo permissions.
Now I have vars/main.yml as below:
users: [{'name': 'user1', 'shell': '/bin/bash', 'sudo': 'user1 ALL=(ALL) NOPASSWD: ALL'}, {'name': 'user2', 'shell': '/bin/zsh', 'sudo': 'user2 ALL=NOPASSWD:/bin/systemctl *start nginx'}, {'name': 'user3', 'shell': '/bin/fish'}]
On the task Set sudo permission for users
because not every user have sudo permission, which I need to check if the sudo attribute is exist or not.
- name: Set sudo permission for users
lineinfile:
dest: /etc/sudoers
state: present
regexp: '^{{ item.name }}'
line: "{{ item.sudo }}"
backup: true
when: "{{ item.sudo }}"
with_items:
- "{{ users }}"
I got error as below:
TASK [createUsers : Set sudo permission for users] ***************************
fatal: [ubuntu]: FAILED! => {"failed": true, "msg": "The conditional check '{{ item.sudo }}' failed. The error was: expected token 'end of statement block', got 'ALL'\n line 1\n\nThe error appears to have been in '/Users/csj/proj/roles/createUsers/tasks/main.yml': line 26, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Set sudo permission for users\n ^ here\n"}
I tried many about quote things but it didn't help.

It should work
when: item.sudo is defined
so the task is
- name: Set sudo permission for users
lineinfile:
dest: /etc/sudoers
state: present
regexp: '^{{ item.name }}'
line: "{{ item.sudo }}"
backup: true
when: item.sudo is defined
with_items:
- "{{ users }}"

Related

Ansible ERROR! unexpected parameter type in action:

I try to run a role/task, but i cant solve the following error:
ERROR! unexpected parameter type in action: <class 'ansible.parsing.yaml.objects.AnsibleSequence'>
The error appears to be in '/home/<user>/ansible/ilias6/roles/keysAndUsers/tasks/main.yaml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---
- name: createUser and add to sudoer
^ here
This is my task:
---
- name: createUser and add to sudoer
become: yes
vars_files:
- /home/<user>/ansible/ilias6/roles/keysAndUsers/lists/userCreateList.yaml
user:
name: "{{ item }}"
groups: "sudo, www-data"
password: "{{ 'password' | password_hash('sha512', 'mysecretsalt') }}"
update_password: on_create
state: present
shell: /bin/bash
system: no
createhome: yes
loop: "{{ users }}"
register: useradd
- name: change user password upon creation
shell: chage -d 0 "{{ item.name }}"
loop: "{{ useradd.results }}"
when: item.changed
I noticed, if I comment out the section vars_files its fine. But i need the extern variables unfortunately

Ansible: What's wrong with my "with_itmes" in playbook

I register 3 hosts key and try to loop my host let another remote host save the key
- setup:
- name: Generate Public Key On 3nodes
openssh_keypair:
path: /root/.ssh/id_rsa
comment: "{{ ansible_hostname }}"
when: inventory_hostname in groups['new_percona']
- name: register public key
shell: cat /root/.ssh/id_rsa.pub
register: public_key
when: inventory_hostname in groups['new_percona']
- name: Add Nodes Public Key On master-0
lineinfile:
dest: /root/.ssh/authorized_keys
line: "{{ hostvars['{{ item }}']['public_key']['stdout'] }}"
with_items:
- percona-0
- percona-1
- percona-2
when: '"master-0" in inventory_hostname'
and the result
TASK [Install : Add Nodes Public Key On master-0] ******************************
fatal: [master-0]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['{{ item }}']\" is undefined\n\nThe error appears to be in '/tmp/awx_5004_1s769t9j/project/roles/Install/tasks/install-percona.yml': line 62, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Add Nodes Public Key On master-0\n ^ here\n"}
I also try
- name: Add Nodes Public Key On master-0
lineinfile:
dest: /root/.ssh/authorized_keys
line: "{{ hostvars['{{ groups[new_percona] }}']['public_key']['stdout'] }}"
when: '"master-0" in inventory_hostname'
or loop
- name: Add Nodes Public Key On master-0
lineinfile:
dest: /root/.ssh/authorized_keys
line: "{{ hostvars['{{ item }}']['public_key']['stdout'] }}"
loop: [ 'percona-0', 'percona-1', 'percona-2' ]
when: '"master-0" in inventory_hostname'
But above are wrong
How to use variable to loop the host?
this is working if just single host
- name: Add Nodes Public Key On master-0
lineinfile:
dest: /root/.ssh/authorized_keys
line: "{{ hostvars['percona-0']['public_key']['stdout'] }}"
when: '"master-0" in inventory_hostname'
You cannot use curly braces inside curly braces.
line: "{{ hostvars[item]['public_key']['stdout'] }}"
This should do what you want.

Ansible Read csv file and encrypt passwords, output of command to file

I have a csv file containing ip addresses and passwords. These passwords need to be encrypted and written to a file.
This is what I have tried so far:
- name: Read csv file
read_csv:
path: files/ww.csv
fieldnames: ip,password
delimiter: ','
register: routers
delegate_to: localhost
- name: encrypt password
command: "ansible-vault encrypt_string --vault-password-file password '{{ router.password }}' --name 'password'"
loop: "{{ routers.list }}"
loop_control:
loop_var: router
register: "output"
delegate_to: localhost
- name: write file
copy:
content: "{{ output.stdout }}"
dest: "/tmp/{{ router.ip }}.yaml"
loop: "{{ routers.list }}"
loop_control:
loop_var: router
delegate_to: localhost
I want to use output.stdout but I get the following error:
TASK [robustel : write file] *********************************************************************************************************************************
fatal: [10.41.1.161]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'stdout'\n\nThe error appears to be in '/ansible/roles/routers/tasks/create_var_files.yaml': line 20, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: write file\n ^ here\n"}
How can I solve this?
You are registering a variable on a task with a loop. This changes the structure of the data as described in the documentation. Debugging output would have given you a clue.
output.results is a list where each element contains a stdout key (e.g. the first one being output.results.0.stdout). Moreover, each element also contains an item key containing the original element in the loop that was registered.
Modifying your last task like below should give you the expected result:
- name: write file
copy:
content: "{{ output_result.stdout }}"
dest: "/tmp/{{ output_result.item.ip }}.yaml"
loop: "{{ output.results }}"
loop_control:
loop_var: output_result
delegate_to: localhost

Using Ansible loop to create multiple users: Undefined error

I am using the following ansible code to create multiple unix user accounts
---
- hosts: test
become: true
tasks:
- name: more complex items to add several users
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
groups: "{{ item.groups }}"
state: present
with_items: "{{ user_details }}"
I am storing the user information by using a separate a variable file as below
`cat /etc/ansible/vars.yml
---
user_details:
- { name: testuser1, uid: 1002, groups: "admin, logs" }
- { name: testuser2, uid: 1003, groups: logs: }`
To execute above playbook , I tried with both the commands below
sudo ansible-playbook /etc/ansible/userloop.yml -e /etc/ansible/vars.yml
sudo ansible-playbook /etc/ansible/userloop.yml
but both commands are failing with below error
fatal: [host-003]: FAILED! => {"msg": "'user_details' is undefined"}
fatal: [host-004]: FAILED! => {"msg": "'user_details' is undefined"}
How to resolve the issue ? I want to maintain a separate variable file to store the user information rather then putting them in the same playbook file .
You can also refer the multiple variable files in playbooks like below
- hosts: all
become: true
vars_files:
- /etc/ansible/vars.yml
tasks:
- name: more complex items to add several users
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
groups: "{{ item.groups }}"
state: present
with_items: "{{ user_details }}"
The type of variables is in the column "Parameter" of the module user. Try the structure of the data below
user_details:
- {name: 'testuser1', uid: 1002, groups: ['admin', 'logs']}
- {name: 'testuser2', uid: 1003, groups: ['logs']}
You are missing # while passing the vars.yml. Hence, the ansible is not reading the file. Try the below command. It works for me.
sudo ansible-playbook /etc/ansible/userloop.yml -e #/etc/ansible/vars.yml

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

Resources