I'm developing my first playbook. I'm using 3 CentOS 8 VMs. Using Oracle Virtual Box on my local pc with Windows 10, which virtualize an Ansible controller VM and 2 target VM's.
My inventory.txt:
# Inventory File
target1 ansible_ssh_pass=osboxes.org ansible_host=192.168.1.106
target2 ansible_ssh_pass=osboxes.org ansible_host=192.168.1.153
My playbook-webapp.yaml contains:
# Ansible Playbook to install a web application
-
name: Deploy Web application
hosts: target1, target2
remote_user: root
tasks:
- name: Install dependencies
yum: name= {{ item }} state=installed
with_items:
- epel-release
- python
- python-pi
I execute with:
ansible-playbook playbook-webapp.yaml -i inventory.txt
Output:
PLAY [Deploy Web application] *********************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************
ok: [target2]
ok: [target1]
TASK [Install dependencies] ***********************************************************************************************************************
ok: [target1] => (item=epel-release)
ok: [target2] => (item=epel-release)
ok: [target1] => (item=python)
ok: [target2] => (item=python)
ok: [target1] => (item=python-pip)
ok: [target2] => (item=python-pip)
PLAY RECAP ****************************************************************************************************************************************
target1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
target2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
But when I try to check for my yum repos on target1 node:
[osboxes#target1 ~]$ yum repolist
repo id repo name
appstream CentOS Linux 8 - AppStream
baseos CentOS Linux 8 - BaseOS
extras CentOS Linux 8 - Extras
However, no epel-release of some sort is shown, but is set in the ansible task to be installed.
If I try to execute
[osboxes#ansiblecontroller web_deployment]$ ansible all -m ping -i inventory.txt
Output:
target2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
target1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
Any suggestion is appreciated.
Try to install the package with the dnf module:
- name: Install dependencies
dnf:
name:
- epel-release
- python
- python-pi
Also, a nice approach to manage your systems with Ansible would be to download the operating system, install python3, then package your system again and use that packaged OS for all VM's. This way, the system is as 'bald' as possible, but only includes python3, which is good for Ansible usage.
no epel-release or other is shown
This is actually quite weird. This sounds like something you should chase. Since we don't know the background details here, I can only guess and guide you in the correct direction.
I am asking myself/you whether you have 'targetted' the correct machine. There are 100 ways to verify whether this is the case. I would do it like this:
- shell: touch /tmp/hi
Then login at the system, and check whether /tmp/hi exists... if it does, then something fishy is going on.
Check installed packages with:
rpm -qa | grep -i epel
Is it installed?
Also, the yum.repos.d should contain the epel repo files
[vagrant#vm-local-1 ~]$ ls /etc/yum.repos.d/ | grep epel
epel-modular.repo
epel-playground.repo
epel-testing-modular.repo
epel-testing.repo
epel.repo
Please let us know.
Following the #Kevin suggestions the right playbook is:
# Ansible Playbook to install a web application
-
name: Deploy Web application
hosts: target1, target2
remote_user: root
tasks:
- name: Install dependencies
dnf:
name:
- epel-release
- python3
- python3-pip
state: installed
To check on the target VMs:
yum repolist
or
ls /etc/yum.repos.d/ | grep epel
and
python3 --version
Related
I'm learning Ansible and I'm trying to convert these Homebrew commands using Ansible's homebrew_tap and homebrew_cask:
brew tap homebrew/cask-fonts
brew install --cask font-hack-nerd-font
My Ansible playbook looks like this:
---
- name: test
hosts: localhost
tasks:
- name: Tapping homebrew/cask-fonts
homebrew_tap:
name: homebrew/cask-fonts
- name: Installing Nerd Font
homebrew_cask:
name: font-hack-nerd-font
When I run it, I get this error:
PLAY [test] ****************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Tapping homebrew/cask-fonts] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Installing Nerd Font] ************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Invalid cask: font-hack-nerd-font."}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
I'm hoping to be able to pull this off using homebrew_cask without brew command directly.
Any guidance is greatly appreciated. Thank you.
It's reported as a bug due to hyphen(s) in the cask package name. This bug is resolved via pull request.
Ansible 2: Is it possible in Ansible Playbook to exclude a package that normally would be upgraded during dist-upgrade by using just the name of the package instead of the exact version?
---
- hosts: localhost
become: yes
tasks:
- name: disable upgrade of Java
dpkg_selections:
name: openjdk-8-jre
selection: hold
I'd like to specify just openjdk instead of openjkd-8-jre because no openjdk should be installed no matter what version of openjdk is available to upgrade to (have different servers with different ubuntu os).
Preliminary note (extending my comment)
openjdk-8-jre is the package name. There is actually one different package for each major version of java. They can be installed alone or all together and managed through alternatives. But e.g. openjdk-11-jre-headless will never replace openjdk-8-jre-headless.
So it is quite unusual to hold such packages as your are cutting yourself off the latest bug and security fixes that should not impact the application using it (e.g. a java-8 application should run on any minor version of openjdk-8).
That being said, if you still want to do it...
Solution with package_facts.
This is basically doing exactly what you were trying except it will only mark as hold existing packages on the machine (which is probably better anyway).
Ansible has a package_facts module which will return the existing installed package in the packages variable.
The idea: get those package name, select only the ones starting with a given name and feed that list to dpkg_selections to mark them as hold. The below playbook was tested successfully against my unbuntu 18.04 home machine.
- name: Disable package upgrade based on partial name
hosts: localhost
gather_facts: false
become: true
vars:
partial_hold_name: openjdk
partial_hold_regexp: "^{{ partial_hold_name }}.*"
hold_package_list: "{{ packages | dict2items | map(attribute='key') | select('match', partial_hold_regexp) | list }}"
tasks:
- name: Gather package facts
package_facts:
- name: dselect all openjdk packages if they exists
dpkg_selections:
name: "{{ item }}"
selection: hold
loop: "{{ hold_package_list }}"
Which gives (first run with openjdk-11 and openjdk-8 installed in parallel and marked as "install")
$ ansible-playbook test.yml
PLAY [Disable package upgrade based on partial name] ***********************************************************************************************************************************************************************************
TASK [Gather package facts] ************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [dselect all openjdk packages if they exists] *************************************************************************************************************************************************************************************
changed: [localhost] => (item=openjdk-11-jre-headless)
changed: [localhost] => (item=openjdk-8-jdk-headless)
changed: [localhost] => (item=openjdk-8-jre-headless)
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I am logged in as root#x.x.x.12 with ansible 2.8.3 Rhel 8.
I wish to copy few files to root#x.x.x.13 Rhel 8 and then execute a python script.
I am able to copy the files sucessfully using ansible. I had even copied the keys and now it is ssh-less.
But during execution of script :
'fatal: [web_node1]: FAILED! => {"changed": false, "msg": "Could not find or access '/root/ansible_copy/write_file.py' on the Ansible Controller.\nIf you are using a module and expect the file to exist on the remote, see the remote_src option"}'
Please note that I am a novice to ansible.
I guess there is some permission issues.
Please Help me out if possible.
Thanking in anticipation
**yaml_file**
-
name: Copy_all_ansible_files_to_servers
hosts: copy_Servers
become: true
become_user: root
tasks:
-
name: copy_to_all
copy:
src: /home/testuser/ansible_project/{{item}}
dest: /root/ansible_copy/{{item}}
owner: root
group: root
mode: u=rxw,g=rxw,o=rxw
with_items:
- write_file.py
- sink.txt
- ansible_playbook_task.yaml
- copy_codes_2.yaml
notify :
- Run_date_command
-
name: Run_python_script
script: /root/ansible_copy/write_file.py > /root/ansible_copy/sink.txt
args:
#chdir: '{{ role_path }}'
executable: /usr/bin/python3.6
**inventory_file**
-
web_node1 ansible_host=x.x.x.13
[control]
thisPc ansible_connection=local
#Groups
[copy_Servers]
web_node1
Command: ansible-playbook copy_codes_2.yaml -i inventory.dat =>
PLAY [Copy_all_ansible_files_to_servers] *******************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [web_node1]
TASK [copy_to_all] *****************************************************************************************************************************************************************************************
ok: [web_node1] => (item=write_file.py)
ok: [web_node1] => (item=sink.txt)
ok: [web_node1] => (item=ansible_playbook_task.yaml)
ok: [web_node1] => (item=copy_codes_2.yaml)
TASK [Run_python_script] ***********************************************************************************************************************************************************************************
fatal: [web_node1]: FAILED! => {"changed": false, "msg": "Could not find or access '/root/ansible_copy/write_file.py' on the Ansible Controller.\nIf you are using a module and expect the file to exist on the remote, see the remote_src option"}
PLAY RECAP *************************************************************************************************************************************************************************************************
web_node1 : ok=2 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
The script command will actually copy the file to the remote server before running it. Thus, when it complains about not being able to find or access the script, it's because it's trying to copy from /root/ansible_copy/write_file.py to the server.
If you don't really need the script to remain on the server after you execute it, you could remove the script from the copy task and change the script task to have the src point at /home/testuser/ansible_project/write_file.py.
Alternatively, instead of using the script command, you can manually run the script after transferring it using:
- name: run the write_file.py after it has already been transferred
command: python3.6 /root/ansible_copy/write_file.py > /root/ansible_copy/sink.txt
(Note: you may need to provide the full path to your python3.6 executable)
I have a lab setup with ansible controller + node and exploring few areas.
I am so far setup an user account named ansible in both machines and enabled ssh keybased authentication
Also setup sudo premissions for the user in both machines
When I try to run the below playbook , It works on the local machine and fails on the other node.
--- #Install Telnet
- hosts: all
name: Install Telnet
become: true
become_user: ansible
become_method: sudo
tasks:
- yum:
name: telnet
state: latest
Output is as follows
`[ansible#host1 playbooks]$ ansible-playbook telnetDeployYUM.yml
PLAY [Install Telnet] ***********************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************
ok: [192.168.64.6]
ok: [192.168.64.5]
TASK [yum] **********************************************************************************************************************************************************************************
ok: [192.168.64.5]
fatal: [192.168.64.6]: FAILED! => {"changed": true, "msg": "You need to be root to perform this command.\n", "obsoletes": {"grub2": {"dist": "x86_64", "repo": "#anaconda", "version": "1:2.02-0.64.el7.centos"}, "grub2-tools": {"dist": "x86_64", "repo": "#anaconda", "version": "1:2.02-0.64.el7.centos"}}, "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}
to retry, use: --limit #/home/ansible/playbooks/telnetDeployYUM.retry
PLAY RECAP **********************************************************************************************************************************************************************************
192.168.64.5 : ok=2 changed=0 unreachable=0 failed=0
192.168.64.6 : ok=1 changed=0 unreachable=0 failed=1
[ansible#host1 playbooks]$
`
I could also manually able to run sudo yum on the failed target as ansible user
I believe sudo set up in correct
[ansible#host2 root]$ sudo whoami
root
Can experts share some insights on what I am missing with respect to my failed machine , Thanks.
Below should work fine
- hosts: all
name: Install Telnet
become: yes
tasks:
- yum:
name: telnet
state: latest
ansible or user through which ansible is getting executed should be in sudoers file.
You are changing your user to ansible which is not required.
Run with -vvvv to see what ansible is doing.
Have you setup ansible in sudoers for password less privilege elevation?
you are getting a message that it is waiting for "escalation prompt". That means when you are running with become, you are failing to become since it needs the password. Make sure your test user is in /etc/sudoers AND you have it marked for that user to NOT need to enter a password when running sudo commands. The entry should end with :NOPASSWD on the line in that file.
I am using below ansible yml file to install python, pip, etc.
roles/python/main.yml:
---
- name: python
apt:
pkg: python
- name: python-pip
apt:
pkg: python-pip
- name: mongopy
pip:
pkg: mongopy
- name: mtools
pip:
pkg: mtools
when I run ansible-playbook on this script, I get below
PLAY [ec2] ***********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************************************************************************
ok: [xxxxx.ap-southeast-2.compute.amazonaws.com]
PLAY RECAP ***********************************************************************************************************************************************************************************************
xxxxxap-southeast-2.compute.amazonaws.com : ok=1 changed=0 unreachable=0 failed=0
there is no error on them but I checked these apps are not installed on the remote host. What wrong with my yml file? Is there any place I can check what the error is?
below is my playbook:
python.yml:
---
- hosts: ec2
remote_user: ubuntu
roles:
- python
below is the command I run:
ansible-playbook -i hosts python.yml
There are no tasks in your python role. Please have a look at the role structure.
If roles/x/tasks/main.yml exists, tasks listed therein will be added to the play
Tasks file (main.yml) should be placed in the tasks subdirectory of the role, not in the main role's directory.
And this has nothing to do with how you described the problem (installing Python or Pip). Even if you replaced the tasks with a single debug task which displays Hello world by default, it would not run.