This commit is contained in:
Luca Bilke 2024-12-25 16:55:49 +01:00
parent 0575d65e90
commit edce5ceee0
8 changed files with 269 additions and 25 deletions

View file

@ -3,7 +3,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING, Any, Callable
if TYPE_CHECKING:
from ansible_collections.ssnailed.ez_compose.plugins.module_utils.common import (
@ -11,9 +11,7 @@ if TYPE_CHECKING:
)
BASE_ARGS = {
"name": {"type": "str", "required": True},
}
BASE_ARGS: dict[str, Any] = {}
def run_helper(

View file

@ -13,8 +13,8 @@ if TYPE_CHECKING:
)
EXTRA_ARGS = {
"proxy_type": {"type": "str"},
"middleware_name": {"type": "string"},
"proxy_type": {"type": "str", "default": "http"},
"name": {"type": "string"},
"middleware": {"type": "str", "required": True},
"settings": {"type": "list", "required": True},
}
@ -24,13 +24,13 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
project_name: str = state.module.params["name"]
middleware: str = params["middleware"]
settings: dict[str, str] = params["settings"]
proxy_type: str = state.module.params.get("proxy_type", "http")
middleware_name: str = state.module.params.get(
"middleware_name",
proxy_type: str = state.module.params["proxy_type"]
name: str = state.module.params.get(
"name",
f"{project_name}_{service_name}_{proxy_type}_{middleware.lower()}",
)
prefix = f"traefik.{proxy_type}.middlewares.{middleware_name}"
prefix = f"traefik.{proxy_type}.middlewares.{name}"
labels = {f"{prefix}.{middleware}.{key}": var for key, var in settings.items()}

View file

@ -13,7 +13,7 @@ if TYPE_CHECKING:
)
EXTRA_ARGS = {
"router_name": {"type": "str"},
"name": {"type": "str"},
"rule": {"type": "str", "required": True},
"proxy_type": {"type": "str", "default": "http"},
"service": {"type": "str"},
@ -31,12 +31,12 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
middlewares: list[str] | None = params.get("middlewares")
certresolver: str | None = params.get("certresolver")
proxy_type: str = params["proxy_type"]
router_name: str = params.get(
"router_name",
name: str = params.get(
"name",
f"{project_name}_{service_name}_{proxy_type}",
)
prefix = f"traefik.{proxy_type}.routers.{router_name}"
prefix = f"traefik.{proxy_type}.routers.{name}"
labels = {
"traefik.enable": True,

View file

@ -14,7 +14,7 @@ if TYPE_CHECKING:
EXTRA_ARGS = {
"proxy_type": {"type": "str", "default": "http"},
"service_name": {"type": "string"},
"name": {"type": "string"},
"port": {"type": "int"},
}
@ -23,12 +23,12 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
project_name: str = state.module.params["name"]
port: int | None = params.get("port")
proxy_type: str = params["proxy_type"]
traefik_service_name: str = params.get(
"service_name",
name: str = params.get(
"name",
f"{project_name}_{service_name}_{proxy_type}",
)
prefix = f"traefik.{proxy_type}.services.{traefik_service_name}"
prefix = f"traefik.{proxy_type}.services.{name}"
labels: dict[str, Any] = {}

View file

@ -17,7 +17,7 @@ if TYPE_CHECKING:
State,
)
BASE_ARGS = {
BASE_ARGS: dict[str, Any] = {
"name": {"type": "str", "required": True},
"image": {"type": "str", "required": True},
"defaults": {"type": "dict"},

View file

@ -3,7 +3,6 @@
from __future__ import annotations
import copy
from typing import TYPE_CHECKING, Any
from ansible_collections.ssnailed.ez_compose.plugins.module_utils import (
@ -19,15 +18,13 @@ if TYPE_CHECKING:
# NOTE: Label helper arguments are added in the compose module itself
EXTRA_ARGS = {
"internal_network": {"type": "bool", "default": False},
"definition": {"type": "dict", "required": True},
}
def helper(state: State, params: dict[str, Any]) -> State:
definition: dict[str, Any] = params["definition"]
internal_network: bool = params["internal_network"]
update = copy.deepcopy(definition)
update: dict[str, Any] = {}
networks = update.get("networks", {})

View file

@ -15,7 +15,7 @@ if TYPE_CHECKING:
)
EXTRA_ARGS = {
"archive": {"type": "str"},
"archive": {"type": "path"},
"backup_volumes": {"type": "list", "elements": "str"},
}
@ -41,11 +41,11 @@ def helper(state: State, params: dict[str, Any]) -> State:
"BACKUP_LATEST_SYMLINK": f"{project_name}-latest",
"BACKUP_PRUNING_PREFIX": f"{project_name}-",
"BACKUP_STOP_DURING_BACKUP_LABEL": project_name,
"BACKUP_ARCHIVE": "/archive",
"DOCKER_HOST": f"tcp://{project_name}_{service_name}_socket_proxy:2375",
}
if archive:
environment["BACKUP_ARCHIVE"] = "/archive"
volumes.append(
{
"type": "bind",

249
plugins/modules/compose.py Normal file → Executable file
View file

@ -1,8 +1,256 @@
#!/usr/bin/env python
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
# MIT License (see LICENSE)
# ruff: noqa: E402
from __future__ import annotations
SERVICE_BASE_DOCS = """
type: dict
suboptions:
name:
description:
- Name of the service.
type: str
image:
description:
- Image to use for service.
type: str
defaults:
description:
- Service definition to be overwritten.
type: dict
overwrite:
description:
- Service definition to overwrite with.
type: dict
"""
LABEL_BASE_DOCS = """
type: dict
suboptions:
"""
DOCUMENTATION = f"""
---
module: compose
short_description: Simplify docker-compose deployments
description:
- Easily create docker-compose files using a single module
author:
- "Luca Bilke (@ssnailed)"
attributes:
check_mode:
support: full
diff_mode:
support: full
options:
name:
description:
- Name of the compose project to create or modify.
aliases: [project]
type: str
project_dir:
description:
- Path to store project directory under.
type: path
services:
description:
- Services to create in the project.
type: list
elements: dict
suboptions:
custom:
description:
- Custom service definition.
{SERVICE_BASE_DOCS}
internal_network:
description:
- If true, add internal network to service.
type: bool
default: false
label_helpers:
description:
- Label helper configurations.
type: dict
suboptions:
docker_volume_backupper:
description:
- Docker Volume Backupper label helper configuration.
{LABEL_BASE_DOCS}
stop:
description:
- If true, stop the container when backing up.
type: bool
default: true
traefik_middleware:
description:
- Traefik Middleware label helper configuration.
{LABEL_BASE_DOCS}
proxy_type:
description:
- Traefik proxy type.
type: str
choices: [http, tcp, udp]
default: http
name:
description:
- Name of the middleware.
- Default is generated dynamically like so:
- [project_name]_[service_name]_[proxy_type]_[middleware]
type: string
middleware:
description:
- The traefik middleware to use.
type: str
required: true
settings:
description:
- Middleware options.
type: dict
required: true
traefik_router:
description:
- Traefik Router label helper configuration.
{LABEL_BASE_DOCS}
proxy_type:
description:
- Traefik proxy type.
type: str
choices: [http, tcp, udp]
default: http
name:
description:
- Name of the middleware.
- Default is generated dynamically like so:
- [project_name]_[service_name]_[proxy_type]
type: string
rule:
description:
- Routing rule to match.
type: str
required: true
service:
description:
- Traefik service to point at.
type: str
certresolver:
description:
- Certresolver to use.
type: str
entrypoints:
description:
- Entrypoints to listen on.
type: list
elements: str
middlewares:
description:
- Middlewares to use.
type: list
elements: str
traefik_service:
description:
- Traefik Service label helper configuration.
{LABEL_BASE_DOCS}
proxy_type:
description:
- Traefik proxy type.
type: str
choices: [http, tcp, udp]
default: http
name:
description:
- Name of the middleware.
- Default is generated dynamically like so:
- [project_name]_[service_name]_[proxy_type]
type: string
port:
description:
- Port to forward to.
type: int
docker_in_docker:
description:
- Docker-in-Docker service definition.
{SERVICE_BASE_DOCS}
docker_socket_proxy:
description:
- Docker Socket Proxy service definition.
{SERVICE_BASE_DOCS}
read_only:
description:
- If true, only allow read access to the docker socket.
type: bool
default: true
docker_volume_backupper:
description:
- Docker Socket Proxy service definition.
{SERVICE_BASE_DOCS}
archive:
description:
- Directory to store backups in.
type: path
backup_volumes:
description:
- List of volume names of volumes to backup.
type: list
elements: str
mariadb:
description:
- MariaDB service definition.
{SERVICE_BASE_DOCS}
backup:
description:
- If true, add labels for the docker volume backupper.
type: bool
database:
description:
- Name of database.
type: str
required: true
username:
description:
- Username for database.
type: str
required: true
password:
description:
- Password for database.
type: str
required: true
root_password:
description:
- Root password for database.
type: str
postgres:
description:
- PostgreSQL service definition.
{SERVICE_BASE_DOCS}
backup:
description:
- If true, add labels for the docker volume backupper.
type: bool
database:
description:
- Name of database.
type: str
required: true
username:
description:
- Username for database.
type: str
required: true
password:
description:
- Password for database.
type: str
required: true
redis:
description:
- Redis service definition.
{SERVICE_BASE_DOCS}
""" # noqa: E501
from typing import Any
from ansible.module_utils.basic import AnsibleModule # type: ignore[reportMissingStubFile]
@ -68,6 +316,7 @@ def main() -> None:
module = AnsibleModule(
argument_spec={
"name": {
"aliases": ["project"],
"type": "str",
"required": True,
},