Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Readme for apt upgrades with Ansible

Here are three separate ways of using Ansible to perform system upgrades on an Ubuntu based system.

  1. apt-update-upgrade.yml This is the absolute most basic playbook I use. It performs an apt update, then apt full-upgrade and lastly an apt autoremove and apt autoclean.
  2. apt-update-upgrade-only-once-a-day.yml I use this in playbook where I'm repeatedly running it to do installs or reconfiguration, or where I have unattended-upgrades installed.
  3. apt-update-upgrade-with-check.yml On systems where I'm not the only administrator, I don't always know whether I'll want to apply an upgrade, so this gives me a chance to list off what packages will be updated and upgraded when I let it proceed... or perhaps I just want a list of what's going to change first! To run this, I also need to create a directory in the same path called filter_plugins and need to put the file splitpart.py in there (that's from https://www.redpill-linpro.com/sysadvent/2017/12/24/ansible-system-updates.html).

Anyway, I use these in different places for different purposes, so I hope they help you!

---
- hosts: all
become: true
tasks:
# Some of these tasks are based on data from here:
# https://askubuntu.com/a/410259
- name: Get stat of last run apt
stat:
path: /var/cache/apt/pkgcache.bin
register: apt_run
- name: "Apt update, Full-upgrade, autoremove, autoclean check"
debug:
msg: "Skipping apt-update, etc. actions as apt update was run today"
when: "'%Y-%m-%d' | strftime(apt_run.stat.mtime) in ansible_date_time.date"
- name: "Apt update, Full-upgrade, autoremove, autoclean"
apt:
upgrade: full
update_cache: yes
autoremove: yes
autoclean: yes
when: "'%Y-%m-%d' | strftime(apt_run.stat.mtime) not in ansible_date_time.date"
#!/usr/bin/ansible-playbook
# This is based loosely on https://www.redpill-linpro.com/sysadvent/2017/12/24/ansible-system-updates.html
---
- hosts: all
become: true
vars:
force: "{% if lookup('env', 'force') == '' %}False{% else %}True{% endif %}"
tasks:
- name: Run apt-get update
apt:
update-cache: yes
changed_when: 0
- name: Get a list of the pending upgrades
command: apt-get --simulate dist-upgrade
args:
warn: false
register: apt_simulate
changed_when: 0
- name: Parse apt-get output to get list of changed packages
set_fact:
updates: '{{ apt_simulate.stdout_lines | select("match", "^Inst ") | list | splitpart(1, " ") | list | sort }}'
changed_when: 0
- name: Show pending updates
debug:
var: updates
when: updates.0 is defined
- name: Do you want to proceed?
pause:
when: updates.0 is defined and not force
- hosts: all
gather_facts: false
become: true
serial: 1
any_errors_fatal: true
max_fail_percentage: 0
vars:
force: "{% if lookup('env', 'force') == '' %}False{% else %}True{% endif %}"
tasks:
- name: Run apt-get autoremove
command: apt-get -y autoremove
args:
warn: false
when:
- '"Inst linux-image-" in apt_simulate.stdout'
- updates.0 is defined
changed_when: 0
- name: Run apt-get full-upgrade
apt:
upgrade: full
register: upgrade_output
when: updates.0 is defined
- name: check if reboot needed
stat: path=/var/run/reboot-required
register: file_reboot_required
- name: Stop here if a reboot isn't required...
meta: end_play
when: not file_reboot_required.stat.exists
- name: Confirm reboot of {{ inventory_hostname }}
pause:
when: not force
- name: reboot node
reboot:
msg: Reboot triggered by Ansible
- name: Check kernel version (basic SSH check)
shell: uname -rv
register: check
until: check.failed == false
retries: 240
delay: 2
- name: Kernel Version
debug:
msg: "{{ check.stdout }}"
- name: waiting between hosts
pause:
minutes: 1
when: inventory_hostname != ansible_play_hosts[-1]
---
- hosts: all
become: true
tasks:
- name: Update OS
apt:
update_cache: yes
upgrade: full
autoremove: yes
autoclean: yes
# This code from https://www.redpill-linpro.com/sysadvent/2017/12/24/ansible-system-updates.html
def splitpart (value, index, char = ','):
if isinstance(value, (list, tuple)):
ret = []
for v in value:
ret.append(v.split(char)[index])
return ret
else:
return value.split(char)[index]
class FilterModule(object):
def filters(self):
return {'splitpart': splitpart}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.