diff --git a/roles/container/meta/argument_specs.yaml b/roles/container/meta/argument_specs.yaml index 61fe9e0..52196aa 100644 --- a/roles/container/meta/argument_specs.yaml +++ b/roles/container/meta/argument_specs.yaml @@ -53,6 +53,16 @@ argument_specs: type: bool required: false default: false + user: + description: Volume owner uid. Only applicable if mount type is volume. + type: str + required: false + default: "" + group: + description: Volume owner gid. Only applicable if mount type is volume. + type: str + required: false + default: "" container_publish_ports: description: "A list of published ports in docker format (::)" diff --git a/roles/container/tasks/main.yaml b/roles/container/tasks/main.yaml index 92b887d..f8af8fe 100644 --- a/roles/container/tasks/main.yaml +++ b/roles/container/tasks/main.yaml @@ -11,6 +11,17 @@ loop_control: loop_var: network +- name: Create volumes for container {{ container_name }} + ansible.builtin.include_role: + name: volume + vars: + volume_name: "{{ volume.source }}" + volume_uid: "{{ volume.user | default('') }}" + volume_gid: "{{ volume.group | default('') }}" + loop: "{{ _container_volumes }}" + loop_control: + loop_var: volume + - name: Create secrets for container {{ container_name }} containers.podman.podman_secret: name: "{{ item.name }}" @@ -24,7 +35,7 @@ name: "{{ container_name }}" command: "{{ container_command or omit }}" user: "{{ container_user or omit }}" - mount: "{{ container_mounts | map('items') | map('map', 'join', '=') | map('join', ',') }}" + mount: "{{ _container_mounts | map('items') | map('map', 'join', '=') | map('join', ',') }}" network: "{{ container_networks | map('regex_replace', '$', '.network') }}" publish: "{{ container_publish_ports }}" secrets: "{{ container_secrets | map(attribute='name') }}" diff --git a/roles/container/vars/main.yaml b/roles/container/vars/main.yaml index f90e2d2..5f2dce2 100644 --- a/roles/container/vars/main.yaml +++ b/roles/container/vars/main.yaml @@ -1,4 +1,25 @@ --- +_container_volumes: "{{ container_mounts | selectattr('type', '==', 'volume') }}" + +_container_mount_sources: "{{ container_mounts | map(attribute='source') }}" +_container_mount_destinations: "{{ container_mounts | map(attribute='destination') }}" + +_container_volume_mount_sources: >- + {{ + _container_volumes + | map(attribute='source') + | map('regex_replace', '$', '.volume') + | map('community.general.dict_kv', 'source') + }} + +_container_mounts: >- + {{ + container_mounts | selectattr('type', '!=', 'volume') + + container_mounts | selectattr('type', '==', 'volume') + | community.general.remove_keys(['user', 'group']) + | zip(_container_volume_mount_sources) | map('combine') + }} + _container_quadlet_unit_options: | [Unit] Description=Container {{ container_name }} diff --git a/roles/volume/README.md b/roles/volume/README.md new file mode 100644 index 0000000..de79822 --- /dev/null +++ b/roles/volume/README.md @@ -0,0 +1 @@ +Sets up podman volume with systemd unit (quadlet) diff --git a/roles/volume/defaults/main.yaml b/roles/volume/defaults/main.yaml new file mode 100644 index 0000000..54af040 --- /dev/null +++ b/roles/volume/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +volume_uid: "" +volume_gid: "" diff --git a/roles/volume/meta/argument_specs.yaml b/roles/volume/meta/argument_specs.yaml new file mode 100644 index 0000000..c357a23 --- /dev/null +++ b/roles/volume/meta/argument_specs.yaml @@ -0,0 +1,19 @@ +--- +argument_specs: + main: + description: Sets up podman volume with systemd unit (quadlet) + options: + volume_name: + description: Name of the volume. Must be unique within a host. + type: str + required: true + volume_uid: + description: Volume uid (the volume owner) + type: str + required: false + default: "" + volume_gid: + description: Volume gid (the volume owner) + type: str + required: false + default: "" diff --git a/roles/volume/meta/main.yaml b/roles/volume/meta/main.yaml new file mode 100644 index 0000000..d80fa53 --- /dev/null +++ b/roles/volume/meta/main.yaml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: podman diff --git a/roles/volume/tasks/main.yaml b/roles/volume/tasks/main.yaml new file mode 100644 index 0000000..767a472 --- /dev/null +++ b/roles/volume/tasks/main.yaml @@ -0,0 +1,11 @@ +--- +- name: Validate inputs + ansible.builtin.import_tasks: validation.yaml + +- name: Create container volume service {{ volume_name }} + containers.podman.podman_volume: + name: "{{ volume_name }}" + options: "{{ volume_options }}" + state: quadlet + quadlet_file_mode: "0644" + notify: Reload systemd daemon diff --git a/roles/volume/tasks/validation.yaml b/roles/volume/tasks/validation.yaml new file mode 100644 index 0000000..ab26323 --- /dev/null +++ b/roles/volume/tasks/validation.yaml @@ -0,0 +1,7 @@ +--- +- name: Assert volume_uid and volume_gid are strings + ansible.builtin.assert: + that: + - volume_uid is string + - volume_gid is string + fail_msg: "volume_uid and volume_gid must be strings, not int." diff --git a/roles/volume/vars/main.yaml b/roles/volume/vars/main.yaml new file mode 100644 index 0000000..3535dfe --- /dev/null +++ b/roles/volume/vars/main.yaml @@ -0,0 +1,6 @@ +--- +volume_mount_options_incl_empty: + - "{{ 'uid=' ~ volume_uid if volume_uid | length > 0 else '' }}" + - "{{ 'gid=' ~ volume_gid if volume_gid | length > 0 else '' }}" +volume_mount_options: "{{ volume_mount_options_incl_empty | select('!=', '') | list }}" +volume_options: "{{ ['o=' ~ volume_mount_options | join(',')] if volume_mount_options | length > 0 else [] }}"