summaryrefslogtreecommitdiff
path: root/roles/sane_debian_system
diff options
context:
space:
mode:
Diffstat (limited to 'roles/sane_debian_system')
-rw-r--r--roles/sane_debian_system/defaults/main.yml21
-rw-r--r--roles/sane_debian_system/subplot.md66
-rw-r--r--roles/sane_debian_system/subplot.py48
-rw-r--r--roles/sane_debian_system/subplot.yaml19
-rw-r--r--roles/sane_debian_system/tasks/apt.yml55
-rw-r--r--roles/sane_debian_system/tasks/env.yml37
-rw-r--r--roles/sane_debian_system/tasks/main.yml12
-rw-r--r--roles/sane_debian_system/templates/sources.list.j213
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