Getting a list of yum updates via ansible fails - linux

- hosts: all
gather_facts: false
become: yes
user: username
tasks:
- name: List Available Patches (Non-Kernel)
yum:
list: updates
update_cache: true
exclude: kernel*
register: yumoutput
- debug: msg="{{ inventory_hostname}} {{ yumoutput.results }}"
MSG:
Unsupported parameters for (yum) module: register Supported parameters
include: allow_downgrade, bugfix, conf_file, disable_gpg_check,
disable_plugin, disablerepo, enable_plugin, enablerepo, exclude,
install_repoquery, installroot, list, name, security, skip_broken, state,
update_cache, update_only, validate_certs
to retry, use:
ansible --version
ansible 2.6.5
Same issue on 2.7.5 version.

This seems to be an indention error. register has to be on the same column as yum.
- hosts: all
gather_facts: false
become: yes
user: username
tasks:
- name: List Available Patches (Non-Kernel)
yum:
list: updates
update_cache: true
exclude: kernel*
register: yumoutput
- debug: msg="{{ inventory_hostname}} {{ yumoutput.results }}"

Related

Installing ohmyzsh for multiple users using ansible?

I want to install ohmyzsh for a list of users using gantsign.oh-my-zsh role which is available in ansible galaxy gantsign.oh-my-zsh so i have to run this role for users here is my playbook
- name: setup ohmyzsh for users
hosts: all
vars:
userlist:
- username: "viktor"
password: "viktor123"
become: yes
roles:
- role: gantsign.oh-my-zsh
users:
- username: "{{ item.username }}"
oh_my_zsh:
theme: gnzh
plugins:
- git
- zsh-syntax-highlighting
- zsh-autosuggestions
- docker
loop: "{{ userlist }}"
tasks:
but I got this error after running playbook
fatal: [worker1]: FAILED! => {"msg": "[{'username': '{{ item.username }}', 'oh_my_zsh': {'theme': 'gnzh', 'plugins': ['git', 'zsh-syntax-highlighting', 'zsh-autosuggestions', 'docker']}, 'loop': '{{ userlist }}'}]: 'item' is undefined"}
fatal: [worker2]: FAILED! => {"msg": "[{'username': '{{ item.username }}', 'oh_my_zsh': {'theme': 'gnzh', 'plugins': ['git', 'zsh-syntax-highlighting', 'zsh-autosuggestions', 'docker']}, 'loop': '{{ userlist }}'}]: 'item' is undefined"}
fatal: [registry1]: FAILED! => {"msg": "[{'username': '{{ item.username }}', 'oh_my_zsh': {'theme': 'gnzh', 'plugins': ['git', 'zsh-syntax-highlighting', 'zsh-autosuggestions', 'docker']}, 'loop': '{{ userlist }}'}]: 'item' is undefined"}
You can't use loops inside the task level roles: keywords. Use include_role inside your tasks instead (untested example):
- name: setup ohmyzsh for users
hosts: all
vars:
userlist:
- username: "viktor"
password: "viktor123"
become: yes
tasks:
- name: run role for each user
include_role:
name: gantsign.oh-my-zsh
vars:
users:
- username: "{{ item.username }}"
oh_my_zsh:
theme: gnzh
plugins:
- git
- zsh-syntax-highlighting
- zsh-autosuggestions
- docker
loop: "{{ userlist }}"
Answer for the generic looping over ansible roles using include_role.
As for the specific problem, the role expects its list of users as a role variable, so you do not need to loop over the role at all, just pass all users to the role itself, as the oh-my-zsh role docs suggest.
- hosts: all
vars:
oh_my_zsh_defaults:
theme: gnzh
plugins:
- git
- zsh-syntax-highlighting
- zsh-autosuggestions
- docker
roles:
- role: gantsign.oh-my-zsh
users:
- username: "viktor"
oh_my_zsh: oh_my_zsh_defaults
- username: "otheruser"
oh_my_zsh: oh_my_zsh_defaults

Testing a task result which uses a loop?

So the first task is always skipped because RedHat 8 is detected which should trigger the fail module to run but this gets skipped also. Is works fine without the loop though.
- name: installing packages
hosts: ansible2
ignore_errors: true
vars_files: varsfile
tasks:
- name: install software based on OS distro and version
yum:
name: "{{ item.name }}"
state: latest
loop: "{{ packages }}"
when: >
( ansible_distribution == "RedHat" and ansible_distribution_major_version is version('12', '>=') )
or
( ansible_distribution == "CentOS" and ansible_distribution_major_version | int >= 8 )
register: result
- fail:
msg: error {{ ansible_hostname }} does not meet minimum requirements
when: result is skipped
Regarding
So the first task is always skipped because RedHat 8 is detected which should trigger the fail module to run but this gets skipped also.
with a small test setup and a debug task for the variable name to debug
---
- hosts: test.example.com
become: false
gather_facts: true
tasks:
- name: Install software based on OS distro and version
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_major_version }}"
register: result
when: ansible_distribution == "RedHat" and ansible_distribution_major_version is version('12', '>=')
with_items: ['pkg1', 'pkg2']
- name: Show result
debug:
var: result
- fail:
msg: "Error: {{ ansible_hostname }} does not meet minimum requirements"
when: result.results[0].skipped
resulting into an output of
TASK [Gathering Facts] ********************************
ok: [test.example.com]
TASK [Show result] ************************************
ok: [test.example.com] =>
result:
changed: false
msg: All items completed
results:
- ansible_loop_var: item
changed: false
item: pkg1
skip_reason: Conditional result was False
skipped: true
...
TASK [fail] *******************************************
fatal: [test.example.com]: FAILED! => changed=false
msg: 'Error: test does not meet minimum requirements'
you can see that the loop will create a list.
- name: Show result
debug:
var: result.results | type_debug
TASK [Show result] ****************
ok: [test.example.com] =>
result.results | type_debug: list
Therefore you need to set the Conditional to when: result.results[0].skipped.
Regarding
Is works fine without the loop though.
it is recommended to simplify your use case with the following approach
- name: Install software based on OS distro and version
yum:
name: "{{ packages }}"
state: latest
according the yum module Notes
When used with a loop: each package will be processed individually, it is much more efficient to pass the list directly to the name option.
and as it is faster and consumes less resources. Furthermore the result set and conditionals are less complex.

Ansible playbook loop with with_items

I have to update sudoers.d multiple user files with few lines/commands using ansible playbook
users.yml
user1:
- Line1111
- Line2222
- Line3333
user2:
- Line4444
- Line5555
- Line6666
main.yml
- hosts: "{{ host_group }}"
vars_files:
- ../users.yml
tasks:
- name: Add user "user1" to sudoers.d
lineinfile:
path: /etc/sudoers.d/user1
line: '{{ item }}'
state: present
mode: 0440
create: yes
validate: 'visudo -cf %s'
with_items:
- "{{ user1 }}"
The above one is working only for user1..
If I want to also include user2 --> How to change the file name : path: /etc/sudoers.d/user1
I tried below and its not working :
Passing below users as variable to main.yml while running
users:
- "user1"
- "user2"
- name: Add user "{{users}}" to sudoers.d
lineinfile:
path: /etc/sudoers.d/{{users}}
line: '{{ item }}'
state: present
mode: 0440
create: yes
validate: 'visudo -cf %s'
with_items:
- "{{ users }}"
So, basically I want to pass in users to a variable {{users}} as user1 and user2 and wanted to use the lines for each user from users.yml and add it to respective user files (/etc/sudoers.d/user1 and /etc/sudoers.d/user2).
So /etc/sudoers.d/user1 should look like
Line1111
Line2222
Line3333
and /etc/sudoers.d/user2 should look like
Line4444
Line5555
Line6666
Try to add quotes:
users:
- "user1"
- "user2"
- name: "Add user {{users}} to sudoers.d"
lineinfile:
path: "/etc/sudoers.d/{{users}}"
line: "{{ item }}"
state: present
mode: 0440
create: yes
validate: 'visudo -cf %s'
with_items:
- "{{ users }}"
As per Ansible Documentation on Using Variables:
YAML syntax requires that if you start a value with {{ foo }} you quote the whole line, since it wants to be sure you aren’t trying to start a YAML dictionary. This is covered on the YAML Syntax documentation.
This won’t work:
- hosts: app_servers
vars:
app_path: {{ base_path }}/22
Do it like this and you’ll be fine:
- hosts: app_servers
vars:
app_path: "{{ base_path }}/22"
cat users.yml
---
users:
- user1:
filename: user1sudoers
args:
- Line1111
- Line2222
- Line3333
- user2:
filename: user2sudoers
args:
- Line4444
- Line5555
- Line6666
I use template here, instead of lineinfile
---
cat sudoers.j2
{% if item.args is defined and item.args %}
{% for arg in item.args %}
{{ arg }}
{% endfor %}
{% endif %}
the task content
---
- hosts: localhost
vars_files: ./users.yml
tasks:
- name: sync sudoers.j2 to localhost
template:
src: sudoers.j2
dest: "/tmp/{{ item.filename }}"
loop: "{{ users_list }}"
when: "users_list is defined and users_list"
after run the task.yml, generate two files under /tmp directory.
cat /tmp/user1sudoers
Line1111
Line2222
Line3333
cat /tmp/user2sudoers
Line4444
Line5555
Line6666

ansible yum check update parse output to have list of packages

I want to parse the output of yum check-update ansible equivalent to get only the list of package in human readable format.
My code so far:
- name: check for updates
hosts: localhost
gather_facts: true
tasks:
- name: check for updates (yum)
yum: list=updates update_cache=true
register: yumoutput
when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
- debug: msg={{ yumoutput.stdout | from_json }}
but I get:
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{ yumoutput.stdout | from_json }}): expected string or buffer"}
EDIT: the complete playbook:
---
- name: check for updates
hosts: localhost
gather_facts: true
tasks:
- name: check for updates (yum)
yum: list=updates update_cache=true
register: yumoutput
when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
- debug: var=yumoutput
msg: "{{ yumoutput.results | map(attribute='name') | list }}
yum module does not register stdout key ― you can see it using debug: var=yumoutput.
You need to extract the package names from the list of dictionaries, for example:
debug:
msg: "{{ yumoutput.results | map(attribute='name') | list }}"
Some minor syntax errors in the complete playbook. This did it for me
---
- name: check for updates
hosts: localhost
gather_facts: true
tasks:
- name: check for updates (yum)
yum: list=updates update_cache=true
register: yumoutput
when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
- debug:
msg: "{{ yumoutput.results | map(attribute='name') | list }}"
In addition to the above-mentioned solution. You can use call back plugin for ease of reading the output.
Below is one of the human-readable call-back plugin:
https://github.com/n0ts/ansible-human_log
More info about call back plugins:
http://docs.ansible.com/ansible/devel/plugins/callback.html

Why Ansible didn't see attribute in variable?

I have Ansible role "db" with simple task:
- name: Check repos
apt_repository: repo="{{ item.repo }}" state={{ item.state }}
with_items:
- "{{ apt_repos }}"
In /defaults/mail.yml:
apt_repos:
# Percona
- { state: present, repo: 'deb http://repo.percona.com/apt wheezy main', keyserver: 'keyserver.ubuntu.com', key: '1C4CBDCDCD2EFD2A', needkey: True }
- { state: present, repo: 'deb-src http://repo.percona.com/apt wheezy main', needkey: False }
When i try to run this ansible-playbook:
---
- hosts: test
roles:
- db
i see error:
fatal: [10.10.10.10] => One or more undefined variables: 'unicode object' has no attribute 'repo'
FATAL: all hosts have already failed -- aborting
But i have another role with same task and variable and it work perfectly. What's wrong?
You want to be doing this:
with_items: apt_repos
apt_repos is a list. By referencing it as - "{{ apt_repos }}" the extra - is turning it into a list of lists. You also don't need the quotes or braces in this case - those are pretty much just redundant in this type of situation.

Resources