How to run apt update and upgrade via Ansible shell - ansible

I'm trying to use Ansible to run the following two commands:
sudo apt-get update && sudo apt-get upgrade -y
I know with ansible you can use:
ansible all -m shell -u user -K -a "uptime"
Would running the following command do it? Or do I have to use some sort of raw command
ansible all -m shell -u user -K -a "sudo apt-get update && sudo apt-get upgrade -y"

I wouldn't recommend using shell for this, as Ansible has the apt module designed for just this purpose. I've detailed using apt below.
In a playbook, you can update and upgrade like so:
- name: Update and upgrade apt packages
become: true
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400 #One day
The cache_valid_time value can be omitted. Its purpose from the docs:
Update the apt cache if its older than the cache_valid_time. This
option is set in seconds.
So it's good to include if you don't want to update the cache when it has only recently been updated.
To do this as an ad-hoc command you can run:
$ ansible all -m apt -a "upgrade=yes update_cache=yes cache_valid_time=86400" --become
ad-hoc commands are described in detail here
Note that I am using --become and become: true. This is an example of typical privilege escalation through Ansible. You use -u user and -K (ask for privilege escalation password). Use whichever works for you, this is just to show you the most common form.

Just to add a flavour on the answer. This one is an executable playbook in all the hosts specified in your inventory file.
- hosts: all
become: true
tasks:
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400

Using Ubuntu 16.04, I did a little adjustement:
- name: Update and upgrade apt packages
become: true
apt:
update_cache: yes
upgrade: 'yes'
I juste put the upgrade yes between apostrophe to avoid un annoying warning:
[WARNING]: The value True (type bool) in a string field was converted to u'True' (type string). If this does
not look like what you expect, quote the entire value to ensure it does not change.
At 2020, I would like just to comment into the original answer, but no enough reputation at that time...
Ref:
The value True (type bool) in a string field was converted to u'True' (type string)

We use the following command to update and upgrade all packages :
ansible all -m apt -a "name='*' state=latest update_cache=yes upgrade=yes" -b --become-user root

Related

How to install ansible on a RHEL machine which doesn't have access to Internet

How to install ansible on a RHEL 6.8 machine which doesn't have access to Internet?
I'd propose to use raw: module. Copy rpm (scp) to server, and run rpm -i.
Raw module does not use a usual ansible workflow and do things 'directly'. Here my code to install python if it's not present on server, I think you can adopt it for rpm for ansible too.
- hosts: all
gather_facts: no
tasks:
- name: Remember sever key and install python
raw: test -x /usr/bin/python || sudo apt-get update && sudo apt-get -y install python
changed_when: True

Ansible - pip not found

I am getting this error:
TASK [pip] *********************************************************************
failed: [default] (item=urllib3) =>
{"changed": false, "item": "urllib3",
"msg": "Unable to find any of pip2, pip to use. pip needs to be installed."}
Upon a suggestion I run following command:
ansible default -a "which pip"
I get an error:
default | FAILED | rc=1 >>
non-zero return code
So I guess that means no pip installed. I tried installing pip using:
ansible default -a "easy_install pip"
I get the following error:
default | FAILED | rc=2 >>
[Errno 2] No such file or directory
Any ideas?
UPDATE
In play_local.yaml, I have the following task:
- name: Prepare system
hosts: default
become: yes
gather_facts: false
pre_tasks:
- raw: sudo apt-get -y install python python-setuptools python-pip build-essential libssl-dev libffi-dev python-dev easyinstall pip
- file: path=/etc/sudoers.d/ssh-auth-sock state=touch mode=0440
#- lineinfile: line='Defaults env_keep += "SSH_AUTH_SOCK"' path=/etc/sudoers.d/ssh-auth-sock
- replace:
path: /etc/apt/sources.list
regexp: 'br.'
replace: ''
Shouldn't this task install pip?
Seems like pip is not installed, you can use the following task to install it:
- name: Install pip
apt:
name: python-pip
update_cache: yes
state: present
May be pip is hashed. Meaning pip is installed at path x (may be /usr/local/bin/pip), however, cached at path y (may be /usr/bin/pip). You can confirm that from - ansible default -m shell -a ‘type pip’. To resolve this you’ll need to run - ansible default -m shell -a ‘hash -r’.
BTW, you can also use command module instead of shell.
I've just met the same problem on a brand new CentOS 7. Solved through installing setuptools with yum first and then pip with easy_install as below :
ansible default -b -m yum -a "name=python-setuptools state=present"
ansible default -b -m easy_install -a "name=pip state=present"
For Debian Based systems (RUN THIS ON CLIENT SYSTEMS):
first install package python-is-python3 then add alias for pip echo alias pip=pip3 >> ~/.bashrc
I know my solution would be dumb but It works.
# pip-fix.yml
- name: pip fix
hosts: all
become: true
tasks:
- name: install python-is-python3
apt: name=python-is-python3 update_cache=yes state=present
- name: creating alias
shell: echo alias pip=pip3 >> ~/.bashrc
- name: test and upgrade pip
pip: name=pip state=latest
tags:
- packages
run using ansible-playbook pip-fix.yml
Ansible Not finding / Installing Pip
While not using the author's original details, i think this might help them or others.
I was getting the following error for installing pip:
via Ansible:
FAILED! => {"changed": false, "cmd": "/bin/easy_install --upgrade pip", "failed": true, "msg": "Couldn't find index page for 'pip' (maybe misspelled?)
directly on the host:
Searching for pip
Reading https://pypi.python.org/simple/pip/
Couldn't find index page for 'pip' (maybe misspelled?)
Scanning index of all packages (this may take a while)
Reading https://pypi.python.org/simple/
No local packages or download links found for pip
error: Could not find suitable distribution for
Requirement.parse('pip')
I attempted to use the above hash -r answer:
(NOTE: help hash... hash -r == forget all remembered locations)
- name: forget easy_install path
shell: hash -r
become: true
however this was not a solve for me.
I found via another post: 'pip install' fails for every package ("Could not find a version that satisfies the requirement") that this was the final fix:
curl https://bootstrap.pypa.io/get-pip.py | python
or
- name: manually install pip
shell: curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python
become: true
NOTE: i changed the pip version. Also, there is a better way to do a curl in ansible, this is simply an example
I then followed with the easy_install pip latest. to ensure it was up to date.
below fix worked for me
#ln -s /usr/local/bin/pip /usr/bin/pip

What's correct way to upgrade APT packages using Ansible?

When setting up a new Linux server, I typically run apt-get update and then apt-get upgrade. The first command updates the list of available packages and their versions, but it does not install or upgrade any packages. The second command actually installs newer versions of the packages I have.
What is the correct way to do this in Ansible? One way you could do it is like this:
- name: update and upgrade apt packages
apt: >
upgrade=yes
update_cache=yes
cache_valid_time=3600
Or you could do it in two separate steps:
- name: update apt packages
apt: >
update_cache=yes
cache_valid_time=3600
- name: upgrade apt packages
apt: upgrade=yes
If you do it the first way, is Ansible smart enough to know that it should run 'update' before 'upgrade'? The Ansible apt documentation doesn't address this finer point.
The apt module documentation does actually state that it will run the update first:
Run the equivalent of apt-get update before the operation. Can be run
as part of the package installation or as a separate step.
(emphasis mine)
So both of those plays should be functionally the same.
Here is the better version of upgrading and updating packages. The below executable playbook will update and upgrade packages to all hosts specified in the inventory file.
- hosts: all
become: yes
tasks:
- name: Update and upgrade apt packages
apt:
upgrade: yes
update_cache: yes
cache_valid_time: 86400 # 1 day
The cache_valid_time value is optional. The docs says:
Update the apt cache if its older than the cache_valid_time. This option is set in seconds.
I think its good practice to include this if you don't want to update the cache when it has only recently been updated.

Unable to Update rsyslog using Ansible

I am having production systems which are running on outdated rsyslog version 7.4.4, hence I need to update using latest v-8 version , as in http://www.rsyslog.com/ubuntu-repository/
Only 3 things need to be done
1. sudo add-apt-repository ppa:adiscon/v8-stable
{After This step, it asks to press [ENTER]
2. sudo apt-get update
3. sudo apt-get install rsyslog
so i wrote the following tasks in playbooks as:
- name: Updating rsyslog from 7.4.4 to v-8 stable| Adding PPA
apt_repository:
repo='ppa:adiscon/v8-stable'
state=present
update_cache=yes
- name: Running Updates
apt: update_cache=yes
- name: Install rsyslog (v-8)
apt: name=rsyslog
state=present
update_cache=yes
at the first task Ansible{Updating rsyslog from 7.4.4 to v-8 stable| Adding PPA} just sits/hangs there.. I am guessing because it expects {ENTER}
What should i do ?
I figured it out - my proxy server were not allowing this traffic!
#NishantSingh

How to make sure an ansible playbook runs completely

I am running this ansible playbook:
---
- hosts: localhost
remote_user: root
tasks:
- name : update system
apt : update_cache=yes
- name : install m4
apt : name=m4 state=present
- name : install build-essential
apt : name=build-essential state=present
- name : install gcc
apt : name=gcc state=present
- name : install gfortran
apt : name=gfortran state=present
- name : install libssl-dev
apt : name=libssl-dev state=present
- name : install python-software-properties
apt : name=python-software-properties state=present
- name : add sage ppa repo
apt_repository: repo='ppa:aims/sagemath'
- name : update system
apt : update_cache=yes
- name : install dvipng
apt : name=dvipng state=present
- name : install sage binary
apt : name=sagemath-upstream-binary state=present
- name : invoke create_sagenb script
command: /usr/bin/screen -d -m sudo /root/databases-and-datamining-iiith/python-scripts/create_sagenb -i -y
- name : invoke start_sage script
command: /usr/bin/screen -d -m sudo /root/databases-and-datamining-iiith/python-scripts/start_sage -i -y
This playbook fails during task "install build-essential" and stops with error asking to run dpkg --configure -a.
How can I make sure that the playbook runs again after facing this error by running the command
dpkg --configure -a
first and then continue with other tasks.
Ansible in general is idempotent. That means you can simply run your playbook again after resolving the issue without conflicts.
This is not always true. In case you have a more complex play and execute tasks depending on the result of another task, this can break easily and a failed task then would bring you into a state that is not so easy to be fixed with Ansible. But that is not the case with the tasks you provided.
If you want to speed things up and skip all the tasks and/or hosts that did not fail, you can work with --limit and/or --start-at-task:
When the playbook fails, you might notice Ansible shows a message including a command which will enable you to limit the play to hosts which failed. So if only 1 host failed you do not need to run the playbook on all hosts:
ansible-playbook ... --limit #/Users/your-username/name-of-playbook.retry
To start at a specific task, you can use --start-at-task. So if your playbook failed at the task "install build-essential" you can start again at right this task and skip all previous tasks:
ansible-playbook ... --start-at-task="install build-essential"
On a side note, the apt module is optimized to work with loops. You can speed up your play by combining the tasks into one single apt task:
tasks:
- name: Install packages that we need for need for apt_repository
apt: update_cache=yes
name={{ item }}
state=present
cache_valid_time=3600
with_items:
- python-software-properties
- python-software-properties-common
- name: add sage ppa repo
apt_repository: repo='ppa:aims/sagemath'
- name: Install packages
apt: update_cache=yes
cache_valid_time=3600
name={{ item }}
state=present
with_items:
- m4
- build-essential
- gcc
- gfortran
- libssl-dev
- dvipng
- sagemath-upstream-binary

Resources