From 68aaa045bdd52ff123c8beaf5dee15484820b7c5 Mon Sep 17 00:00:00 2001
From: godog <godog@autistici.org>
Date: Sun, 15 Dec 2019 15:31:20 +0100
Subject: [PATCH] docker: add podman as container runtime for Buster

---
 roles/base/tasks/apt.yml              | 12 +-------
 roles/docker/defaults/main.yml        |  2 ++
 roles/docker/files/registries.conf    |  2 ++
 roles/docker/tasks/buster_upgrade.yml | 28 ++++++++++++++++++
 roles/docker/tasks/docker.yml         | 32 ++++++++++++++++++++
 roles/docker/tasks/main.yml           | 42 +++++++++------------------
 roles/docker/tasks/podman.yml         | 32 ++++++++++++++++++++
 roles/docker/tasks/start.yml          |  7 +++++
 roles/docker/templates/run.sh.j2      | 22 ++++++++++++++
 roles/docker/templates/systemd.j2     |  5 +++-
 test/integration-test-docker.yml      |  7 ++++-
 11 files changed, 149 insertions(+), 42 deletions(-)
 create mode 100644 roles/docker/files/registries.conf
 create mode 100644 roles/docker/tasks/buster_upgrade.yml
 create mode 100644 roles/docker/tasks/docker.yml
 create mode 100644 roles/docker/tasks/podman.yml

diff --git a/roles/base/tasks/apt.yml b/roles/base/tasks/apt.yml
index 48307a13..19038e0e 100644
--- a/roles/base/tasks/apt.yml
+++ b/roles/base/tasks/apt.yml
@@ -65,7 +65,6 @@
       - rsync
       - git
       - python-pip
-      - python-docker
       - ntp
       - openssl
       - curl
@@ -77,16 +76,6 @@
       - restic
       - runcron
 
-# With the default credentials handler 'docker login' stops working with:
-# error getting credentials - err: exit status 1, out: Cannot autolaunch
-# D-Bus without X11 $DISPLAY
-# See also https://bugs.debian.org/910823
-- name: Fix docker login on Buster
-  file:
-    state: absent
-    path: /usr/bin/docker-credential-secretservice
-  when: float_debian_dist == 'buster'
-
 - name: Install Stretch packages
   apt:
     name: "{{ packages }}"
@@ -95,6 +84,7 @@
     packages:
       - apt-transport-https
       - liblz4-tool
+      - python-docker
   when: float_debian_dist == 'stretch'
 
 - name: Install Buster packages
diff --git a/roles/docker/defaults/main.yml b/roles/docker/defaults/main.yml
index bfb3b49a..85db0284 100644
--- a/roles/docker/defaults/main.yml
+++ b/roles/docker/defaults/main.yml
@@ -3,6 +3,8 @@
 docker_registry_url: ""
 docker_registry_username: ""
 docker_registry_password: ""
+
+# The following options are not used on >= Buster
 docker_daemon_config:
   log-driver: "local"
   log-opts:
diff --git a/roles/docker/files/registries.conf b/roles/docker/files/registries.conf
new file mode 100644
index 00000000..4496b5d1
--- /dev/null
+++ b/roles/docker/files/registries.conf
@@ -0,0 +1,2 @@
+# Dummy file to mute podman's warning
+# WARN[0000] unable to find /etc/containers/registries.conf. some podman (image shortnames) commands may be limited
diff --git a/roles/docker/tasks/buster_upgrade.yml b/roles/docker/tasks/buster_upgrade.yml
new file mode 100644
index 00000000..0207ec14
--- /dev/null
+++ b/roles/docker/tasks/buster_upgrade.yml
@@ -0,0 +1,28 @@
+- name: Remove docker.com GPG key
+  apt_key:
+    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
+    url: https://download.docker.com/linux/debian/gpg
+    state: absent
+
+- name: Remove docker.com package repository
+  apt_repository:
+    repo: "deb [arch=amd64] {% if apt_proxy is defined %}http://{{ apt_proxy }}/HTTPS/{% else %}https:{% endif %}//download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
+    state: absent
+
+- name: Remove docker packages
+  apt:
+    name: "{{ packages }}"
+    state: absent
+  vars:
+    packages:
+      - docker-ce
+      - systemd-docker
+
+- name: Remove docker files
+  file:
+    dest: "{{ item }}"
+    state: absent
+  with_items:
+    - /etc/docker
+    - /usr/local/bin/docker-cleanup
+    - /etc/cron.d/docker-cleanup
diff --git a/roles/docker/tasks/docker.yml b/roles/docker/tasks/docker.yml
new file mode 100644
index 00000000..baa9ad7d
--- /dev/null
+++ b/roles/docker/tasks/docker.yml
@@ -0,0 +1,32 @@
+# TODO: switch to keyserver once the apt_key --no-tty bug in Ansible is fixed.
+- name: Install docker.com GPG key
+  apt_key:
+    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
+    url: https://download.docker.com/linux/debian/gpg
+    state: present
+
+- name: Install docker.com package repository
+  apt_repository:
+    repo: "deb [arch=amd64] {% if apt_proxy is defined %}http://{{ apt_proxy }}/HTTPS/{% else %}https:{% endif %}//download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
+    state: present
+
+- file:
+    path: "/etc/docker"
+    state: directory
+
+- name: Configure docker daemon
+  template:
+    src: daemon.json.j2
+    dest: /etc/docker/daemon.json
+  notify:
+    - restart docker
+
+- name: Install docker packages
+  apt:
+    name: "{{ packages }}"
+    state: present
+  vars:
+    packages:
+      - docker-ce
+      - systemd-docker
+
diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml
index dada82b9..c56866a5 100644
--- a/roles/docker/tasks/main.yml
+++ b/roles/docker/tasks/main.yml
@@ -1,36 +1,20 @@
 ---
 
-# TODO: switch to keyserver once the apt_key --no-tty bug in Ansible is fixed.
-- name: Install docker.com GPG key
-  apt_key:
-    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
-    url: https://download.docker.com/linux/debian/gpg
-    state: present
-
-- name: Install docker.com package repository
-  apt_repository:
-    repo: "deb [arch=amd64] {% if apt_proxy is defined %}http://{{ apt_proxy }}/HTTPS/{% else %}https:{% endif %}//download.docker.com/linux/debian {{ ansible_distribution_release }} stable"
-    state: present
+- set_fact:
+    container_runtime: "podman"
 
-- file:
-    path: "/etc/docker"
-    state: directory
+- set_fact:
+    container_runtime: "docker"
+  when: "float_debian_dist == 'stretch'"
 
-- name: Configure docker daemon
-  template:
-    src: daemon.json.j2
-    dest: /etc/docker/daemon.json
-  notify:
-    - restart docker
-
-- name: Install docker packages
-  apt:
-    name: "{{ packages }}"
-    state: present
-  vars:
-    packages:
-      - docker-ce
-      - systemd-docker
+- include_tasks: buster_upgrade.yml
+  when: "float_debian_dist == 'buster'"
+
+- include_tasks: docker.yml
+  when: "container_runtime == 'docker'"
+
+- include_tasks: podman.yml
+  when: "container_runtime == 'podman'"
 
 - name: Login to the Docker registry
   command: docker login -u "{{ docker_registry_username }}" -p "{{ docker_registry_password }}" "{{ docker_registry_url }}"
diff --git a/roles/docker/tasks/podman.yml b/roles/docker/tasks/podman.yml
new file mode 100644
index 00000000..0d682d0b
--- /dev/null
+++ b/roles/docker/tasks/podman.yml
@@ -0,0 +1,32 @@
+---
+
+# TODO: switch to keyserver once the apt_key --no-tty bug in Ansible is fixed.
+- name: Install project atomic PPA GPG key
+  apt_key:
+    id: 018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D
+    url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x8becf1637ad8c79d'
+    state: present
+
+- name: Install project atomic PPA repository
+  apt_repository:
+    repo: "deb http://ppa.launchpad.net/projectatomic/ppa/ubuntu disco main"
+    state: present
+
+- name: Install podman packages
+  apt:
+    name: "{{ packages }}"
+    state: present
+  vars:
+    packages:
+      - podman
+
+- name: Symlink podman to docker
+  file:
+    src: /usr/bin/podman
+    dest: /usr/bin/docker
+    state: link
+
+- name: Install podman registries.conf
+  copy:
+    dest: /etc/containers/registries.conf
+    src: registries.conf
diff --git a/roles/docker/tasks/start.yml b/roles/docker/tasks/start.yml
index dce9d140..fe7660f6 100644
--- a/roles/docker/tasks/start.yml
+++ b/roles/docker/tasks/start.yml
@@ -59,6 +59,13 @@
         name: "{{ container.image }}"
         force: true
       register: docker_image
+      when: "container_runtime == 'docker'"
+
+    - name: Pull the Docker image {{ container.image }}
+      # Ansible >= 2.8 ships with podman_image
+      command: "podman pull {{ container.image }}"
+      register: podman_image
+      when: "container_runtime == 'podman'"
 
     - name: Start the systemd unit {{ systemd_service }}
       systemd:
diff --git a/roles/docker/templates/run.sh.j2 b/roles/docker/templates/run.sh.j2
index 3dd7f225..77c8825e 100644
--- a/roles/docker/templates/run.sh.j2
+++ b/roles/docker/templates/run.sh.j2
@@ -55,7 +55,29 @@ for gid in $(id -G {{ container_user }}); do
 done
 {% endif %}
 
+{% if container_runtime == 'podman' %}
+# Remove 'created' (but never started) and 'exited' containers to avoid name conflicts
+podman ps --quiet --all \
+  --filter status=created \
+  --filter name={{ service.name }}-{{ container.name }} \
+  | xargs --no-run-if-empty podman rm
+
+podman ps --quiet --all \
+  --filter status=exited \
+  --filter name={{ service.name }}-{{ container.name }} \
+  | xargs --no-run-if-empty podman rm
+
+exec /usr/bin/podman run --env-host \
+  --cgroup-manager=cgroupfs \
+  --cgroup-parent /system.slice/{{ systemd_service }} \
+  --rm --name {{ service.name }}-{{ container.name }} \
+  $opts \
+  {{ container.image }} {{ container.get('args', '') }}
+{% endif %}
+
+{% if container_runtime == 'docker' %}
 exec /usr/bin/systemd-docker --env run \
   --rm --name {{ service.name }}-{{ container.name }} \
   $opts \
   {{ container.image }} {{ container.get('args', '') }}
+{% endif %}
diff --git a/roles/docker/templates/systemd.j2 b/roles/docker/templates/systemd.j2
index 3a64bd0f..7ba81e14 100644
--- a/roles/docker/templates/systemd.j2
+++ b/roles/docker/templates/systemd.j2
@@ -1,7 +1,9 @@
 [Unit]
 Description={{ service.name }}/{{ container.name }}
+{% if container_runtime == 'docker' %}
 After=docker.service
 Requires=docker.service
+{% endif %}
 
 [Service]
 EnvironmentFile=-/etc/default/{{ service.name }}-{{ container.name }}
@@ -22,4 +24,5 @@ CPUQuota={{ 100 * container.resources.cpu }}%
 LimitNOFILE=65535
 
 [Install]
-WantedBy=multi-user.target docker.service
+WantedBy=multi-user.target {{ 'docker.service' if container_runtime == 'docker' else '' }}
+Alias={{ service.name }}-{{ container.name }}
diff --git a/test/integration-test-docker.yml b/test/integration-test-docker.yml
index bf0a3944..39d2038a 100644
--- a/test/integration-test-docker.yml
+++ b/test/integration-test-docker.yml
@@ -13,6 +13,11 @@
       docker_image:
         name: registry.git.autistici.org/ai3/float:integration-test
         force: true
+      when: "float_debian_dist == 'stretch'"
+
+    - name: Setup test Docker image
+      command: "podman pull registry.git.autistici.org/ai3/float:integration-test"
+      when: "float_debian_dist != 'stretch'"
 
     - name: Run tests
-      command: docker run --mount type=bind,source=/tmp/test-config.yml,destination=/test-config.yml registry.git.autistici.org/ai3/float:integration-test
+      command: docker run --net host --mount type=bind,source=/tmp/test-config.yml,destination=/test-config.yml registry.git.autistici.org/ai3/float:integration-test
-- 
GitLab