Compare commits
6 Commits
7d8b1cb258
...
a10bf366e6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a10bf366e6 | ||
|
|
78860da6a4 | ||
|
|
aa9eabf19c | ||
|
|
2e14434c9f | ||
|
|
8f29c2815e | ||
|
|
60529c18cd |
@@ -94,7 +94,7 @@ argument_specs:
|
|||||||
default: []
|
default: []
|
||||||
elements: str
|
elements: str
|
||||||
container_secrets:
|
container_secrets:
|
||||||
description: A list of secrets available to the container in /run/secrets/<secret name>
|
description: A list of secrets available to the container as file or environment variable
|
||||||
type: list
|
type: list
|
||||||
required: false
|
required: false
|
||||||
default: []
|
default: []
|
||||||
@@ -122,6 +122,13 @@ argument_specs:
|
|||||||
- mount
|
- mount
|
||||||
- env
|
- env
|
||||||
default: mount
|
default: mount
|
||||||
|
target:
|
||||||
|
description: >
|
||||||
|
Where the secret will be available inside the container. If type is mount, this is
|
||||||
|
either a full file path or a filename under /run/secrets. If type is env, this is
|
||||||
|
the name of the environment variable. Defaults to secret name.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
|
||||||
container_env:
|
container_env:
|
||||||
description: A dict of environment variables for the container
|
description: A dict of environment variables for the container
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
network: "{{ container_networks | map('regex_replace', '$', '.network') }}"
|
network: "{{ container_networks | map('regex_replace', '$', '.network') }}"
|
||||||
publish: "{{ container_publish_ports }}"
|
publish: "{{ container_publish_ports }}"
|
||||||
secrets: "{{ _container_secrets }}"
|
secrets: "{{ _container_secrets }}"
|
||||||
env: "{{ container_env.keys() | zip(container_env.values() | map('quote')) | community.general.dict }}"
|
env: "{{ container_env }}"
|
||||||
state: quadlet
|
state: quadlet
|
||||||
quadlet_file_mode: "0600"
|
quadlet_file_mode: "0600"
|
||||||
quadlet_options: "{{ _container_quadlet_options }}"
|
quadlet_options: "{{ _container_quadlet_options }}"
|
||||||
|
|||||||
@@ -29,7 +29,14 @@ _container_secrets: >-
|
|||||||
| zip(
|
| zip(
|
||||||
container_secrets
|
container_secrets
|
||||||
| map(attribute='type', default='mount')
|
| map(attribute='type', default='mount')
|
||||||
| map('regex_replace', '^', 'type=')
|
| map('regex_replace', '^', 'type='),
|
||||||
|
container_secrets
|
||||||
|
| map(attribute='name')
|
||||||
|
| map('community.general.dict_kv', 'target')
|
||||||
|
| zip(container_secrets)
|
||||||
|
| map('combine')
|
||||||
|
| map(attribute='target')
|
||||||
|
| map('regex_replace', '^', 'target=')
|
||||||
)
|
)
|
||||||
| map('join', ',')
|
| map('join', ',')
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ service_container_secrets: []
|
|||||||
service_container_env: {}
|
service_container_env: {}
|
||||||
|
|
||||||
service_database_type: none
|
service_database_type: none
|
||||||
|
service_postgres_image: docker.io/library/postgres
|
||||||
|
service_redis: false
|
||||||
|
|
||||||
service_additional_containers: []
|
service_additional_containers: []
|
||||||
|
|
||||||
|
|||||||
@@ -114,10 +114,12 @@ argument_specs:
|
|||||||
default: ""
|
default: ""
|
||||||
service_container_secrets:
|
service_container_secrets:
|
||||||
description:
|
description:
|
||||||
- A list of secrets available to the service container in /run/secrets/<service name>-<secret name>
|
|
||||||
- >
|
- >
|
||||||
A dict of secrets and their values (including autogenerated values) is available as `service_podman_secrets` for use
|
A list of secrets available to the service container as file or environment variable
|
||||||
in tepmlates or environment variables. This should only be used if the container doesn't support reading the secret from file
|
- >
|
||||||
|
A dict of secrets and their values (including autogenerated values) is available as
|
||||||
|
`service_podman_secrets` for use in templates. This should only be used if the
|
||||||
|
container doesn't support reading the secret from file or environment variable.
|
||||||
type: list
|
type: list
|
||||||
required: false
|
required: false
|
||||||
default: []
|
default: []
|
||||||
@@ -129,8 +131,12 @@ argument_specs:
|
|||||||
required: true
|
required: true
|
||||||
value:
|
value:
|
||||||
description:
|
description:
|
||||||
- Value of the secret. Defaults to a 128-character random string containing alphanumeric characters.
|
- >
|
||||||
- If the value is not explicitly set, it will not be changed if the secret already exists.
|
Value of the secret. Defaults to a 128-character random string containing
|
||||||
|
alphanumeric characters.
|
||||||
|
- >
|
||||||
|
If the value is not explicitly set, it will not be changed if the secret
|
||||||
|
already exists.
|
||||||
type: str
|
type: str
|
||||||
required: false
|
required: false
|
||||||
length:
|
length:
|
||||||
@@ -145,6 +151,14 @@ argument_specs:
|
|||||||
- mount
|
- mount
|
||||||
- env
|
- env
|
||||||
default: mount
|
default: mount
|
||||||
|
target:
|
||||||
|
description: >
|
||||||
|
Where the secret will be available inside the container. If type is mount, this is
|
||||||
|
either a full file path or a filename under /run/secrets. If type is env, this is
|
||||||
|
the name of the environment variable. Defaults to secret name.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
|
||||||
service_container_env:
|
service_container_env:
|
||||||
description: A dict of environment variables for the service container(s)
|
description: A dict of environment variables for the service container(s)
|
||||||
type: dict
|
type: dict
|
||||||
@@ -155,10 +169,10 @@ argument_specs:
|
|||||||
description:
|
description:
|
||||||
- Database type to set up.
|
- Database type to set up.
|
||||||
- >
|
- >
|
||||||
It will be run in a docker container accessible to the service at
|
It will be run in a container accessible to the service at
|
||||||
host {{ service_name }}-{{ service_database_type }} on the default port.
|
host {{ service_name }}-{{ service_database_type }} on the default port.
|
||||||
- The database user will be {{ service_name }}
|
- The database user will be {{ service_name }}
|
||||||
- The password will be accessible as secret at /run/secrets/{{ service_name }}-{{ service_database_type }}
|
- The password will be accessible as secret at /run/secrets/{{ service_database_type }}
|
||||||
- >
|
- >
|
||||||
The password will also be available as the
|
The password will also be available as the
|
||||||
service_podman_secrets['{{ service_name }}-{{ service_database_type }}'] variable.
|
service_podman_secrets['{{ service_name }}-{{ service_database_type }}'] variable.
|
||||||
@@ -168,17 +182,30 @@ argument_specs:
|
|||||||
- postgres
|
- postgres
|
||||||
- none
|
- none
|
||||||
default: none
|
default: none
|
||||||
|
service_postgres_image:
|
||||||
|
description: Postgresql image to use.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: docker.io/library/postgres
|
||||||
service_postgres_tag:
|
service_postgres_tag:
|
||||||
description:
|
description:
|
||||||
- Postgresql version to use.
|
- Postgresql version to use.
|
||||||
- Can be debian (n) or alpine-based (n-alpine), where n can be major version like 14 or minor like 14.13.
|
- Can be debian (n) or alpine-based (n-alpine), where n can be major version like 14 or minor like 14.13.
|
||||||
- Required if service_database_type is postgres, does nothing otherwise
|
- Required if service_database_type is postgres, does nothing otherwise
|
||||||
|
- If a custom postgres image is specified, see that image documentation for supported tags.
|
||||||
type: str
|
type: str
|
||||||
required: false
|
required: false
|
||||||
|
service_redis:
|
||||||
|
description: >-
|
||||||
|
Whether to install redis in a container accessible to the service at host
|
||||||
|
{{ service_name }}-redis.
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
service_additional_containers:
|
service_additional_containers:
|
||||||
description:
|
description:
|
||||||
- List of additional containers for the sercice.
|
- List of additional containers for the service.
|
||||||
- >
|
- >
|
||||||
Will inherit most options from main service container, except for publish_ports.
|
Will inherit most options from main service container, except for publish_ports.
|
||||||
All options can be overridden per-container.
|
All options can be overridden per-container.
|
||||||
@@ -245,6 +272,53 @@ argument_specs:
|
|||||||
type: dict
|
type: dict
|
||||||
required: false
|
required: false
|
||||||
default: {}
|
default: {}
|
||||||
|
secrets:
|
||||||
|
description:
|
||||||
|
- >
|
||||||
|
A list of secrets available to the service container as file or environment
|
||||||
|
variable
|
||||||
|
- >
|
||||||
|
A dict of secrets and their values (including autogenerated values) is available as
|
||||||
|
`service_podman_secrets` for use in templates. This should only be used if the
|
||||||
|
container doesn't support reading the secret from file or environment variable.
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
default: []
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
description: Name of the secret
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
value:
|
||||||
|
description:
|
||||||
|
- >
|
||||||
|
Value of the secret. Defaults to a 128-character random string containing
|
||||||
|
alphanumeric characters.
|
||||||
|
- >
|
||||||
|
If the value is not explicitly set, it will not be changed if the secret
|
||||||
|
already exists.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
length:
|
||||||
|
description: Length of randomly generated string
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
default: 128
|
||||||
|
type:
|
||||||
|
description: How the secret will be exposed to the container
|
||||||
|
type: str
|
||||||
|
choices:
|
||||||
|
- mount
|
||||||
|
- env
|
||||||
|
default: mount
|
||||||
|
target:
|
||||||
|
description: >
|
||||||
|
Where the secret will be available inside the container. If type is mount, this is
|
||||||
|
either a full file path or a filename under /run/secrets. If type is env, this is
|
||||||
|
the name of the environment variable. Defaults to secret name.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
|
||||||
service_requires:
|
service_requires:
|
||||||
description: List of systemd units this service container depends on.
|
description: List of systemd units this service container depends on.
|
||||||
|
|||||||
20
roles/service/tasks/additional.yaml
Normal file
20
roles/service/tasks/additional.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Additional container {{ container ~ ' for ' ~ service_name }}
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: container
|
||||||
|
vars:
|
||||||
|
container_name: "{{ container.name }}"
|
||||||
|
container_image: "{{ container.image | default(service_container_image) }}"
|
||||||
|
container_image_creds: "{{ service_container_image_creds }}"
|
||||||
|
container_user: "{{ service_container_user }}"
|
||||||
|
container_mounts: "{{ container.mounts | default(_service_container_mounts) }}"
|
||||||
|
container_publish_ports: "{{ container.publish_ports | default([]) }}"
|
||||||
|
container_networks: "{{ _service_container_networks }}"
|
||||||
|
container_secrets: "{{ container.secrets | default(_service_container_secrets) }}"
|
||||||
|
container_env: "{{ container.env | default(service_container_env) }}"
|
||||||
|
container_requires: "{{ _service_container_requires }}"
|
||||||
|
container_wants: "{{ service_wants }}"
|
||||||
|
container_auto_update: "{{ service_auto_update }}"
|
||||||
|
loop: "{{ _service_additional_containers }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: container
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
name: container
|
name: container
|
||||||
vars:
|
vars:
|
||||||
container_name: "{{ service_name }}-{{ service_database_type }}" # This doesn't use _service_database_name to allow container role handlers to work
|
container_name: "{{ service_name }}-{{ service_database_type }}" # This doesn't use _service_database_name to allow container role handlers to work
|
||||||
container_image: "docker.io/library/postgres:{{ service_postgres_tag }}"
|
container_image: "{{ service_postgres_image }}:{{ service_postgres_tag }}"
|
||||||
container_mounts:
|
container_mounts:
|
||||||
- type: volume
|
- type: volume
|
||||||
source: "{{ _service_database_name }}"
|
source: "{{ _service_database_name }}"
|
||||||
@@ -13,8 +13,9 @@
|
|||||||
- "{{ service_name }}"
|
- "{{ service_name }}"
|
||||||
container_secrets:
|
container_secrets:
|
||||||
- name: "{{ _service_database_name }}"
|
- name: "{{ _service_database_name }}"
|
||||||
|
target: "{{ service_database_type }}"
|
||||||
container_env:
|
container_env:
|
||||||
POSTGRES_USER: "{{ service_name | replace('-', '_') }}"
|
POSTGRES_USER: "{{ service_name | replace('-', '_') }}"
|
||||||
POSTGRES_PASSWORD_FILE: "/run/secrets/{{ _service_database_name }}"
|
POSTGRES_PASSWORD_FILE: "/run/secrets/{{ service_database_type }}"
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
|
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
|
||||||
container_auto_update: "{{ service_auto_update }}"
|
container_auto_update: "{{ service_auto_update }}"
|
||||||
|
|||||||
@@ -6,10 +6,14 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
_service_container_mounts: []
|
_service_container_mounts: []
|
||||||
|
|
||||||
- name: Databse for {{ service_name }}
|
- name: Database for {{ service_name }}
|
||||||
ansible.builtin.include_tasks: database.yaml
|
ansible.builtin.include_tasks: database.yaml
|
||||||
when: _service_setup_database
|
when: _service_setup_database
|
||||||
|
|
||||||
|
- name: Redis for {{ service_name }}
|
||||||
|
ansible.builtin.include_tasks: redis.yaml
|
||||||
|
when: service_redis
|
||||||
|
|
||||||
- name: Secrets for {{ service_name }}
|
- name: Secrets for {{ service_name }}
|
||||||
ansible.builtin.include_tasks: secrets.yaml
|
ansible.builtin.include_tasks: secrets.yaml
|
||||||
when: _service_container_secrets | length > 0
|
when: _service_container_secrets | length > 0
|
||||||
@@ -18,6 +22,10 @@
|
|||||||
ansible.builtin.include_tasks: mounts.yaml
|
ansible.builtin.include_tasks: mounts.yaml
|
||||||
when: service_container_mounts | length > 0
|
when: service_container_mounts | length > 0
|
||||||
|
|
||||||
|
- name: Additional containers for {{ service_name }}
|
||||||
|
ansible.builtin.include_tasks: additional.yaml
|
||||||
|
when: _service_additional_containers | length > 0
|
||||||
|
|
||||||
- name: Main container for {{ service_name }}
|
- name: Main container for {{ service_name }}
|
||||||
ansible.builtin.import_role:
|
ansible.builtin.import_role:
|
||||||
name: container
|
name: container
|
||||||
@@ -28,7 +36,7 @@
|
|||||||
container_user: "{{ service_container_user }}"
|
container_user: "{{ service_container_user }}"
|
||||||
container_mounts: "{{ _service_container_mounts }}"
|
container_mounts: "{{ _service_container_mounts }}"
|
||||||
container_publish_ports: "{{ service_container_publish_ports }}"
|
container_publish_ports: "{{ service_container_publish_ports }}"
|
||||||
container_networks: "{{ [service_name] + service_container_additional_networks }}"
|
container_networks: "{{ _service_container_networks }}"
|
||||||
container_secrets: "{{ _service_container_secrets }}"
|
container_secrets: "{{ _service_container_secrets }}"
|
||||||
container_env: "{{ service_container_env }}"
|
container_env: "{{ service_container_env }}"
|
||||||
container_requires: "{{ _service_container_requires }}"
|
container_requires: "{{ _service_container_requires }}"
|
||||||
|
|||||||
10
roles/service/tasks/redis.yaml
Normal file
10
roles/service/tasks/redis.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Redis container for {{ service_name }}
|
||||||
|
ansible.builtin.import_role:
|
||||||
|
name: container
|
||||||
|
vars:
|
||||||
|
container_name: "{{ service_name }}-redis"
|
||||||
|
container_image: docker.io/valkey/valkey:alpine
|
||||||
|
container_networks:
|
||||||
|
- "{{ service_name }}"
|
||||||
|
container_auto_update: "{{ service_auto_update }}"
|
||||||
@@ -5,20 +5,50 @@ _service_host_directory: "/srv/{{ service_name }}"
|
|||||||
_service_setup_database: "{{ service_database_type != 'none' }}"
|
_service_setup_database: "{{ service_database_type != 'none' }}"
|
||||||
_service_database_name: "{{ service_name }}-{{ service_database_type }}"
|
_service_database_name: "{{ service_name }}-{{ service_database_type }}"
|
||||||
|
|
||||||
_service_container_secrets: >
|
_service_container_networks: "{{ [service_name] + service_container_additional_networks }}"
|
||||||
|
|
||||||
|
_service_container_secrets: >-
|
||||||
{{
|
{{
|
||||||
service_container_secrets
|
service_container_secrets
|
||||||
| zip(service_container_secrets
|
| map(attribute='name')
|
||||||
| map(attribute='name')
|
| map('community.general.dict_kv', 'target')
|
||||||
| map('regex_replace', '^', service_name ~ '-')
|
| zip(
|
||||||
| map('community.general.dict_kv', 'name')
|
service_container_secrets,
|
||||||
|
service_container_secrets
|
||||||
|
| map(attribute='name')
|
||||||
|
| map('regex_replace', '^', service_name ~ '-')
|
||||||
|
| map('community.general.dict_kv', 'name')
|
||||||
)
|
)
|
||||||
| map('combine')
|
| map('combine')
|
||||||
+ ([{'name': _service_database_name }] if _service_setup_database else [])
|
+ ([{'name': _service_database_name, 'target': service_database_type }] if _service_setup_database else [])
|
||||||
}}
|
}}
|
||||||
|
|
||||||
_service_container_requires: "{{ service_requires + ([_service_database_name + '.service'] if _service_setup_database else []) }}"
|
_service_additional_containers: >-
|
||||||
_service_container_wants: "{{ service_wants + ([service_name + '-socat.socket'] if service_domains | length > 0 else []) }}"
|
{{
|
||||||
|
service_additional_containers
|
||||||
|
| zip(
|
||||||
|
service_additional_containers
|
||||||
|
| map(attribute='name')
|
||||||
|
| map('regex_replace', '^', service_name ~ '-')
|
||||||
|
| map('community.general.dict_kv', 'name')
|
||||||
|
)
|
||||||
|
| map('combine')
|
||||||
|
}}
|
||||||
|
|
||||||
|
_service_container_requires: >-
|
||||||
|
{{
|
||||||
|
service_requires
|
||||||
|
+ ([_service_database_name + '.service'] if _service_setup_database else [])
|
||||||
|
+ ([service_name + '-redis.service'] if service_redis else [])
|
||||||
|
}}
|
||||||
|
_service_container_wants: >-
|
||||||
|
{{
|
||||||
|
service_wants
|
||||||
|
+ ([service_name + '-socat.socket'] if service_domains | length > 0 else [])
|
||||||
|
+ _service_additional_containers
|
||||||
|
| map(attribute='name')
|
||||||
|
| map('regex_replace', '$', '.service')
|
||||||
|
}}
|
||||||
|
|
||||||
_service_replacement_host_header:
|
_service_replacement_host_header:
|
||||||
Host: "{{ service_name }}:{{ service_container_http_port }}"
|
Host: "{{ service_name }}:{{ service_container_http_port }}"
|
||||||
|
|||||||
Reference in New Issue
Block a user