I am starting out w/ Ansible and am working with roles for the first time. I have a main playbook that's just supposed to distinguish between Ubuntu and CentOS when installing Docker, but for some reason I can't get it to work. Is it the indentation?
- name: Install Docker for Ubuntu and CentOS
hosts: all
remote_user: xyz
tasks:
- name: Import tasks for Ubuntu
- import_tasks: ubuntu_Docker.yml
when: ansible_facts['os_family'] == "Debian"
- name: Import tasks for CentOS
- import_tasks: centos_Docker.yml
when: ansible_facts['distribution'] == "CentOS"
The error appears to be in 'filelocation': line 9, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Import tasks for Ubuntu
^ here (points at the n)
tried many indentations, just can't get it to work. It's probably trivial, but again: New to this, and a bit confused...Thx in regards.
No hyphen(-) for import_tasks. Check the example at https://docs.ansible.com/ansible/2.4/import_tasks_module.html
---
- name: Install Docker for Ubuntu and CentOS
hosts: all
remote_user: xyz
tasks:
- name: Import tasks for Ubuntu
import_tasks: ubuntu_Docker.yml
when: ansible_facts['os_family'] == "Debian"
- name: Import tasks for CentOS
import_tasks: centos_Docker.yml
when: ansible_facts['distribution'] == "CentOS"
Related
I'm having problem executing an Ansible playbook to install a package using yum on RHEL7 and dnf on RHEL8.
I'm using a condition as shown on my playbook below, but keep getting errors.
Error
{"msg": "The conditional check 'ansible_os_family == \"RedHat\" and ansible_lsb.major_release|int == \"7\"' failed. The error was: error while evaluating conditional (ansible_os_family == \"RedHat\" and ansible_lsb.major_release|int == \"7\"): 'dict object' has no attribute 'major_release'\n\nThe error appears to be in '/ansible/master/intall.pkg.yml': line 9, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n # (Task-1) Checks if ansible_os_family == \"RHEL7\" and then Installs telnet on Remote Node\n - name: Install telnet on RHEL7 Server\n ^ here\n"}
Playbook
---
- hosts: all
gather_facts: true
become: yes
#become_user: ansible
become_method: sudo
tasks:
# (Task-1) Checks if ansible_os_family == "RHEL7" and then Installs telnet on Remote Node
- name: Install telnet on RHEL7 Server
yum: name=telnet state=present
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int == "7"
# (Task-2) Checks if ansible_os_family == "RHEL8" and then Installs telnet on Remote Node
- name: Install telnet on RHEL8 Server
package: name=telnet state=present
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int == "8"
How do I use my playbook to skip the RHEL7 and install the package on RHEL8 using dnf?
Thank you.
As already mentioned within the comments by #Zeitounator you may have a look into Conditionals based on ansible_facts since the fact respective variable is a string.
The following minimal example is working in an production environment.
- name: "Install telnet on RHEL-{{ ansible_distribution_major_version }} Remote Node"
yum:
name: telnet
state: present
when: ansible_distribution == 'RedHat' and ansible_distribution_major_version == '7'
- name: "Install telnet on RHEL-{{ ansible_distribution_major_version }} Remote Node"
yum:
name: telnet
state: present
when: ansible_distribution == 'RedHat' and ansible_distribution_major_version == '8'
This is possible because of Software management tools in RHEL 8
Although YUM v4 used in RHEL 8 is based on DNF, it is compatible with YUM v3 used in RHEL 7. For software installation, the yum command and most of its options work the same way in RHEL 8 as they did in RHEL 7.
This means that in your specific case by using the yum or package module
This modules manages packages on a target without specifying a package manager module (like ansible.builtin.yum, ansible.builtin.apt, …). It is convenient to use in an heterogeneous environment of machines without having to create a specific task for each package manager. package calls behind the module for the package manager used by the operating system discovered by the module ansible.builtin.setup.
there would be no need for a conditional check unless there would be differences in the availability of packages and or naming.
A single task like
- name: "Install telnet on RHEL-{{ ansible_distribution_major_version }} Remote Node"
package: # or even yum
name: telnet
state: present
should just work.
Depending on your infrastructure and to be prepared for future releases you could switch to the dnf module for RHEL-8 and RHEL-9 instances.
- name: "Install telnet on RHEL-{{ ansible_distribution_major_version }} Remote Node"
dnf:
name: telnet
state: present
when: ansible_distribution == 'RedHat' and ansible_distribution_major_version == '8'
---
- name: install httpd and mod_ssl
hosts: all
vars_files:
- vars/package_list.yaml
tasks:
- name: install httpd,firewalld and mod_ssl
yum:
name: "{{ item }}"
state: latest
loop: "{{ package_list }}"
when: >
( ansible_facts['distribution'] == 'Ubuntu' )
or
( ansible_facts['distribution'] == 'CentOS' and ansible_facts['distribution'] == 'Fedora' and ansible_facts['distribution_version'] is version( '8' , '>=') )
# some other tasks.
How can I send a failure message if task install httpd, firewalld and mod_ssl fails based on the condition that if distribution is ubuntu then proceed with the install or if the distribution is 'CenOS' ( Not 'Fedora' ) with version >= '8' then proceed with the install or show a failure message.
If the condition is not met then it exits with the failure message or else it continues with the rest of the play.
something like:
if (
( distro == 'Ubuntu' ) or
( distro == 'CentOS' and distro != 'Fedora' and version >= 8)
)
then install httpd, firewalld, mod_ssl and proceed further
else
print "Error: requirements not met for setup"
Simplify the pattern:
fail early if your target does not meet the requirement
go on with the rest of your tasks if it does
Note: I'm not sure I fully understand your condition which differs in your example playbook and pseudo code and is not really clear in both cases. So this is just a layout example. Put whatever condition is needed.
Moreover:
although it is possible, using yum on Ubuntu looks a bit awkward.
looping over yum is discouraged. You should pass the list of packages directly in the name attribute (fixed below)
---
- name: install something on my supported targets
hosts: all
vars_files:
- vars/package_list.yml
tasks:
- name: Fail if the target isn't supported
ansible.builtin.fail:
msg: target isn't supported
when: my_target_condition_is_false
- name: install packages on supported target
ansible.builtin.yum:
name: "{{ package_list }}"
state: latest
# some other tasks.
I just started experimenting with ansible and I am trying to write my first simple playbook.
But I am getting a syntax error with the task keywork,
---
name: add ansible user
hosts: all
become: true
become_method: sudo
become_user:root
tasks:
- user:
name: ansible
groups: ansible
When I run this get the following:
utility:~/scripts/ansible# ansible-playbook --check add-ansible-user.yml
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/root/scripts/ansible/add-ansible-user.yml': line 8, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
tasks:
^ here
From searching I belive the best bet is that I have an indent problem, but nomatter how I have tried to change it up, I cant get it too work.
- name: add ansible user
hosts: all
become: true
become_method: sudo
become_user: root
tasks:
- user:
name: ansible
groups: ansible
It's indeed the indentation problem. Please try the code written above.
Facing same issue, by making correct Indent spacing able to resolve it
As ref below
---
- name: my ansible
hosts: webserver
remote_user: root
become: true
tasks:
- name: intall httpd
yum:
name: httpd
state: latest
- name: run httpd
service:
name: httpd
state: started
- name: create content
copy:
content: “Congratulation on installing ansible”
dest: /var/www/html/index.html
The problem is here:
become_user:root
You need a space between : and root
become_user: root
I am learning ansible and this is my YAML file.
---# Outline to playbook translation
- hosts: node1
user: test
sudo: yes
gather_facts: no
tasks:
- name: date time stamp at start
raw: /usr/bin/date > /home/test/playbook_start.log
- name: install apache web server
yum: pkg=httpd state=latest
- name: start the service
service: name=httd state=restarted
- name: verify web service is running or not
command: systemctl status httpd
register: result
- debug: var-result
- name: install client SW telnet
yum: pkg=telnet state=latest
- name: install client pkg VIM
yum: pkg=vim state=latest
and I get this error while running
ERROR! Syntax Error while loading YAML.
The error appears to have been in '/home/test/Outline/webserver.yml': line 2, column 8, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
---# Outline to playbook translation
- hosts: node1
^ here
Try this file:
---
# Outline to playbook translation
- hosts: node1
user: test
sudo: yes
gather_facts: no
tasks:
- name: date time stamp at start
raw: /usr/bin/date > /home/test/playbook_start.log
- name: install apache web server
yum: pkg=httpd state=latest
- name: start the service
service: name=httd state=restarted
- name: verify web service is running or not
command: systemctl status httpd
register: result
- debug: var=result
- name: install client SW telnet
yum: pkg=telnet state=latest
- name: install client pkg VIM
yum: pkg=vim state=latest
The syntax error is because you did not separate the comment on the first line of the file from the preceding token (the directives end marker: ---):
Comments must be separated from other tokens by white space characters.
try:
--- # Outline to playbook translation
Either remove "# Outline to playbook translation" or put it in a next line or give a space after ---
I have a tasks.yml that contains something like :
- name: something on Debian wheezy
when: ansible_distribution == 'Debian' and ansible_distribution_version == '7'
- name: something on Debian jessie
when: ansible_distribution == 'Debian' and ansible_distribution_version == '8'
- name: something on Ubuntu
when: ansible_distribution == 'Ubuntu'
I want to add a task (or something) that aborts the playbook if none of those tasks were run.
Maybe "something" is installing a package, and some tasks that come after are configuring that newly installed package. If I run the playbook on a RedHat system, that package won't be installed, and I want to abort before executing the tasks that configure it.
I think I could do something like:
- fail: msg="abort!"
when: not (ansible_distribution == 'Debian' and ansible_distribution_version == '7') and not (ansible_distribution == 'Debian' and ansible_distribution_version == '8') and not ansible_distribution == 'Ubuntu'
... but that's annoying. Is there any better solution?
---
- name: test
hosts: localhost
tasks:
- name: Install pkg
debug: msg="Installed pkg"
when: "{{ ansible_distribution == 'Debian' }}"
register: debian_pkg
- name: Install pkg
debug: msg="Installed pkg"
when: "{{ ansible_distribution == 'Ubuntu' }}"
register: ubuntu_pkg
- fail: msg="Unsupported OS"
when: "debian_pkg|skipped and ubuntu_pkg|skipped"
I finally went a simpler, more "business"-accurate way. I want to install something, and I then expect something to be installed. In fact, in my infrastructure where not everything is automated (I'm not root everywhere) I sometimes can't install something, but I still want to check that it is installed (it was installed out-of-band).
So, after the tasks that install something depending on the OS, I added a task that checks if it is installed, simply by trying to run it. Something like that:
- include: install_something.yml # contains the install tasks for each OS
when: can_become_root
- name: Check that something is installed
command: something --version