diff options
Diffstat (limited to 'roles/sane_debian_system')
-rw-r--r-- | roles/sane_debian_system/defaults/main.yml | 21 | ||||
-rw-r--r-- | roles/sane_debian_system/subplot.md | 66 | ||||
-rw-r--r-- | roles/sane_debian_system/subplot.py | 48 | ||||
-rw-r--r-- | roles/sane_debian_system/subplot.yaml | 19 | ||||
-rw-r--r-- | roles/sane_debian_system/tasks/apt.yml | 55 | ||||
-rw-r--r-- | roles/sane_debian_system/tasks/env.yml | 37 | ||||
-rw-r--r-- | roles/sane_debian_system/tasks/main.yml | 12 | ||||
-rw-r--r-- | roles/sane_debian_system/templates/sources.list.j2 | 13 |
8 files changed, 214 insertions, 57 deletions
diff --git a/roles/sane_debian_system/defaults/main.yml b/roles/sane_debian_system/defaults/main.yml index 9e2ca84..d896b75 100644 --- a/roles/sane_debian_system/defaults/main.yml +++ b/roles/sane_debian_system/defaults/main.yml @@ -1,15 +1,20 @@ # These are the variables expected by this role. -# The desired hostname. Default is empty, which means hostname won't -# be set. -hostname: "" +# Playbook should set this to the version of this role it expects to +# use. Defaults to the inventory hostname. +sane_debian_system_version: "{{ inventory_hostname }}" + + +# The desired hostname. There is no no default, which means hostname +# won't be set. +sane_debian_system_hostname: "" # The Debian release code name to use. -debian_codename: +sane_debian_system_codename: # Default Debian mirror to use. Default should work everywhere, but if # needed, pick a faster mirror, perhaps a local one. -debian_mirror: deb.debian.org +sane_debian_system_mirror: deb.debian.org # A list of extra APT repositories to add. Each list entry should be a @@ -18,13 +23,13 @@ debian_mirror: deb.debian.org # keys are "signing_key", the public key of the archive signing key, # and "keyring_packge", which contains the .deb package with the # archive signing key. -sources_lists: [] +sane_debian_system_sources_lists: [] # Locales that should be generated. This should be a list of name, such as # fi_FI.UTF-8. -locales: [] +sane_debian_system_locales: [] # Default time zone. -timezone: UTC +sane_debian_system_timezone: UTC diff --git a/roles/sane_debian_system/subplot.md b/roles/sane_debian_system/subplot.md new file mode 100644 index 0000000..be05984 --- /dev/null +++ b/roles/sane_debian_system/subplot.md @@ -0,0 +1,66 @@ +# Role `sane_debian_system` – set up a manageable Debian system + +This role sets up a Debian system so that it can be managed with +Ansible in a reasonable way. + +## Version history + +### Version 2 + +* `sane_debian_hostname` defaults to the inventory hostname. This + means it's not necessary to set it if the default is sufficient. + +## Minimally sane Debian system + +~~~scenario +given a host running Debian +when I use role sane_debian_system +and I use variables from sane1.yml +and I run the playbook +then the host has the sudo package installed +and the host has the apt-transport-https package installed +and the host has the locales package installed +and the host has the systemd-timesyncd package installed +and the host has an empty /etc/apt/sources.list.d directory +and the host has hostname saneone +~~~ + +~~~{#sane1.yml .file .yaml} +ansible_python_interpreter: /usr/bin/python3 + +sane_debian_system_version: 2 +sane_debian_system_codename: bullseye +sane_debian_system_hostname: saneone +~~~ + +## Uses inventory hostname by default + +~~~scenario +given a host running Debian +when I use role sane_debian_system +and I use variables from sane-without-hostname.yml +and I run the playbook +then the host has the sudo package installed +and the host has hostname debian-ansible-test +~~~ + +~~~{#sane-without-hostname.yml .file .yaml} +sane_debian_system_version: 2 + +sane_debian_system_codename: bullseye +~~~ + +## Checks that debian codename is set + +~~~scenario +given a host running Debian +when I use role sane_debian_system +and I use variables from sane2.yml +and I try to run the playbook +then the command fails +and stdout contains "sane_debian_system_codename" +~~~ + +~~~{#sane2.yml .file .yaml} +sane_debian_system_version: 2 +~~~ diff --git a/roles/sane_debian_system/subplot.py b/roles/sane_debian_system/subplot.py new file mode 100644 index 0000000..f45eb2b --- /dev/null +++ b/roles/sane_debian_system/subplot.py @@ -0,0 +1,48 @@ +import logging + + +def host_has_package_installed(ctx, package=None): + assert_eq = globals()["assert_eq"] + qemu = ctx["qemu"] + output, exit = qemu.ssh(["dpkg", "--status", package]) + assert_eq(exit, 0) + installed = False + for line in output.decode("UTF8").splitlines(): + if line.startswith("Status:") and " installed" in line: + installed = True + break + assert installed + + +def host_directory_is_empty(ctx, pathname=None): + assert_eq = globals()["assert_eq"] + qemu = ctx["qemu"] + output, exit = qemu.ssh(["find", "/etc/apt/sources.list.d"]) + assert_eq(exit, 0) + for line in output.decode("UTF8").splitlines(): + assert "/etc/apt/sources.list.d/" not in line + + +def host_hostname_is(ctx, hostname=None): + assert_eq = globals()["assert_eq"] + qemu = ctx["qemu"] + output, exit = qemu.ssh(["hostname"]) + assert_eq(exit, 0) + actual = output.decode("UTF8").splitlines()[-1] + assert_eq(actual, hostname) + + +def host_hostname_has_address(ctx, hostname=None, addr=None): + assert_eq = globals()["assert_eq"] + + logging.debug(f"host_hostname_has_address:") + qemu = ctx["qemu"] + output, exit = qemu.ssh(["cat", "/etc/hosts"]) + assert_eq(exit, 0) + logging.debug(f" /etc/hosts: {output!r}") + actual = output.decode("UTF8") + logging.debug(f" /etc/hosts: {actual!r}") + wordlines = [line.split() for line in actual.splitlines()] + matches = [words for words in wordlines if len(words) == 2 and words[1] == hostname] + logging.debug(f" matches: {matches!r}") + assert_eq(matches, [[addr, hostname]]) diff --git a/roles/sane_debian_system/subplot.yaml b/roles/sane_debian_system/subplot.yaml new file mode 100644 index 0000000..b7f03cb --- /dev/null +++ b/roles/sane_debian_system/subplot.yaml @@ -0,0 +1,19 @@ +- then: the host has the {package} package installed + impl: + python: + function: host_has_package_installed + +- then: the host has an empty {pathname} directory + impl: + python: + function: host_directory_is_empty + +- then: the host has hostname {hostname} + impl: + python: + function: host_hostname_is + +- then: the host has {hostname} in /etc/hosts for {addr} + impl: + python: + function: host_hostname_has_address diff --git a/roles/sane_debian_system/tasks/apt.yml b/roles/sane_debian_system/tasks/apt.yml index 84c6420..0da3332 100644 --- a/roles/sane_debian_system/tasks/apt.yml +++ b/roles/sane_debian_system/tasks/apt.yml @@ -1,9 +1,9 @@ # Safety check: make sure debian_codename is set. -- name: check that debian_codename is set +- name: check that sane_debian_system_codename is set shell: | - if [ "{{ debian_codename }}" = "" ] + if [ "{{ sane_debian_system_codename }}" = "" ] then - echo "You MUST set debian_codename" 1>&2 + echo "You MUST set sane_debian_system_codename" 1>&2 exit 1 fi @@ -11,8 +11,12 @@ # First update package lists. The ones that come with the image may be # badly out of date. # -# Ignore any error here so that later tasks can fix things such as a badly -# formed sources.list. +# Use shell to run apt-get, rather than the Ansible apt module, so +# that we can pass in the --allow-releaseinfo--change option. +- name: update package lists + shell: | + apt-get update --allow-releaseinfo-change + - name: update package lists ignore_errors: yes apt: @@ -24,11 +28,7 @@ # will still work. apt-transport-https is in the main Debian archive, # and we assume those are in the sources.list that come with the # image. -# -# Ignore any error here so that later tasks can fix things such as a badly -# formed sources.list. - name: install apt-transport-https - ignore_errors: yes apt: name: apt-transport-https @@ -37,26 +37,45 @@ src: sources.list.j2 dest: /etc/apt/sources.list +- name: "update package lists" + apt: + update_cache: yes + +- name: install necessary tools + apt: + name: + - sudo + +- name: "allow root to use sudo" + copy: + content: | + root ALL=(ALL:ALL) NOPASSWD: ALL + dest: /etc/sudoers.d/root + mode: 0600 + - name: additional sources.list.d/* - with_items: "{{ sources_lists }}" + with_items: "{{ sane_debian_system_sources_lists }}" apt_repository: repo: "{{ item.repo }}" update_cache: no - name: add archive signing keys - with_items: "{{ sources_lists }}" - apt_key: - data: "{{ item.signing_key }}" - state: present + with_items: "{{ sane_debian_system_sources_lists }}" + shell: | + key="{{ item.signing_key }}" + sum="$(echo -n "$key" | sha1sum | awk '{ print $1 }')" + echo "$key" > "/etc/apt/trusted.gpg.d/$sum.asc" when: item.signing_key is defined +# Use shell to run apt-get to update package lists so that we can pass +# in the --allow-releaseinfo--change option. - name: update package lists - apt: - update_cache: yes - cache_valid_time: 0 + shell: | + apt-get update --allow-releaseinfo-change + - name: add archive keyrings - with_items: "{{ sources_lists }}" + with_items: "{{ sane_debian_system_sources_lists }}" apt: name: "{{ item.keyring_package }}" when: item.keyring_package is defined diff --git a/roles/sane_debian_system/tasks/env.yml b/roles/sane_debian_system/tasks/env.yml index c62fca4..eedd864 100644 --- a/roles/sane_debian_system/tasks/env.yml +++ b/roles/sane_debian_system/tasks/env.yml @@ -2,35 +2,38 @@ apt: name: dbus -- name: set /etc/hostname - copy: - content: "{{ hostname }}" - dest: /etc/hostname - owner: root - group: root - mode: 0444 - when: hostname is defined +- name: "start dbus" + systemd: + name: dbus + daemon_reload: yes + enabled: yes + state: started -- name: add hostname to /etc/hosts - lineinfile: - dest: /etc/hosts - regexp: '^127\.0\.1\.1 ' - line: "127.0.1.1 {{ hostname }}" - when: hostname is defined +- name: set /etc/hostname + hostname: + name: "{{ sane_debian_system_hostname }}" + when: sane_debian_system_hostname != "" - name: set timezone timezone: - name: "{{ timezone }}" + name: "{{ sane_debian_system_timezone }}" - name: install environment packages apt: state: present name: - locales - - ntp + +- name: install systemd-timesyncd or ntp + shell: | + if apt-cache show systemd-timesyncd > /dev/null; then + DEBIAN_FRONTEND=noninteractife apt-get install -y systemd-timesyncd + else + DEBIAN_FRONTEND=noninteractife apt-get install -y ntp + fi - name: generate locales locale_gen: name: "{{ item }}" state: present - with_items: "{{ locales }}" + with_items: "{{ sane_debian_system_locales }}" diff --git a/roles/sane_debian_system/tasks/main.yml b/roles/sane_debian_system/tasks/main.yml index dcb3b60..bc8c6d3 100644 --- a/roles/sane_debian_system/tasks/main.yml +++ b/roles/sane_debian_system/tasks/main.yml @@ -1,2 +1,10 @@ -- include: apt.yml -- include: env.yml +- name: "sane_debian_system_version" + shell: | + [ "{{ sane_debian_system_version }}" = "2" ] || \ + (echo "Unexpected version {{ sane_debian_system_version }}" 1>&2; exit 1) + +- ansible.builtin.import_tasks: + file: apt.yml + +- ansible.builtin.import_tasks: + file: env.yml diff --git a/roles/sane_debian_system/templates/sources.list.j2 b/roles/sane_debian_system/templates/sources.list.j2 index 65e8706..897e2ce 100644 --- a/roles/sane_debian_system/templates/sources.list.j2 +++ b/roles/sane_debian_system/templates/sources.list.j2 @@ -1,12 +1 @@ -deb http://{{ debian_mirror }}/debian {{ debian_codename }} main - -{% if debian_codename != 'unstable' %} -deb http://security.debian.org/ {{ debian_codename }}/updates main -{% endif %} - -{% if debian_codename != 'buster' %} -{% if debian_codename != 'unstable' %} -deb http://{{ debian_mirror }}/debian {{ debian_codename }}-updates main -deb http://{{ debian_mirror }}/debian {{ debian_codename }}-backports main -{% endif %} -{% endif %} +deb http://{{ sane_debian_system_mirror }}/debian {{ sane_debian_system_codename }} main |