WIP
This commit is contained in:
parent
729cb75ab4
commit
2735859028
16 changed files with 211 additions and 171 deletions
|
@ -4,31 +4,17 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from dataclasses import dataclass, field, replace
|
from dataclasses import replace
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import Result, State
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible.module_utils.basic import AnsibleModule # pyright: ignore[reportMissingTypeStubs]
|
from ansible.module_utils.basic import AnsibleModule # pyright: ignore[reportMissingTypeStubs]
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class Result:
|
|
||||||
changed: bool = False
|
|
||||||
diff: dict[str, Any] = field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class State:
|
|
||||||
module: AnsibleModule
|
|
||||||
result: Result
|
|
||||||
compose_filepath: str
|
|
||||||
before: dict[str, Any]
|
|
||||||
after: dict[str, Any]
|
|
||||||
|
|
||||||
|
|
||||||
def recursive_update(
|
def recursive_update(
|
||||||
default: dict[Any, Any],
|
default: dict[Any, Any],
|
||||||
update: dict[Any, Any],
|
update: dict[Any, Any],
|
||||||
|
@ -67,6 +53,9 @@ def get_state(module: AnsibleModule) -> State:
|
||||||
before=before,
|
before=before,
|
||||||
after={
|
after={
|
||||||
"name": module.params["name"],
|
"name": module.params["name"],
|
||||||
|
"services": {},
|
||||||
|
"networks": {},
|
||||||
|
"volumes": {},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,12 +64,12 @@ def update_project(state: State) -> State:
|
||||||
"""Ensure that networks/volumes that exist in services also exist in the project."""
|
"""Ensure that networks/volumes that exist in services also exist in the project."""
|
||||||
project = copy.deepcopy(state.after)
|
project = copy.deepcopy(state.after)
|
||||||
|
|
||||||
project_services = project.get("services", {})
|
project_services: dict[str, Any] = project.get("services", {})
|
||||||
project_networks = project.get("networks", {})
|
project_networks: dict[str, Any] = project.get("networks", {})
|
||||||
project_volumes = project.get("volumes", {})
|
project_volumes: dict[str, Any] = project.get("volumes", {})
|
||||||
|
|
||||||
for service in project_services:
|
for project_service in [x for x in project_services.values() if x]:
|
||||||
if service_volumes := service.get("volumes"):
|
if service_volumes := project_service.get("volumes"):
|
||||||
service_volume_names = [x["source"] for x in service_volumes]
|
service_volume_names = [x["source"] for x in service_volumes]
|
||||||
project_volumes.update(
|
project_volumes.update(
|
||||||
{
|
{
|
||||||
|
@ -90,7 +79,7 @@ def update_project(state: State) -> State:
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if service_network_names := service.get("networks").keys():
|
if service_network_names := project_service.get("networks", {}).keys():
|
||||||
project_networks.update(
|
project_networks.update(
|
||||||
{
|
{
|
||||||
service_network_name: None
|
service_network_name: None
|
||||||
|
|
|
@ -6,7 +6,7 @@ from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING, Any, Callable
|
from typing import TYPE_CHECKING, Any, Callable
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ BASE_ARGS: dict[str, Any] = {}
|
||||||
|
|
||||||
def run_helper(
|
def run_helper(
|
||||||
state: State,
|
state: State,
|
||||||
helper: Callable[[State], State] = lambda _: _,
|
service_name: str,
|
||||||
|
params: dict[str, Any],
|
||||||
|
helper: Callable[[State, str, dict[str, Any]], State] = lambda a, _b, _c: a,
|
||||||
) -> State:
|
) -> State:
|
||||||
return helper(state)
|
return helper(state, service_name, params)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
|
||||||
middleware: str = params["middleware"]
|
middleware: str = params["middleware"]
|
||||||
settings: dict[str, str] = params["settings"]
|
settings: dict[str, str] = params["settings"]
|
||||||
proxy_type: str = state.module.params["proxy_type"]
|
proxy_type: str = state.module.params["proxy_type"]
|
||||||
name: str = state.module.params.get(
|
name: str = (
|
||||||
"name",
|
params.get("name")
|
||||||
f"{project_name}_{service_name}_{proxy_type}_{middleware.lower()}",
|
or f"{project_name}_{service_name}_{proxy_type}_{middleware.lower()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
prefix = f"traefik.{proxy_type}.middlewares.{name}"
|
prefix = f"traefik.{proxy_type}.middlewares.{name}"
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,10 +31,7 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
|
||||||
middlewares: list[str] | None = params.get("middlewares")
|
middlewares: list[str] | None = params.get("middlewares")
|
||||||
certresolver: str | None = params.get("certresolver")
|
certresolver: str | None = params.get("certresolver")
|
||||||
proxy_type: str = params["proxy_type"]
|
proxy_type: str = params["proxy_type"]
|
||||||
name: str = params.get(
|
name: str = params.get("name") or f"{project_name}_{service_name}_{proxy_type}"
|
||||||
"name",
|
|
||||||
f"{project_name}_{service_name}_{proxy_type}",
|
|
||||||
)
|
|
||||||
|
|
||||||
prefix = f"traefik.{proxy_type}.routers.{name}"
|
prefix = f"traefik.{proxy_type}.routers.{name}"
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,10 +23,7 @@ def helper(state: State, service_name: str, params: dict[str, Any]) -> State:
|
||||||
project_name: str = state.module.params["name"]
|
project_name: str = state.module.params["name"]
|
||||||
port: int | None = params.get("port")
|
port: int | None = params.get("port")
|
||||||
proxy_type: str = params["proxy_type"]
|
proxy_type: str = params["proxy_type"]
|
||||||
name: str = params.get(
|
name: str = params.get("name") or f"{project_name}_{service_name}_{proxy_type}"
|
||||||
"name",
|
|
||||||
f"{project_name}_{service_name}_{proxy_type}",
|
|
||||||
)
|
|
||||||
|
|
||||||
prefix = f"traefik.{proxy_type}.services.{name}"
|
prefix = f"traefik.{proxy_type}.services.{name}"
|
||||||
|
|
||||||
|
|
25
plugins/module_utils/models.py
Normal file
25
plugins/module_utils/models.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ansible.module_utils.basic import AnsibleModule # pyright: ignore[reportMissingTypeStubs]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Result:
|
||||||
|
changed: bool = False
|
||||||
|
diff: dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class State:
|
||||||
|
module: AnsibleModule
|
||||||
|
result: Result
|
||||||
|
compose_filepath: str
|
||||||
|
before: dict[str, Any]
|
||||||
|
after: dict[str, Any]
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"common",
|
"common",
|
||||||
"custom",
|
"custom",
|
||||||
|
|
|
@ -13,13 +13,12 @@ from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
BASE_ARGS: dict[str, Any] = {
|
BASE_ARGS: dict[str, Any] = {
|
||||||
"name": {"type": "str", "required": True},
|
"name": {"type": "str"},
|
||||||
"image": {"type": "str", "required": True},
|
|
||||||
"overwrite": {"type": "dict"},
|
"overwrite": {"type": "dict"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +29,6 @@ def apply_base(state: State, params: dict[str, Any]) -> State:
|
||||||
new: dict[str, Any] = {
|
new: dict[str, Any] = {
|
||||||
"container_name": f"{project_name}_{params['name']}",
|
"container_name": f"{project_name}_{params['name']}",
|
||||||
"hostname": f"{project_name}_{params['name']}",
|
"hostname": f"{project_name}_{params['name']}",
|
||||||
"image": params["image"],
|
|
||||||
"restart": "unless-stopped",
|
"restart": "unless-stopped",
|
||||||
"environment": {},
|
"environment": {},
|
||||||
"labels": {},
|
"labels": {},
|
||||||
|
@ -75,14 +73,17 @@ def update(state: State, params: dict[str, Any], update: dict[str, Any]) -> Stat
|
||||||
service_name: str = params["name"]
|
service_name: str = params["name"]
|
||||||
project = copy.deepcopy(state.after)
|
project = copy.deepcopy(state.after)
|
||||||
|
|
||||||
|
project["services"][service_name] = project["services"].get(service_name, {})
|
||||||
_ = recursive_update(project["services"][service_name], update)
|
_ = recursive_update(project["services"][service_name], update)
|
||||||
|
|
||||||
# FIX: this silently throws out misconfigured volumes
|
# FIX: this silently throws out misconfigured volumes
|
||||||
unique_volumes = {
|
unique_volumes = dict(
|
||||||
vol["target"]: vol
|
{
|
||||||
for vol in project["services"][service_name].get("volumes", [])
|
vol["target"]: vol
|
||||||
if "target" in vol
|
for vol in project["services"][service_name].get("volumes", [])
|
||||||
}.values()
|
if "target" in vol
|
||||||
|
}.values(),
|
||||||
|
)
|
||||||
|
|
||||||
project["services"][service_name]["volumes"] = unique_volumes
|
project["services"][service_name]["volumes"] = unique_volumes
|
||||||
return replace(state, after=project)
|
return replace(state, after=project)
|
||||||
|
@ -93,8 +94,14 @@ def run_helper(
|
||||||
params: dict[str, Any],
|
params: dict[str, Any],
|
||||||
helper: Callable[[State, dict[str, Any]], State] = lambda x, _: x,
|
helper: Callable[[State, dict[str, Any]], State] = lambda x, _: x,
|
||||||
) -> State:
|
) -> State:
|
||||||
|
if not params.get("name"):
|
||||||
|
params["name"] = str.split(helper.__module__, ".")[-1]
|
||||||
|
|
||||||
|
if not params.get("overwrite"):
|
||||||
|
params["overwrite"] = params.get("definition", {})
|
||||||
|
|
||||||
state = apply_base(state, params)
|
state = apply_base(state, params)
|
||||||
state = apply_settings(state, params)
|
state = apply_settings(state, params)
|
||||||
state = helper(state, params)
|
state = helper(state, params)
|
||||||
state = apply_definition(state, params, params.get("overwrite", {}))
|
state = apply_definition(state, params, params["overwrite"])
|
||||||
return update_project(state)
|
return update_project(state)
|
||||||
|
|
|
@ -5,19 +5,18 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import label, service, spec
|
||||||
label,
|
|
||||||
service,
|
|
||||||
)
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE: Label helper arguments are added in the compose module itself
|
FORCE_ARGS = {
|
||||||
EXTRA_ARGS = {
|
"name": {"type": "str", "required": True},
|
||||||
|
"definition": {"type": "dict", "required": True},
|
||||||
"internal_network": {"type": "bool", "default": False},
|
"internal_network": {"type": "bool", "default": False},
|
||||||
|
"label_helpers": spec.label_argument_spec(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +32,8 @@ def helper(state: State, params: dict[str, Any]) -> State:
|
||||||
|
|
||||||
update["networks"] = networks
|
update["networks"] = networks
|
||||||
|
|
||||||
for name, args in params["label_helpers"].items():
|
for name, args in [(x, y) for x, y in params.get("label_helpers", {}).items() if y]:
|
||||||
state = getattr(label, name).helper(state, params["name"], args)
|
helper = getattr(label, name).helper
|
||||||
|
state = label.common.run_helper(state, params["name"], args, helper)
|
||||||
|
|
||||||
return service.common.update(state, params, update)
|
return service.common.update(state, params, update)
|
||||||
|
|
|
@ -8,21 +8,21 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
EXTRA_ARGS = {
|
EXTRA_ARGS = {
|
||||||
"archive": {"type": "path"},
|
"archive": {"type": "path"},
|
||||||
"backup_volumes": {"type": "list", "elements": "str"},
|
"backup_volumes": {"type": "list", "elements": "str", "required": True},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State, params: dict[str, Any]) -> State:
|
def helper(state: State, params: dict[str, Any]) -> State:
|
||||||
|
project_name: str = state.module.params["name"]
|
||||||
archive: str | None = params.get("archive")
|
archive: str | None = params.get("archive")
|
||||||
backup_volumes: list[str] | None = params.get("backup_volumes", [])
|
backup_volumes: list[str] | None = params["backup_volumes"]
|
||||||
service_name = params["name"]
|
service_name = params["name"]
|
||||||
project_name = params["project_name"]
|
|
||||||
|
|
||||||
volumes: list[dict[str, Any]] = [
|
volumes: list[dict[str, Any]] = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ EXTRA_ARGS = {
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State, params: dict[str, Any]) -> State:
|
def helper(state: State, params: dict[str, Any]) -> State:
|
||||||
project_name: str = state.module.params["project_name"]
|
project_name: str = state.module.params["name"]
|
||||||
backup: bool = params["backup"]
|
backup: bool = params["backup"]
|
||||||
database: str = params["database"]
|
database: str = params["database"]
|
||||||
username: str = params["username"]
|
username: str = params["username"]
|
||||||
|
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Any
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import service
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ EXTRA_ARGS = {
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State, params: dict[str, Any]) -> State:
|
def helper(state: State, params: dict[str, Any]) -> State:
|
||||||
project_name: str = state.module.params["project_name"]
|
project_name: str = state.module.params["name"]
|
||||||
backup: bool = params["backup"]
|
backup: bool = params["backup"]
|
||||||
database: str = params["database"]
|
database: str = params["database"]
|
||||||
username: str = params["username"]
|
username: str = params["username"]
|
||||||
|
|
|
@ -6,7 +6,7 @@ from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.models import (
|
||||||
State,
|
State,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
112
plugins/module_utils/spec.py
Normal file
112
plugins/module_utils/spec.py
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import (
|
||||||
|
label,
|
||||||
|
service,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_modules(parent_module: ModuleType) -> list[tuple[str, ModuleType]]:
|
||||||
|
return [
|
||||||
|
(name, getattr(parent_module, name)) for name in parent_module.__all__ if name != "common"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_module_options(
|
||||||
|
module: ModuleType,
|
||||||
|
base_args: dict[str, Any] | None = None,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
if not base_args:
|
||||||
|
base_args = {}
|
||||||
|
|
||||||
|
if force_args := getattr(module, "FORCE_ARGS", None):
|
||||||
|
return force_args
|
||||||
|
|
||||||
|
if extra_args := getattr(module, "EXTRA_ARGS", None):
|
||||||
|
return {
|
||||||
|
**base_args,
|
||||||
|
**extra_args,
|
||||||
|
}
|
||||||
|
|
||||||
|
return base_args
|
||||||
|
|
||||||
|
|
||||||
|
def label_argument_spec() -> dict[str, Any]:
|
||||||
|
label_args: dict[str, Any] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
for module_name, module in get_modules(label):
|
||||||
|
label_args["options"][module_name] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": get_module_options(module, label.common.BASE_ARGS),
|
||||||
|
}
|
||||||
|
|
||||||
|
return label_args
|
||||||
|
|
||||||
|
|
||||||
|
def service_argument_spec() -> dict[str, Any]:
|
||||||
|
service_args: dict[str, Any] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": {},
|
||||||
|
"required": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
for module_name, module in get_modules(service):
|
||||||
|
service_args["options"][module_name] = {
|
||||||
|
"type": "list",
|
||||||
|
"elements": "dict",
|
||||||
|
"options": get_module_options(module, service.common.BASE_ARGS),
|
||||||
|
}
|
||||||
|
|
||||||
|
return service_args
|
||||||
|
|
||||||
|
|
||||||
|
def settings_spec() -> dict[str, Any]:
|
||||||
|
settings: dict[str, Any] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": {
|
||||||
|
"default_definition": {"type": "dict"},
|
||||||
|
"service_default_args": {"type": "dict", "options": {}},
|
||||||
|
"label_default_args": {"type": "dict", "options": {}},
|
||||||
|
"service_default_definitions": {"type": "dict", "options": {}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for module_name, module in get_modules(service):
|
||||||
|
settings["options"]["service_default_definitions"]["options"][module_name] = {
|
||||||
|
"type": "dict",
|
||||||
|
}
|
||||||
|
|
||||||
|
service_args: dict[str, Any] = deepcopy(get_module_options(module))
|
||||||
|
|
||||||
|
for arg in service_args.values():
|
||||||
|
arg.pop("required", None)
|
||||||
|
|
||||||
|
settings["options"]["service_default_args"]["options"][module_name] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": service_args,
|
||||||
|
}
|
||||||
|
|
||||||
|
for module_name, module in get_modules(label):
|
||||||
|
label_args: dict[str, Any] = deepcopy(get_module_options(module))
|
||||||
|
|
||||||
|
for arg in label_args.values():
|
||||||
|
arg.pop("required", None)
|
||||||
|
|
||||||
|
settings["options"]["label_default_args"]["options"][module_name] = {
|
||||||
|
"type": "dict",
|
||||||
|
"options": label_args,
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings
|
|
@ -4,7 +4,10 @@
|
||||||
# ruff: noqa: E402
|
# ruff: noqa: E402
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from pprint import pp
|
||||||
|
|
||||||
|
# TODO: break this down per module
|
||||||
|
# TODO: generate this by reassembling
|
||||||
DOCUMENTATION = """
|
DOCUMENTATION = """
|
||||||
---
|
---
|
||||||
module: compose
|
module: compose
|
||||||
|
@ -449,113 +452,16 @@ options:
|
||||||
type: dict
|
type: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from copy import deepcopy
|
|
||||||
from importlib.util import find_spec
|
from importlib.util import find_spec
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule # pyright: ignore[reportMissingTypeStubs]
|
from ansible.module_utils.basic import AnsibleModule # pyright: ignore[reportMissingTypeStubs]
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils import (
|
||||||
common,
|
common,
|
||||||
label,
|
|
||||||
service,
|
service,
|
||||||
|
spec,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def label_argument_spec() -> dict[str, Any]:
|
|
||||||
label_args: dict[str, Any] = {
|
|
||||||
"type": "dict",
|
|
||||||
"options": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
for module in label.__all__:
|
|
||||||
if module == "common":
|
|
||||||
continue
|
|
||||||
|
|
||||||
options = {
|
|
||||||
**label.common.BASE_ARGS,
|
|
||||||
**getattr(label, module).EXTRA_ARGS,
|
|
||||||
}
|
|
||||||
|
|
||||||
label_args["options"][module] = {
|
|
||||||
"type": "dict",
|
|
||||||
"options": options,
|
|
||||||
}
|
|
||||||
|
|
||||||
return label_args
|
|
||||||
|
|
||||||
|
|
||||||
def service_argument_spec() -> dict[str, Any]:
|
|
||||||
service_args: dict[str, Any] = {
|
|
||||||
"type": "list",
|
|
||||||
"elements": "dict",
|
|
||||||
"suboptions": {},
|
|
||||||
"required": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
for module in service.__all__:
|
|
||||||
if module == "common":
|
|
||||||
continue
|
|
||||||
|
|
||||||
options = {
|
|
||||||
**service.common.BASE_ARGS,
|
|
||||||
**getattr(service, module).EXTRA_ARGS,
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: move to service.common
|
|
||||||
if module == "custom":
|
|
||||||
options["label_helpers"] = label_argument_spec()
|
|
||||||
|
|
||||||
service_args["suboptions"][module] = {
|
|
||||||
"type": "dict",
|
|
||||||
"suboptions": options,
|
|
||||||
}
|
|
||||||
|
|
||||||
return service_args
|
|
||||||
|
|
||||||
|
|
||||||
def settings_spec() -> dict[str, Any]:
|
|
||||||
settings: dict[str, Any] = {
|
|
||||||
"type": "dict",
|
|
||||||
"suboptions": {
|
|
||||||
"default_definition": {"type": "dict"},
|
|
||||||
"service_default_args": {"type": "dict", "suboptions": {}},
|
|
||||||
"service_default_definitions": {"type": "dict", "suboptions": {}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for module in service.__all__:
|
|
||||||
if module == "common":
|
|
||||||
continue
|
|
||||||
|
|
||||||
settings["suboptions"]["service_default_definitions"]["suboptions"][module] = {
|
|
||||||
"type": "dict",
|
|
||||||
}
|
|
||||||
|
|
||||||
args = deepcopy(getattr(service, module).EXTRA_ARGS)
|
|
||||||
for arg in args.values():
|
|
||||||
arg.pop("required", None)
|
|
||||||
|
|
||||||
settings["suboptions"]["service_default_args"]["suboptions"][module] = {
|
|
||||||
"type": "dict",
|
|
||||||
"suboptions": args,
|
|
||||||
}
|
|
||||||
|
|
||||||
for module in label.__all__:
|
|
||||||
if module == "common":
|
|
||||||
continue
|
|
||||||
|
|
||||||
args = deepcopy(getattr(label, module).EXTRA_ARGS)
|
|
||||||
for arg in args.values():
|
|
||||||
arg.pop("required", None)
|
|
||||||
|
|
||||||
settings["suboptions"]["label_default_args"]["suboptions"][module] = {
|
|
||||||
"type": "dict",
|
|
||||||
"suboptions": args,
|
|
||||||
}
|
|
||||||
|
|
||||||
return settings
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec={
|
argument_spec={
|
||||||
|
@ -568,8 +474,8 @@ def main() -> None:
|
||||||
"type": "path",
|
"type": "path",
|
||||||
"default": "/var/lib/ez_compose",
|
"default": "/var/lib/ez_compose",
|
||||||
},
|
},
|
||||||
"settings": settings_spec(),
|
"settings": spec.settings_spec(),
|
||||||
"services": service_argument_spec(),
|
"services": spec.service_argument_spec(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -578,9 +484,11 @@ def main() -> None:
|
||||||
|
|
||||||
state = common.get_state(module)
|
state = common.get_state(module)
|
||||||
|
|
||||||
for name, definitions in module.params["services"].items():
|
for name, services_params in [(x, y) for x, y in module.params["services"].items() if y]:
|
||||||
for definition in definitions:
|
for service_params in services_params:
|
||||||
state = getattr(service, name).helper(state, definition)
|
helper = getattr(service, name).helper
|
||||||
|
state = service.common.run_helper(state, service_params, helper)
|
||||||
|
pp(state.after)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue