diff --git a/roles/podman_woodpecker_agent/defaults/main.yml b/roles/podman_woodpecker_agent/defaults/main.yml new file mode 100644 index 0000000..4fc3506 --- /dev/null +++ b/roles/podman_woodpecker_agent/defaults/main.yml @@ -0,0 +1,3 @@ +--- +podman_woodpecker_agent_filter_labels: "" +podman_woodpecker_agent_image_path: docker.io/woodpeckerci/woodpecker-agent diff --git a/roles/podman_woodpecker_agent/handlers/main.yml b/roles/podman_woodpecker_agent/handlers/main.yml new file mode 100644 index 0000000..68f9073 --- /dev/null +++ b/roles/podman_woodpecker_agent/handlers/main.yml @@ -0,0 +1,12 @@ +--- +- name: Reload systemd daemon + ansible.builtin.systemd_service: + daemon_reload: true + +- name: Reload user systemd daemon + ansible.builtin.systemd_service: + daemon_reload: true + scope: user + become_method: community.general.machinectl + become_user: "{{ podman_woodpecker_agent_user }}" + become: true diff --git a/roles/podman_woodpecker_agent/tasks/activate-proxies.yml b/roles/podman_woodpecker_agent/tasks/activate-proxies.yml new file mode 100644 index 0000000..c03d643 --- /dev/null +++ b/roles/podman_woodpecker_agent/tasks/activate-proxies.yml @@ -0,0 +1,11 @@ +--- +- name: Determine UID of workspace user + ansible.builtin.user: + name: "{{ workspace_user }}" + register: user_data + +- name: Activate Podman socket proxy for the workspace + ansible.builtin.systemd_service: + name: woodpecker-proxy@{{ user_data['uid'] }}.path + state: started + enabled: true diff --git a/roles/podman_woodpecker_agent/tasks/agents.yml b/roles/podman_woodpecker_agent/tasks/agents.yml new file mode 100644 index 0000000..5bcf514 --- /dev/null +++ b/roles/podman_woodpecker_agent/tasks/agents.yml @@ -0,0 +1,60 @@ +--- +- name: Create Woodpecker agent volume + containers.podman.podman_volume: + name: "woodpecker-agent-{{ workspace_user }}" + state: present + +- name: Create Woodpecker agent secret + containers.podman.podman_secret: + state: present + name: "woodpecker-agent-secret-{{ workspace_user }}" + data: "{{ podman_woodpecker_agent_secret }}" + # Necessary to make the module idempotent on Podman < v4.7 + # See: https://github.com/containers/ansible-podman-collections/issues/692 + skip_existing: true + +- name: Determine UID of workspace user + ansible.builtin.user: + name: "{{ workspace_user }}" + register: user_data + +- name: Create Woodpecker container + containers.podman.podman_container: + name: "woodpecker-agent-{{ user_data['uid'] }}" + state: present + image: "{{ podman_woodpecker_agent_image_path }}:{{ podman_woodpecker_version }}" + volumes: + - 'woodpecker-agent-{{ workspace_user }}:/etc/woodpecker' + - '/etc/timezone:/etc/timezone:ro' + - '/etc/localtime:/etc/localtime:ro' + - "/run/woodpecker/{{ user_data['uid'] }}.sock:/var/run/docker.sock" + env: + WOODPECKER_SERVER: "{{ podman_woodpecker_agent_server }}" + WOODPECKER_HOSTNAME: "{{ workspace_user }}" + # Nothing is using the healthcheck IIUC, so disabling it doesn't reduce functionality. + WOODPECKER_HEALTHCHECK: false + WOODPECKER_LOG_LEVEL: debug + WOODPECKER_BACKEND: docker + WOODPECKER_FILTER_LABELS: "{{ podman_woodpecker_agent_filter_labels }}" + secrets: + - "woodpecker-agent-secret-{{ workspace_user }},type=env,target=WOODPECKER_AGENT_SECRET" + generate_systemd: + restart_policy: always + path: ~/.config/systemd/user + after: "podman-proxy@{{ user_data['uid'] }}.target" + requires: "podman-proxy@{{ user_data['uid'] }}.target" + notify: Reload user systemd daemon + +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Start and enable Woodpecker services + ansible.builtin.systemd_service: + name: "{{ item }}" + daemon_reload: true + state: started + enabled: true + scope: user + loop: + - "podman-proxy@{{ user_data['uid'] }}.path" + - "container-woodpecker-agent-{{ user_data['uid'] }}.service" diff --git a/roles/podman_woodpecker_agent/tasks/machinectl.yml b/roles/podman_woodpecker_agent/tasks/machinectl.yml new file mode 100644 index 0000000..2d67059 --- /dev/null +++ b/roles/podman_woodpecker_agent/tasks/machinectl.yml @@ -0,0 +1,22 @@ +--- +- name: Create systemd user configuration directory + ansible.builtin.file: + dest: ~/.config/systemd/user + state: directory + mode: "0750" + +- name: Install systemd unit files for the proxy target + ansible.builtin.template: + src: "{{ item }}.j2" + dest: "~/.config/systemd/user/{{ item }}" + mode: "0644" + notify: Reload user systemd daemon + loop: + - podman-proxy@.path + - podman-proxy@.target + +- name: Create Woodpecker agents + ansible.builtin.include_tasks: agents.yml + loop: "{{ podman_woodpecker_agent_workspace_users }}" + loop_control: + loop_var: workspace_user diff --git a/roles/podman_woodpecker_agent/tasks/main.yml b/roles/podman_woodpecker_agent/tasks/main.yml new file mode 100644 index 0000000..8e8ef90 --- /dev/null +++ b/roles/podman_woodpecker_agent/tasks/main.yml @@ -0,0 +1,20 @@ +--- +- name: Configure proxies for the Podman sockets + ansible.builtin.import_tasks: socket-proxy.yml + +- name: Activate the workspace Podman systemd socket unit + ansible.builtin.systemd_service: + name: podman.socket + state: started + enabled: true + scope: user + become_method: community.general.machinectl + become_user: "{{ item }}" + become: true + loop: "{{ podman_woodpecker_agent_workspace_users }}" + +- name: Configure Woodpecker agent services + ansible.builtin.import_tasks: machinectl.yml + become_method: community.general.machinectl + become_user: "{{ podman_woodpecker_agent_user }}" + become: true diff --git a/roles/podman_woodpecker_agent/tasks/socket-proxy.yml b/roles/podman_woodpecker_agent/tasks/socket-proxy.yml new file mode 100644 index 0000000..e45d740 --- /dev/null +++ b/roles/podman_woodpecker_agent/tasks/socket-proxy.yml @@ -0,0 +1,26 @@ +--- +- name: Install proxy systemd units + ansible.builtin.template: + src: "{{ item }}.j2" + dest: "/etc/systemd/system/{{ item }}" + mode: "0644" + loop: + - woodpecker-proxy@.path + - woodpecker-proxy@.service + - woodpecker-proxy@.socket + notify: Reload systemd daemon + +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Install tmpfiles configuration + ansible.builtin.template: + src: tmpfiles.j2 + dest: /etc/tmpfiles.d/woodpecker.conf + mode: "0644" + +- name: Activate systemd units for the Podman sockets + ansible.builtin.include_tasks: activate-proxies.yml + loop: "{{ podman_woodpecker_agent_workspace_users }}" + loop_control: + loop_var: workspace_user diff --git a/roles/podman_woodpecker_agent/templates/podman-proxy@.path.j2 b/roles/podman_woodpecker_agent/templates/podman-proxy@.path.j2 new file mode 100644 index 0000000..1169799 --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/podman-proxy@.path.j2 @@ -0,0 +1,10 @@ +# {{ ansible_managed }} +[Unit] +Description=Watch for the creation of the workspace user Podman socket + +[Path] +PathExists=/run/woodpecker/%i.sock +Unit=podman-proxy@%i.target + +[Install] +WantedBy=default.target diff --git a/roles/podman_woodpecker_agent/templates/podman-proxy@.target.j2 b/roles/podman_woodpecker_agent/templates/podman-proxy@.target.j2 new file mode 100644 index 0000000..bff0a58 --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/podman-proxy@.target.j2 @@ -0,0 +1,3 @@ +# {{ ansible_managed }} +[Unit] +Description=The proxied socket to the Podman service is available to be mounted diff --git a/roles/podman_woodpecker_agent/templates/tmpfiles.j2 b/roles/podman_woodpecker_agent/templates/tmpfiles.j2 new file mode 100644 index 0000000..927170d --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/tmpfiles.j2 @@ -0,0 +1,2 @@ +# {{ ansible_managed }} +D /run/woodpecker 0750 root woodpecker-agent diff --git a/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.path.j2 b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.path.j2 new file mode 100644 index 0000000..81a4c13 --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.path.j2 @@ -0,0 +1,10 @@ +# {{ ansible_managed }} +[Unit] +Description=Watch for the creation of the workspace user Podman socket + +[Path] +PathExists=/run/user/%i/podman/podman.sock +Unit=woodpecker-proxy@%i.socket + +[Install] +WantedBy=multi-user.target diff --git a/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.service.j2 b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.service.j2 new file mode 100644 index 0000000..17e3afe --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.service.j2 @@ -0,0 +1,9 @@ +# {{ ansible_managed }} +[Unit] +Requires=woodpecker-proxy@%i.socket +After=woodpecker-proxy@%i.socket + +[Service] +ExecStart=/usr/lib/systemd/systemd-socket-proxyd /run/user/%i/podman/podman.sock +PrivateTmp=yes +PrivateNetwork=yes diff --git a/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.socket.j2 b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.socket.j2 new file mode 100644 index 0000000..f45b3f9 --- /dev/null +++ b/roles/podman_woodpecker_agent/templates/woodpecker-proxy@.socket.j2 @@ -0,0 +1,8 @@ +# {{ ansible_managed }} +[Unit] +Description=Proxy connections + +[Socket] +ListenStream=/run/woodpecker/%i.sock +SocketMode=0660 +SocketUser={{ podman_woodpecker_agent_user }}