bugfixes, no_defaults feature

This commit is contained in:
Luca Bilke 2025-01-19 19:33:56 +01:00
commit 4a2f50adfe
Signed by: luca
GPG key ID: C9E851809C1A5BDE
12 changed files with 56 additions and 17 deletions

View file

@ -3,6 +3,7 @@
from __future__ import annotations from __future__ import annotations
import contextlib
import copy import copy
from dataclasses import replace from dataclasses import replace
from pathlib import Path from pathlib import Path
@ -24,13 +25,22 @@ def recursive_update(
for k, v in update.items(): for k, v in update.items():
if isinstance(v, dict): if isinstance(v, dict):
v = cast(dict[str, Any], v) v = cast(dict[str, Any], v)
default[k] = recursive_update(default.get(k, {}), v) if v.get("_ezd_no_defaults"):
v.pop("_ezd_no_defaults")
default[k] = v
else:
default[k] = recursive_update(default.get(k, {}), v)
elif isinstance(v, list): elif isinstance(v, list):
v = cast(list[Any], v) v = cast(list[Any], v)
new = cast(list[Any], (default.get(k, []))) old = cast(list[Any], (default.get(k, [])))
new.extend(v) if "_ezd_no_defaults" in old:
default[k] = new with contextlib.suppress(ValueError):
old.remove("_ezd_no_defaults")
default[k] = v
else:
old.extend(v)
default[k] = old
else: else:
default[k] = v default[k] = v
@ -40,12 +50,10 @@ def recursive_update(
def get_state(module: AnsibleModule) -> State: def get_state(module: AnsibleModule) -> State:
"""Create a new state object, loading the compose file into "before" if it exists.""" """Create a new state object, loading the compose file into "before" if it exists."""
# def clean_params[T](obj: T) -> T:
T = TypeVar("T") T = TypeVar("T")
# def clean_params[T](obj: T) -> T:
def clean_params(obj: T) -> T: def clean_params(obj: T) -> T:
# NOTE: ansible sets None as default for arguments, which is a pain in
# the ass for the purposes of this module
obj = copy.deepcopy(obj) obj = copy.deepcopy(obj)
if isinstance(obj, dict): if isinstance(obj, dict):

View file

@ -12,12 +12,14 @@ EXTRA_ARGS = {
"proxy_type": {"type": "str", "default": "http"}, "proxy_type": {"type": "str", "default": "http"},
"name": {"type": "str"}, "name": {"type": "str"},
"port": {"type": "int"}, "port": {"type": "int"},
"protocol_version": {"type": "int"},
} }
def helper(state: State, service_name: str, params: dict[str, Any]) -> dict[str, Any]: def helper(state: State, service_name: str, params: dict[str, Any]) -> dict[str, Any]:
project_name: str = state.params["name"] project_name: str = state.params["name"]
port: int | None = params.get("port") port: int | None = params.get("port")
protocol_version: int | None = params.get("protocol_version")
proxy_type: str = params["proxy_type"] proxy_type: str = params["proxy_type"]
name: str = params.get("name", f"{project_name}_{service_name}_{proxy_type}") name: str = params.get("name", f"{project_name}_{service_name}_{proxy_type}")
@ -28,6 +30,9 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> dict[str,
if port: if port:
labels[f"{prefix}.loadbalancer.server.port"] = str(port) labels[f"{prefix}.loadbalancer.server.port"] = str(port)
if protocol_version:
labels[f"{prefix}.loadbalancer.proxyProtocol.version"] = str(protocol_version)
return { return {
"labels": labels, "labels": labels,
} }

View file

@ -14,4 +14,7 @@ EXTRA_ARGS = {}
def helper(_state: State, _params: dict[str, Any]) -> dict[str, Any]: def helper(_state: State, _params: dict[str, Any]) -> dict[str, Any]:
return { return {
"privileged": True, "privileged": True,
"networks": {
"internal": {}
}
} }

View file

@ -9,7 +9,7 @@ if TYPE_CHECKING:
from ansible_collections.snailed.ez_docker.plugins.module_utils.models import State from ansible_collections.snailed.ez_docker.plugins.module_utils.models import State
EXTRA_ARGS = { EXTRA_ARGS = {
"read_only": {"type": "bool", "default": True}, "read_only": {"type": "bool", "required": True},
} }
@ -27,4 +27,7 @@ def helper(_state: State, params: dict[str, Any]) -> dict[str, Any]:
return { return {
"volumes": volumes, "volumes": volumes,
"networks": {
"internal": {}
}
} }

View file

@ -11,6 +11,7 @@ if TYPE_CHECKING:
EXTRA_ARGS = { EXTRA_ARGS = {
"archive": {"type": "path"}, "archive": {"type": "path"},
"backup_volumes": {"type": "list", "elements": "str", "required": True}, "backup_volumes": {"type": "list", "elements": "str", "required": True},
"docker_socket_proxy": {"type": "str"}
} }
@ -18,7 +19,7 @@ def helper(state: State, params: dict[str, Any]) -> dict[str, Any]:
project_name: str = state.params["name"] project_name: str = state.params["name"]
archive: str | None = params.get("archive") archive: str | None = params.get("archive")
backup_volumes: list[str] | None = params["backup_volumes"] backup_volumes: list[str] | None = params["backup_volumes"]
service_name = params["name"] socket_proxy: str | None = params.get("docker_socket_proxy")
volumes: list[dict[str, Any]] = [ volumes: list[dict[str, Any]] = [
{ {
@ -35,9 +36,12 @@ def helper(state: State, params: dict[str, Any]) -> dict[str, Any]:
"BACKUP_LATEST_SYMLINK": f"{project_name}-latest", "BACKUP_LATEST_SYMLINK": f"{project_name}-latest",
"BACKUP_PRUNING_PREFIX": f"{project_name}-", "BACKUP_PRUNING_PREFIX": f"{project_name}-",
"BACKUP_STOP_DURING_BACKUP_LABEL": project_name, "BACKUP_STOP_DURING_BACKUP_LABEL": project_name,
"DOCKER_HOST": f"tcp://{project_name}_{service_name}_socket_proxy:2375", # "DOCKER_HOST": f"tcp://{project_name}_{service_name}_socket_proxy:2375",
} }
if socket_proxy:
environment["DOCKER_HOST"] = f"tcp://{socket_proxy}:2375"
if archive: if archive:
environment["BACKUP_ARCHIVE"] = "/archive" environment["BACKUP_ARCHIVE"] = "/archive"
volumes.append( volumes.append(
@ -52,4 +56,7 @@ def helper(state: State, params: dict[str, Any]) -> dict[str, Any]:
return { return {
"environment": environment, "environment": environment,
"volumes": volumes, "volumes": volumes,
"networks": {
"internal": {}
}
} }

View file

@ -76,4 +76,7 @@ def helper(state: State, params: dict[str, Any]) -> dict[str, Any]:
"environment": environment, "environment": environment,
"volumes": volumes, "volumes": volumes,
"labels": labels, "labels": labels,
"networks": {
"internal": {}
}
} }

View file

@ -67,4 +67,7 @@ def helper(state: State, params: dict[str, Any]) -> dict[str, Any]:
"environment": environment, "environment": environment,
"volumes": volumes, "volumes": volumes,
"labels": labels, "labels": labels,
"networks": {
"internal": {}
}
} }

View file

@ -12,4 +12,4 @@ EXTRA_ARGS = {}
def helper(_state: State, _params: dict[str, Any]) -> dict[str, Any]: def helper(_state: State, _params: dict[str, Any]) -> dict[str, Any]:
return {} return {"networks": {"internal": {}}}

View file

@ -50,7 +50,8 @@ def label_argument_spec() -> dict[str, Any]:
label_args["options"][module_name] = { label_args["options"][module_name] = {
"type": "list", "type": "list",
"elements": "dict", "elements": "dict",
"options": get_module_options(module, label.common.BASE_ARGS), "options": get_module_options(module, label.common.BASE_ARGS)
| {"_ezd_no_defaults": {"type": bool}},
} }
return label_args return label_args
@ -67,7 +68,8 @@ def service_argument_spec() -> dict[str, Any]:
service_args["options"][module_name] = { service_args["options"][module_name] = {
"type": "list", "type": "list",
"elements": "dict", "elements": "dict",
"options": get_module_options(module, service.common.BASE_ARGS), "options": get_module_options(module, service.common.BASE_ARGS)
| {"_ezd_no_defaults": {"type": bool}},
} }
return service_args return service_args

View file

@ -5,6 +5,7 @@
from __future__ import annotations from __future__ import annotations
# WARN: This documentation is out of date
# TODO: break this down per module # TODO: break this down per module
# TODO: generate this by reassembling # TODO: generate this by reassembling
# TODO: add note about not setting container_name or host_name in defaults # TODO: add note about not setting container_name or host_name in defaults
@ -508,8 +509,6 @@ def main() -> None:
module.fail_json(f"Error while writing new compose file: {e}") # pyright: ignore[reportUnknownMemberType] module.fail_json(f"Error while writing new compose file: {e}") # pyright: ignore[reportUnknownMemberType]
ret = asdict(state.result) ret = asdict(state.result)
if not module._diff: # noqa: SLF001
del ret["diff"]
module.exit_json(**ret) # pyright: ignore[reportUnknownMemberType] module.exit_json(**ret) # pyright: ignore[reportUnknownMemberType]

View file

@ -19,15 +19,20 @@
services: "{{ project_definition.value }}" services: "{{ project_definition.value }}"
settings: "{{ ez_docker_settings }}" settings: "{{ ez_docker_settings }}"
project_dir: "{{ project_dir }}" project_dir: "{{ project_dir }}"
# no_log: true no_log: true
register: compose register: compose
- name: "project | Start project: {{ project_name }}" - name: "project | Start project: {{ project_name }}"
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
pull: missing pull: missing
project_src: "{{ project_dir }}" project_src: "{{ project_dir }}"
remove_orphans: true
state: "present" state: "present"
- name: "project | Reset file changes: {{ project_name }}"
ansible.builtin.set_fact:
services_changed: []
- name: "project | Import per-service tasks: {{ project_name }}" - name: "project | Import per-service tasks: {{ project_name }}"
ansible.builtin.include_tasks: service.yml ansible.builtin.include_tasks: service.yml
loop: "{{ compose.diff.after.services | dict2items }}" loop: "{{ compose.diff.after.services | dict2items }}"
@ -37,7 +42,7 @@
- name: "project | Restart docker projects: {{ project_name }}" - name: "project | Restart docker projects: {{ project_name }}"
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
services: services_changed services: "{{ services_changed }}"
project_src: "{{ project_dir }}" project_src: "{{ project_dir }}"
state: "restarted" state: "restarted"
when: services_changed when: services_changed

View file

@ -32,3 +32,4 @@
- name: "service | Register file changes: {{ service.value.container_name }}" - name: "service | Register file changes: {{ service.value.container_name }}"
ansible.builtin.set_fact: ansible.builtin.set_fact:
services_changed: "{{ services_changed | default([]) + [service.key] }}" services_changed: "{{ services_changed | default([]) + [service.key] }}"
when: copy.changed or template.changed