Compare commits

...

3 Commits

93 changed files with 322 additions and 204 deletions

View File

@ -1,7 +1,7 @@
ROLES_DIR := ./roles ROLES_DIR := ./roles
APPLICATIONS_OUT := ./group_vars/all/03_applications.yml APPLICATIONS_OUT := ./group_vars/all/03_applications.yml
APPLICATIONS_SCRIPT := ./cli/generate-applications-defaults.py APPLICATIONS_SCRIPT := ./cli/generate-applications-defaults.py
INCLUDES_OUT := ./tasks/include-docker-roles.yml INCLUDES_OUT := ./tasks/utils/docker-roles.yml
INCLUDES_SCRIPT := ./cli/generate_playbook.py INCLUDES_SCRIPT := ./cli/generate_playbook.py
.PHONY: build install test .PHONY: build install test

View File

@ -98,8 +98,7 @@ Now that you have defined the application settings, domain, and application ID,
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
``` ```
3. **`docker-compose.yml.j2`**: 3. **`docker-compose.yml.j2`**:

View File

@ -23,6 +23,7 @@ def get_docker_compose(path_docker_compose_instances: str, application_id: str)
'files': { 'files': {
'env': f"{base}.env/env", 'env': f"{base}.env/env",
'docker_compose': f"{base}docker-compose.yml", 'docker_compose': f"{base}docker-compose.yml",
'dockerfile': f"{base}Dockerfile",
} }
} }

View File

@ -19,15 +19,15 @@ defaults_service_provider:
bluesky: >- bluesky: >-
{{ ('@' ~ users.administrator.username ~ '.' ~ domains.bluesky.api) {{ ('@' ~ users.administrator.username ~ '.' ~ domains.bluesky.api)
if 'bluesky' in group_names else '' }} if 'bluesky' in group_names else '' }}
email: "contact@{{ primary_domain }}" email: "contact@{{ primary_domain }}"
mastodon: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('mastodon') if 'mastodon' in group_names else '' }}" mastodon: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('mastodon') if 'mastodon' in group_names else '' }}"
matrix: "{{ '@' ~ users.administrator.username ~ ':' ~ domains.matrix.synapse if 'matrix' in group_names else '' }}" matrix: "{{ '@' ~ users.administrator.username ~ ':' ~ domains.matrix.synapse if 'matrix' in group_names else '' }}"
peertube: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('peertube') if 'peertube' in group_names else '' }}" peertube: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('peertube') if 'peertube' in group_names else '' }}"
pixelfed: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('pixelfed') if 'pixelfed' in group_names else '' }}" pixelfed: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('pixelfed') if 'pixelfed' in group_names else '' }}"
phone: "+0 000 000 404" phone: "+0 000 000 404"
wordpress: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('wordpress') if 'wordpress' in group_names else '' }}" wordpress: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('wordpress') if 'wordpress' in group_names else '' }}"
legal: legal:
editorial_responsible: "Johannes Gutenberg" editorial_responsible: "Johannes Gutenberg"
source_code: "https://github.com/kevinveenbirkenbach/cymais" source_code: "https://github.com/kevinveenbirkenbach/cymais"
imprint: "{{web_protocol}}://{{ domains | get_domain('html-server') }}/imprint.html" imprint: "{{web_protocol}}://{{ domains | get_domain('html-server') }}/imprint.html"

View File

@ -2,9 +2,9 @@
hosts: all hosts: all
tasks: tasks:
- name: "Load 'constructor' tasks" - name: "Load 'constructor' tasks"
include_tasks: "tasks/constructor.yml" include_tasks: "tasks/plays/01_constructor.yml"
- name: "Load '{{host_type}}' tasks" - name: "Load '{{host_type}}' tasks"
include_tasks: "tasks/{{host_type}}.yml" include_tasks: "tasks/plays/02_{{host_type}}.yml"
- name: "Load 'destructor' tasks" - name: "Load 'destructor' tasks"
include_tasks: "tasks/destructor.yml" include_tasks: "tasks/plays/03_destructor.yml"
become: true become: true

View File

@ -6,7 +6,7 @@ services:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: docker.io/akaunting/akaunting:{{applications.akaunting.version}} image: "{{ applications[application_id].images.akaunting }}"
build: build:
context: . context: .
ports: ports:

View File

@ -1,12 +1,13 @@
version: "latest" images:
company_name: "{{primary_domain}}" akaunting: "docker.io/akaunting/akaunting:latest"
company_email: "{{users.administrator.email}}" company_name: "{{primary_domain}}"
setup_admin_email: "{{users.administrator.email}}" company_email: "{{users.administrator.email}}"
setup_admin_email: "{{users.administrator.email}}"
features: features:
matomo: true matomo: true
css: true css: true
portfolio_iframe: false portfolio_iframe: false
central_database: true central_database: true
credentials: credentials:
domains: domains:
canonical: canonical:

View File

@ -5,7 +5,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
web: web:
image: "attendize_web:{{applications.attendize.version}}" image: "{{ applications[application_id].images.web }}"
ports: ports:
- "{{ports.localhost.http[application_id]}}:80" - "{{ports.localhost.http[application_id]}}:80"
volumes: volumes:
@ -19,7 +19,7 @@ services:
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
worker: worker:
image: "attendize_worker:{{applications.attendize.version}}" image: "{{ applications[application_id].images.worker }}"
{% include 'templates/docker/container/depends-on-database-redis.yml.j2' %} {% include 'templates/docker/container/depends-on-database-redis.yml.j2' %}
maildev: maildev:
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}

View File

@ -1,4 +1,6 @@
version: "latest" image:
web: "attendize_web:latest"
worker: "attendize_worker:latest"
credentials: credentials:
features: features:
matomo: true matomo: true

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -6,7 +6,7 @@ services:
application: application:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: "baserow/baserow:{{applications.baserow.version}}" image: "{{ applications[application_id].images.baserow }}"
container_name: baserow-application container_name: baserow-application
volumes: volumes:
- data:/baserow/data - data:/baserow/data

View File

@ -1,4 +1,5 @@
version: "latest" images:
baserow: "baserow/baserow:latest"
features: features:
matomo: true matomo: true
css: true css: true

View File

@ -47,5 +47,4 @@
version: "main" version: "main"
notify: docker compose project build and setup notify: docker compose project build and setup
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -1,6 +1,6 @@
services: services:
pds: pds:
image: "ghcr.io/bluesky-social/pds:{{applications.bluesky.pds.version}}" image: "{{ applications[application_id].images.pds }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
volumes: volumes:
- pds_data:/opt/pds - pds_data:/opt/pds

View File

@ -1,6 +1,8 @@
users: users:
administrator: administrator:
email: "{{users.administrator.email}}" email: "{{users.administrator.email}}"
images:
pds: "ghcr.io/bluesky-social/pds:latest"
pds: pds:
version: "latest" version: "latest"
credentials: credentials:

View File

@ -0,0 +1,42 @@
- name: "Create (optional) '{{ docker_compose.files.dockerfile }}'"
template:
src: "{{ playbook_dir }}/roles/{{ role_name }}/templates/Dockerfile"
dest: "{{ docker_compose.files.dockerfile }}"
notify: docker compose project build and setup
ignore_errors: false
register: create_dockerfile_result
failed_when:
- create_dockerfile_result is failed
- "'Could not find or access' not in create_dockerfile_result.msg"
- name: "Create (optional) '{{ docker_compose.files.env }}'"
template:
src: "env.j2"
dest: "{{ docker_compose.files.env }}"
mode: '770'
force: yes
notify: docker compose project setup
register: env_template
ignore_errors: false
failed_when:
- env_template is failed
- "'Could not find or access' not in env_template.msg"
- name: "Create (obligatoric) '{{ docker_compose.files.docker_compose }}'"
template:
src: "docker-compose.yml.j2"
dest: "{{ docker_compose.files.docker_compose }}"
notify: docker compose project setup
register: docker_compose_template
- name: "Check if any container is running in {{ docker_compose.directories.instance }}"
command: docker compose ps -q --filter status=running
args:
chdir: "{{ docker_compose.directories.instance }}"
register: docker_ps
changed_when: (docker_ps.stdout | trim) == ""
notify: docker compose project setup
when: not (docker_compose_template.changed or env_template.changed)
- name: flush docker compose project setup
meta: flush_handlers

View File

@ -1,4 +1,4 @@
# DRAFT role docker-coturn # Coturn Server (DRAFT)
setup an coturn server based on https://hub.docker.com/r/coturn/coturn setup an coturn server based on https://hub.docker.com/r/coturn/coturn
## todo ## todo

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -1,4 +1,2 @@
user: turnuser user: turnuser
credentials: credentials:
# password: # Need to be defined in invetory file
# secret: # Need to be defined in invetory file

View File

@ -14,8 +14,7 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: Set OIDC scopes in EspoCRM config (inside web container) - name: Set OIDC scopes in EspoCRM config (inside web container)
ansible.builtin.shell: | ansible.builtin.shell: |

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
web: web:
image: espocrm/espocrm:{{ applications[application_id].version }} image: "{{ applications[application_id].images.espocrm }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"] test: ["CMD", "curl", "-f", "http://localhost/"]
@ -15,7 +15,7 @@ services:
- data:/var/www/html - data:/var/www/html
daemon: daemon:
image: espocrm/espocrm:{{ applications[application_id].version }} image: "{{ applications[application_id].images.espocrm }}"
restart: {{docker_restart_policy}} restart: {{docker_restart_policy}}
logging: logging:
driver: journald driver: journald
@ -25,7 +25,7 @@ services:
- data:/var/www/html - data:/var/www/html
websocket: websocket:
image: espocrm/espocrm:{{ applications[application_id].version }} image: "{{ applications[application_id].images.espocrm }}"
restart: {{docker_restart_policy}} restart: {{docker_restart_policy}}
logging: logging:
driver: journald driver: journald

View File

@ -1,4 +1,5 @@
version: "latest" images:
espocrm: "espocrm/espocrm:latest"
users: users:
administrator: administrator:
username: "{{ users.administrator.username }}" username: "{{ users.administrator.username }}"

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
application: application:
image: "friendica:{{applications.friendica.version}}" image: "{{ applications[application_id].images.friendica }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
volumes: volumes:
- html:/var/www/html - html:/var/www/html

View File

@ -1,4 +1,5 @@
version: "latest" images:
friendica: "friendica:latest"
features: features:
matomo: true matomo: true
css: true css: true

View File

@ -10,7 +10,6 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -14,7 +14,7 @@ services:
# flag: # flag:
# celery -A funkwhale_api.taskapp worker -l INFO --concurrency=4 # celery -A funkwhale_api.taskapp worker -l INFO --concurrency=4
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: funkwhale/api:{{applications.funkwhale.version}} image: "{{ applications[application_id].images.api }}"
command: celery -A funkwhale_api.taskapp worker -l INFO --concurrency={{celeryd_concurrency}} command: celery -A funkwhale_api.taskapp worker -l INFO --concurrency={{celeryd_concurrency}}
environment: environment:
- C_FORCE_ROOT=true - C_FORCE_ROOT=true
@ -26,14 +26,14 @@ services:
celerybeat: celerybeat:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: funkwhale/api:{{applications.funkwhale.version}} image: "{{ applications[application_id].images.api }}"
command: celery -A funkwhale_api.taskapp beat --pidfile= -l INFO command: celery -A funkwhale_api.taskapp beat --pidfile= -l INFO
{% include 'templates/docker/container/depends-on-database-redis.yml.j2' %} {% include 'templates/docker/container/depends-on-database-redis.yml.j2' %}
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
api: api:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: funkwhale/api:{{applications.funkwhale.version}} image: "{{ applications[application_id].images.api }}"
volumes: volumes:
- "music:{{music_directory_path}}:ro" - "music:{{music_directory_path}}:ro"
- "data:{{media_root}}" - "data:{{media_root}}"
@ -45,7 +45,7 @@ services:
front: front:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: funkwhale/front:{{applications.funkwhale.version}} image: "{{ applications[application_id].images.front }}"
depends_on: depends_on:
- api - api
environment: environment:
@ -60,7 +60,7 @@ services:
typesense: typesense:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: typesense/typesense:0.24.0 image: "{{ applications[application_id].images.typesense }}"
volumes: volumes:
- ./typesense/data:/data - ./typesense/data:/data
command: --data-dir /data --enable-cors command: --data-dir /data --enable-cors

View File

@ -1,4 +1,7 @@
version: "1.4.0" images:
api: "funkwhale/api:1.4.0"
front: "funkwhale/front:1.4.0"
typesense: "typesense/typesense"
features: features:
matomo: true matomo: true
css: true css: true

View File

@ -1,4 +1,4 @@
# FusionDirectory # FusionDirectory (DRAFT)
# Warning # Warning
This application isn't implemented yet This application isn't implemented yet

View File

@ -9,5 +9,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -4,7 +4,7 @@ services:
application: application:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: "gitea/gitea:{{applications.gitea.version}}" image: "{{ applications[application_id].images.gitea }}"
ports: ports:
- "127.0.0.1:{{ports.localhost.http[application_id]}}:3000" - "127.0.0.1:{{ports.localhost.http[application_id]}}:3000"
- "{{ports.public.ssh[application_id]}}:22" - "{{ports.public.ssh[application_id]}}:22"

View File

@ -1,4 +1,5 @@
version: "latest" # Use latest docker image images:
gitea: "gitea/gitea:latest"
configuration: configuration:
repository: repository:
enable_push_create_user: True # Allow users to push local repositories to Gitea and have them automatically created for a user. enable_push_create_user: True # Allow users to push local repositories to Gitea and have them automatically created for a user.
@ -7,14 +8,14 @@ configuration:
features: features:
matomo: true matomo: true
css: true css: true
portfolio_iframe: true portfolio_iframe: true
central_database: true central_database: true
csp: csp:
flags: flags:
script-src: script-src:
unsafe-inline: true unsafe-inline: true
style-src: style-src:
unsafe-inline: true unsafe-inline: true
whitelist: whitelist:
font-src: font-src:
- "data:" - "data:"

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -5,7 +5,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
web: web:
image: "gitlab/gitlab-ee:{{applications.gitlab.version}}" image: "{{ applications[application_id].images.gitlab }}"
hostname: '{{domains | get_domain(application_id)}}' hostname: '{{domains | get_domain(application_id)}}'
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
ports: ports:

View File

@ -1,4 +1,5 @@
version: "latest" images:
gitlab: "gitlab/gitlab-ee:latest"
features: features:
matomo: true matomo: true
css: true css: true

View File

@ -13,5 +13,4 @@
loop_control: loop_control:
loop_var: domain loop_var: domain
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
application: application:
image: "joomla:{{applications.joomla.version}}" image: "{{ applications[application_id].images.joomla }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
volumes: volumes:
- data:/var/www/html - data:/var/www/html

View File

@ -1,4 +1,5 @@
version: "latest" images:
joomla: "joomla:latest"
features: features:
matomo: true matomo: true
css: true css: true

View File

@ -10,8 +10,7 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: "create directory {{import_directory_host}}" - name: "create directory {{import_directory_host}}"
file: file:

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
application: application:
image: quay.io/keycloak/keycloak:{{applications.keycloak.version}} image: "{{ applications[application_id].images.keycloak }}"
container_name: {{container_name}} container_name: {{container_name}}
command: start {% if applications[application_id].import_realm | bool %}--import-realm{% endif %} command: start {% if applications[application_id].import_realm | bool %}--import-realm{% endif %}
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}

View File

@ -1,4 +1,5 @@
version: "latest" images:
keycloak: "quay.io/keycloak/keycloak:latest"
users: users:
administrator: administrator:
username: "{{users.administrator.username}}" # Administrator Username for Keycloak username: "{{users.administrator.username}}" # Administrator Username for Keycloak

View File

@ -9,5 +9,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -4,7 +4,7 @@ services:
application: application:
container_name: {{ application_id }} container_name: {{ application_id }}
image: ghcr.io/ldapaccountmanager/lam:{{applications[application_id].version}} image: "{{ applications[application_id].images.lam }}"
ports: ports:
- 127.0.0.1:{{ports.localhost.http[application_id]}}:80 - 127.0.0.1:{{ports.localhost.http[application_id]}}:80
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}

View File

@ -1,4 +1,5 @@
version: "latest" images:
lam: "ghcr.io/ldapaccountmanager/lam:latest"
oauth2_proxy: oauth2_proxy:
application: application application: application
port: 80 port: 80

View File

@ -23,8 +23,7 @@
ipam_config: ipam_config:
- subnet: "{{ networks.local.central_ldap.subnet }}" - subnet: "{{ networks.local.central_ldap.subnet }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: "create directory {{ldif_host_path}}{{item}}" - name: "create directory {{ldif_host_path}}{{item}}"
file: file:

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-oauth2-proxy/templates/container.yml.j2' %} {% include 'roles/docker-oauth2-proxy/templates/container.yml.j2' %}
application: application:
image: bitnami/openldap:{{ applications[application_id].version }} image: "{{ applications[application_id].images.openldap }}"
container_name: {{ applications[application_id].hostname }} container_name: {{ applications[application_id].hostname }}
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
{% if applications[application_id].network.public | bool or applications[application_id].network.local | bool %} {% if applications[application_id].network.public | bool or applications[application_id].network.local | bool %}

View File

@ -1,4 +1,5 @@
version: "latest" images:
openldap: "bitnami/openldap:latest"
network: network:
local: True # Activates local network. Necessary for LDIF import routines local: True # Activates local network. Necessary for LDIF import routines
docker: True # Activates docker network to allow other docker containers to connect docker: True # Activates docker network to allow other docker containers to connect

View File

@ -25,8 +25,7 @@
dest: "{{docker_compose.directories.config}}config.toml" dest: "{{docker_compose.directories.config}}config.toml"
notify: docker compose project setup notify: docker compose project setup
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: Check if listmonk database is already initialized - name: Check if listmonk database is already initialized
command: docker compose exec -T {{database_host}} psql -U {{database_username}} -d {{database_name}} -c "\dt" command: docker compose exec -T {{database_host}} psql -U {{database_username}} -d {{database_name}} -c "\dt"

View File

@ -4,7 +4,7 @@ services:
application: application:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: listmonk/listmonk:{{applications.listmonk.version}} image: "{{ applications[application_id].images.listmonk }}"
ports: ports:
- "127.0.0.1:{{ports.localhost.http[application_id]}}:9000" - "127.0.0.1:{{ports.localhost.http[application_id]}}:9000"
volumes: volumes:

View File

@ -1,3 +1,5 @@
images:
listmonk: "listmonk/listmonk:latest"
users: users:
administrator: administrator:
username: "{{users.administrator.username}}" # Listmonk administrator account username username: "{{users.administrator.username}}" # Listmonk administrator account username

View File

@ -18,8 +18,7 @@
name: nginx-docker-cert-deploy name: nginx-docker-cert-deploy
when: run_once_docker_mailu is not defined when: run_once_docker_mailu is not defined
- name: "Copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
when: run_once_docker_mailu is not defined when: run_once_docker_mailu is not defined
- name: Flush docker service handlers - name: Flush docker service handlers

View File

@ -16,8 +16,7 @@
client_max_body_size: "80m" client_max_body_size: "80m"
vhost_flavour: "ws_generic" vhost_flavour: "ws_generic"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: flush docker service - name: flush docker service
meta: flush_handlers meta: flush_handlers

View File

@ -5,7 +5,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
web: web:
image: ghcr.io/mastodon/mastodon:{{applications.mastodon.version}} image: "{{ applications[application_id].images.mastodon }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000" command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
healthcheck: healthcheck:
@ -18,7 +18,7 @@ services:
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
streaming: streaming:
image: ghcr.io/mastodon/mastodon-streaming:{{applications.mastodon.version}} image: "{{ applications[application_id].images.streaming }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
command: node ./streaming command: node ./streaming
healthcheck: healthcheck:
@ -29,7 +29,7 @@ services:
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
sidekiq: sidekiq:
image: ghcr.io/mastodon/mastodon:{{applications.mastodon.version}} image: "{{ applications[application_id].images.mastodon }}"
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
command: bundle exec sidekiq command: bundle exec sidekiq
{% include 'templates/docker/container/depends-on-database-redis.yml.j2' %} {% include 'templates/docker/container/depends-on-database-redis.yml.j2' %}

View File

@ -1,4 +1,6 @@
version: "latest" images:
mastodon: "ghcr.io/mastodon/mastodon:latest"
streaming: "ghcr.io/mastodon/mastodon-streaming:latest"
single_user_mode: false # Set true for initial setup single_user_mode: false # Set true for initial setup
setup: false # Set true in inventory file to execute the setup and initializing procedures setup: false # Set true in inventory file to execute the setup and initializing procedures
credentials: credentials:

View File

@ -12,8 +12,7 @@
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
when: run_once_docker_matomo is not defined when: run_once_docker_matomo is not defined
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
when: run_once_docker_matomo is not defined when: run_once_docker_matomo is not defined
- name: run the docker matomo tasks once - name: run the docker matomo tasks once

View File

@ -4,7 +4,7 @@ services:
application: application:
{% include 'roles/docker-compose/templates/services/base.yml.j2' %} {% include 'roles/docker-compose/templates/services/base.yml.j2' %}
image: matomo:{{applications.matomo.version}} image: "{{ applications[application_id].images.matomo }}"
ports: ports:
- "127.0.0.1:{{ports.localhost.http.matomo}}:80" - "127.0.0.1:{{ports.localhost.http.matomo}}:80"
volumes: volumes:

View File

@ -1,4 +1,5 @@
version: "latest" images:
matomo: "matomo:latest"
features: features:
matomo: true matomo: true
css: false css: false

View File

@ -3,7 +3,7 @@ services:
{% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %} {% include 'roles/docker-central-database/templates/services/' + database_type + '.yml.j2' %}
synapse: synapse:
image: matrixdotorg/synapse:{{applications[application_id].synapse.version}} image: "{{ applications[application_id].images.synapse }}"
container_name: matrix-synapse container_name: matrix-synapse
restart: {{docker_restart_policy}} restart: {{docker_restart_policy}}
logging: logging:
@ -36,7 +36,7 @@ services:
{% endif %} {% endif %}
{% include 'templates/docker/container/networks.yml.j2' %} {% include 'templates/docker/container/networks.yml.j2' %}
element: element:
image: vectorim/element-web:{{applications[application_id].element.version}} image: "{{ applications[application_id].images.element }}"
container_name: matrix-element container_name: matrix-element
restart: {{docker_restart_policy}} restart: {{docker_restart_policy}}
volumes: volumes:

View File

@ -1,4 +1,7 @@
images:
synapse: "matrixdotorg/synapse:latest"
element: "vectorim/element-web:latest"
# Set bridges
users: users:
administrator: administrator:
username: "{{users.administrator.username}}" # Accountname of the matrix admin username: "{{users.administrator.username}}" # Accountname of the matrix admin

View File

@ -10,14 +10,7 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "Transfer Dockerfile to {{ docker_compose.directories.instance }}" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
template:
src: Dockerfile.j2
dest: "{{ docker_compose.directories.instance }}Dockerfile"
notify: docker compose project build and setup
- name: "copy docker-compose.yml and env file"
include_tasks: copy-docker-compose-and-env.yml
- name: "Configure OIDC login for Moodle if enabled" - name: "Configure OIDC login for Moodle if enabled"
include_tasks: oidc.yml include_tasks: oidc.yml

View File

@ -35,8 +35,7 @@
dest: "{{docker_compose.directories.volumes}}nginx.conf" dest: "{{docker_compose.directories.volumes}}nginx.conf"
notify: restart nextcloud nginx service notify: restart nextcloud nginx service
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: Flush all handlers immediately so that occ can be used - name: Flush all handlers immediately so that occ can be used
meta: flush_handlers meta: flush_handlers

View File

@ -10,23 +10,16 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "Create {{openproject_plugins_service}}" - name: "Create {{openproject_plugins_folder}}"
file: file:
path: "{{openproject_plugins_service}}" path: "{{openproject_plugins_folder}}"
state: directory state: directory
mode: '0755' mode: '0755'
- name: "Transfering Gemfile.plugins to {{openproject_plugins_service}}" - name: "Transfering Gemfile.plugins to {{openproject_plugins_folder}}"
copy: copy:
src: Gemfile.plugins src: Gemfile.plugins
dest: "{{openproject_plugins_service}}Gemfile.plugins" dest: "{{openproject_plugins_folder}}Gemfile.plugins"
notify:
- docker compose project build and setup
- name: "Transfering Dockerfile to {{openproject_plugins_service}}Dockerfile"
template:
src: Dockerfile
dest: "{{openproject_plugins_service}}Dockerfile"
notify: notify:
- docker compose project build and setup - docker compose project build and setup
@ -40,8 +33,7 @@
state: directory state: directory
mode: 0755 mode: 0755
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: flush docker service - name: flush docker service
meta: flush_handlers meta: flush_handlers

View File

@ -5,7 +5,7 @@ FROM openproject/community:{{applications.openproject.version}}
# path inside of the container. Say for `/app/vendor/plugins/openproject-slack`: # path inside of the container. Say for `/app/vendor/plugins/openproject-slack`:
# COPY /path/to/my/local/openproject-slack /app/vendor/plugins/openproject-slack # COPY /path/to/my/local/openproject-slack /app/vendor/plugins/openproject-slack
COPY Gemfile.plugins /app/ COPY volumes/plugins/Gemfile.plugins /app/
# If the plugin uses any external NPM dependencies you have to install them here. # If the plugin uses any external NPM dependencies you have to install them here.
# RUN npm add npm <package-name>* # RUN npm add npm <package-name>*

View File

@ -4,7 +4,7 @@ x-op-app: &app
driver: journald driver: journald
image: {{custom_openproject_image}} image: {{custom_openproject_image}}
build: build:
context: {{openproject_plugins_service}} context: .
dockerfile: Dockerfile dockerfile: Dockerfile
services: services:

View File

@ -9,7 +9,7 @@ ldap:
features: features:
matomo: true matomo: true
css: true css: true
portfolio_iframe: false portfolio_iframe: false
ldap: true ldap: true
central_database: true central_database: true
oauth2: true oauth2: true

View File

@ -2,7 +2,8 @@ application_id: "openproject"
docker_repository_address: "https://github.com/opf/openproject-deploy" docker_repository_address: "https://github.com/opf/openproject-deploy"
database_type: "postgres" database_type: "postgres"
openproject_plugins_service: "{{docker_compose.directories.services}}plugins/" openproject_plugins_folder: "{{docker_compose.directories.volumes}}plugins/"
custom_openproject_image: "custom_openproject" custom_openproject_image: "custom_openproject"
# The following volume doesn't have a practcical function. It just exist to prevent the creation of unnecessary anonymous volumes # The following volume doesn't have a practcical function. It just exist to prevent the creation of unnecessary anonymous volumes
@ -23,4 +24,4 @@ openproject_filters:
users: >- users: >-
{{ '(memberOf=cn=openproject-users,' ~ ldap.dn.application_roles ~ ')' {{ '(memberOf=cn=openproject-users,' ~ ldap.dn.application_roles ~ ')'
if applications[application_id].ldap.filters.users else '' }} if applications[application_id].ldap.filters.users else '' }}

View File

@ -11,8 +11,7 @@
vars: vars:
http: "{{ ports.localhost.http[application_id] }}" http: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml
- name: "Install and activate auth-openid-connect plugin if OIDC is enabled" - name: "Install and activate auth-openid-connect plugin if OIDC is enabled"
include_tasks: enable-oidc.yml include_tasks: enable-oidc.yml

View File

@ -14,5 +14,4 @@
include_tasks: configuration.yml include_tasks: configuration.yml
when: applications[application_id].server_mode | bool when: applications[application_id].server_mode | bool
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -9,5 +9,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -0,0 +1,2 @@
# Todo
- Integrate OIDC as soon as possible

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -26,5 +26,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -12,10 +12,4 @@
become: true become: true
ignore_errors: true ignore_errors: true
- name: add docker-compose.yml - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
template: src=docker-compose.yml.j2 dest={{docker_compose.directories.instance}}docker-compose.yml
notify: docker compose project setup
- name: add Dockerfile
template: src=Dockerfile.j2 dest={{docker_compose.directories.instance}}Dockerfile
notify: docker compose project setup

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -22,5 +22,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -27,5 +27,4 @@
force: yes force: yes
notify: docker compose project setup notify: docker compose project setup
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -28,5 +28,4 @@
dest: "{{docker_compose_init}}" dest: "{{docker_compose_init}}"
notify: docker compose project build and setup notify: docker compose project build and setup
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -25,14 +25,7 @@
dest: "{{ host_msmtp_conf }}" dest: "{{ host_msmtp_conf }}"
notify: docker compose project build and setup notify: docker compose project build and setup
- name: "Transfering Dockerfile to {{ docker_compose.directories.instance }}" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
copy:
src: Dockerfile
dest: "{{ docker_compose.directories.instance }}Dockerfile"
notify: docker compose project build and setup
- name: "copy docker-compose.yml and env file"
include_tasks: copy-docker-compose-and-env.yml
- name: "Install wordpress" - name: "Install wordpress"
include_tasks: install.yml include_tasks: install.yml

View File

@ -1,4 +1,4 @@
FROM wordpress FROM wordpress:{{applications[application_id].version}}
# Install msmtp and update system # Install msmtp and update system
RUN apt-get update && \ RUN apt-get update && \

View File

@ -10,5 +10,4 @@
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file" - include_tasks: "{{ playbook_dir }}/roles/docker-compose/tasks/create-files.yml"
include_tasks: copy-docker-compose-and-env.yml

1
tasks/.gitignore vendored
View File

@ -1 +0,0 @@
include-docker-roles.yml

View File

@ -1,3 +0,0 @@
# todo
- Move update-repository-with-files.yml to own role
- Move copy-docker-compose-and-env.yml to own role

View File

@ -1,27 +0,0 @@
- name: "create {{ docker_compose.files.docker_compose }}"
template:
src: "docker-compose.yml.j2"
dest: "{{ docker_compose.files.docker_compose }}"
notify: docker compose project setup
register: docker_compose_template
- name: "create {{ docker_compose.files.env }}"
template:
src: "env.j2"
dest: "{{ docker_compose.files.env }}"
mode: '770'
force: yes
notify: docker compose project setup
register: env_template
- name: "Check if any container is running in {{ docker_compose.directories.instance }}"
command: docker compose ps -q --filter status=running
args:
chdir: "{{ docker_compose.directories.instance }}"
register: docker_ps
changed_when: (docker_ps.stdout | trim) == ""
notify: docker compose project setup
when: not (docker_compose_template.changed or env_template.changed)
- name: flush docker compose project setup
meta: flush_handlers

View File

@ -12,7 +12,7 @@
- system-btrfs-auto-balancer - system-btrfs-auto-balancer
- name: "Integrate Docker Role includes" - name: "Integrate Docker Role includes"
include_tasks: "include-docker-roles.yml" include_tasks: "./tasks/utils/docker-roles.yml"
# Native Webserver Roles # Native Webserver Roles
- name: setup nginx-serve-htmls - name: setup nginx-serve-htmls

1
tasks/utils/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
docker-roles.yml

View File

@ -0,0 +1,49 @@
import unittest
from pathlib import Path
import yaml
class TestDeprecatedVersionKey(unittest.TestCase):
def test_version_key_deprecation(self):
"""
Checks all roles/docker-*/vars/configuration.yml for deprecated use of 'version'.
Warns if 'version' is set but 'images' is missing.
Prints warnings but does NOT fail the test.
"""
repo_root = Path(__file__).resolve().parent.parent.parent
roles_dir = repo_root / "roles"
warnings = []
for role_path in roles_dir.iterdir():
if not (role_path.is_dir() and role_path.name.startswith("docker-")):
continue
cfg_file = role_path / "vars" / "configuration.yml"
if not cfg_file.exists():
continue
try:
config = yaml.safe_load(cfg_file.read_text("utf-8")) or {}
except yaml.YAMLError as e:
print(f"YAML parse error in {cfg_file}: {e}")
continue
uses_version = 'version' in config
uses_images = 'images' in config
if uses_version and not uses_images:
warnings.append(
f"[DEPRECATION WARNING] {role_path.name}/vars/configuration.yml: "
f"'version:' is set, but 'images:' is missing. "
f"'version' is deprecated and must only be set if 'images' is present."
)
if warnings:
print("\n".join(warnings))
else:
print("No deprecated 'version:' keys found in docker roles without 'images:'.")
# Never fail, just warn
self.assertTrue(True)
if __name__ == "__main__":
unittest.main()

View File

@ -0,0 +1,88 @@
import unittest
import yaml
from pathlib import Path
import re
class TestDockerRoleImagesConfiguration(unittest.TestCase):
def test_images_keys_and_templates(self):
"""
For each docker-* role, check that:
- roles/docker-*/vars/configuration.yml contains 'images' as a dict with keys/values
- Each image key is referenced as:
image: "{{ applications[application_id].images.<key> }}"
in either roles/docker-*/templates/docker-compose.yml.j2 or env.j2
"""
repo_root = Path(__file__).resolve().parent.parent.parent
roles_dir = repo_root / "roles"
errors = []
warnings = []
for role_path in roles_dir.iterdir():
if not (role_path.is_dir() and role_path.name.startswith("docker-")):
continue
cfg_file = role_path / "vars" / "configuration.yml"
if not cfg_file.exists():
continue # No configuration to check
try:
config = yaml.safe_load(cfg_file.read_text("utf-8")) or {}
except yaml.YAMLError as e:
errors.append(f"{role_path.name}: YAML parse error: {e}")
continue
images = config.get("images")
if not images:
warnings.append(f"[WARNING] {role_path.name}: No 'images' key in configuration.yml")
continue
if not isinstance(images, dict):
errors.append(f"{role_path.name}: 'images' must be a dict in configuration.yml")
continue
for key, value in images.items():
if not key or not value or not isinstance(key, str) or not isinstance(value, str):
errors.append(f"{role_path.name}: images['{key}'] is invalid (must be non-empty string key and value)")
continue
# Improved regex: matches both ' and " and allows whitespace
pattern = (
r'image:\s*["\']\{\{\s*applications\[application_id\]\.images\.' + re.escape(key) + r'\s*\}\}["\']'
)
found = False
for tmpl_file in [
role_path / "templates" / "docker-compose.yml.j2",
role_path / "templates" / "env.j2"
]:
if tmpl_file.exists():
content = tmpl_file.read_text("utf-8")
if re.search(pattern, content):
found = True
break
if not found:
errors.append(
f"{role_path.name}: image key '{key}' is not referenced as "
f'image: \"{{{{ applications[application_id].images.{key} }}}}\" in docker-compose.yml.j2 or env.j2'
)
# OPTIONAL: Check if the image is available locally via docker images
# from shutil import which
# import subprocess
# if which("docker"):
# try:
# out = subprocess.check_output(
# ["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"]
# ).decode()
# if value not in out:
# errors.append(f"{role_path.name}: Image '{value}' not found locally (optional check)")
# except Exception as e:
# errors.append(f"{role_path.name}: Error running 'docker images' (optional): {e}")
if warnings:
print("\nWarnings in docker role images configuration:\n" + "\n".join(warnings))
if errors:
self.fail("Errors in docker role images configuration:\n" + "\n".join(errors))
if __name__ == "__main__":
unittest.main()