WIP
This commit is contained in:
parent
2006d16b30
commit
dd82a95cf1
21 changed files with 325 additions and 456 deletions
4
plugins/__init__.py
Normal file
4
plugins/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""A collection to ease the creation of docker compose files using ansible."""
|
4
plugins/module_utils/__init__.py
Normal file
4
plugins/module_utils/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Module utilities for ez_compose modules."""
|
|
@ -1,17 +1,21 @@
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Common module utilities."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from dataclasses import asdict, dataclass, field, replace
|
from dataclasses import asdict, dataclass, field, replace
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
PROJECTS_DIR = "/var/lib/ez_compose"
|
PROJECTS_DIR = "/var/lib/ez_compose"
|
||||||
BASE_SERVICE_ARGS = {
|
|
||||||
|
BASE_ARGS = {
|
||||||
"project_name": {
|
"project_name": {
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"required": True,
|
"required": True,
|
||||||
|
@ -20,59 +24,41 @@ BASE_SERVICE_ARGS = {
|
||||||
"type": "str",
|
"type": "str",
|
||||||
"required": True,
|
"required": True,
|
||||||
},
|
},
|
||||||
"image": {
|
|
||||||
"type": "str",
|
|
||||||
},
|
|
||||||
"state": {
|
|
||||||
"type": "str",
|
|
||||||
"default": "present",
|
|
||||||
"choices": ["present", "absent"],
|
|
||||||
},
|
|
||||||
"defaults": {
|
|
||||||
"type": "dict",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
BASE_LABEL_ARGS = {
|
|
||||||
"project_name": {
|
|
||||||
"type": "str",
|
|
||||||
"required": True,
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "str",
|
|
||||||
"required": True,
|
|
||||||
},
|
|
||||||
"state": {
|
|
||||||
"type": "str",
|
|
||||||
"default": "present",
|
|
||||||
"choices": ["present", "absent"],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Result:
|
class Result:
|
||||||
|
"""Module result object."""
|
||||||
|
|
||||||
changed: bool = False
|
changed: bool = False
|
||||||
diff: dict[str, Any] = field(default_factory=dict)
|
diff: dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
# @dataclass(frozen=True)
|
||||||
class Settings:
|
# class Settings:
|
||||||
projects_dir: str = "/usr/local/share/ez_compose/"
|
# projects_dir: str = "/usr/local/share/ez_compose/"
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class State:
|
class State:
|
||||||
module: Any # Replace Any with the actual type of AnsibleModule if available
|
"""Execution state object."""
|
||||||
|
|
||||||
|
module: AnsibleModule
|
||||||
result: Result
|
result: Result
|
||||||
compose_filepath: str
|
compose_filepath: str
|
||||||
before: dict[str, Any]
|
before: dict[str, Any]
|
||||||
after: dict[str, Any]
|
after: dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
def _recursive_update(default: dict[Any, Any], update: dict[Any, Any]) -> dict[Any, Any]:
|
def recursive_update(
|
||||||
for key in update:
|
default: dict[Any, Any],
|
||||||
|
update: dict[Any, Any],
|
||||||
|
) -> dict[Any, Any]:
|
||||||
|
"""Recursively update a dictionary."""
|
||||||
|
for key in update: # noqa: PLC0206
|
||||||
if isinstance(update[key], dict) and isinstance(default.get(key), dict):
|
if isinstance(update[key], dict) and isinstance(default.get(key), dict):
|
||||||
default[key] = _recursive_update(default[key], update[key])
|
default[key] = recursive_update(default[key], update[key])
|
||||||
|
|
||||||
elif isinstance(update[key], list) and isinstance(default.get(key), list):
|
elif isinstance(update[key], list) and isinstance(default.get(key), list):
|
||||||
default_set = set(default[key])
|
default_set = set(default[key])
|
||||||
|
@ -86,10 +72,13 @@ def _recursive_update(default: dict[Any, Any], update: dict[Any, Any]) -> dict[A
|
||||||
|
|
||||||
|
|
||||||
def get_state(module: AnsibleModule) -> State:
|
def get_state(module: AnsibleModule) -> State:
|
||||||
compose_filepath = f"{PROJECTS_DIR}/{module.params['project_name']}/docker-compose.yml"
|
"""Create a new state object, loading the compose file into "before" if it exists."""
|
||||||
|
compose_filepath = (
|
||||||
|
f"{PROJECTS_DIR}/{module.params['project_name']}/docker-compose.yml"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(compose_filepath, "r") as fp:
|
with Path(compose_filepath).open("r") as fp:
|
||||||
before = yaml.safe_load(fp)
|
before = yaml.safe_load(fp)
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
@ -100,92 +89,11 @@ def get_state(module: AnsibleModule) -> State:
|
||||||
result=Result(),
|
result=Result(),
|
||||||
compose_filepath=compose_filepath,
|
compose_filepath=compose_filepath,
|
||||||
before=before,
|
before=before,
|
||||||
after=before,
|
after={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def apply_service_base(state: State) -> State:
|
|
||||||
service_name = state.module.params["name"]
|
|
||||||
project_name = state.module.params["project_name"]
|
|
||||||
image = state.module.params["image"]
|
|
||||||
|
|
||||||
update: dict[str, Any] = {
|
|
||||||
"service_name": f"{project_name}_{service_name}",
|
|
||||||
"hostname": f"{project_name}_{service_name}",
|
|
||||||
"image": image,
|
|
||||||
"restart": "unless-stopped",
|
|
||||||
"environment": {},
|
|
||||||
"labels": {},
|
|
||||||
"volumes": [],
|
|
||||||
"networks": {
|
|
||||||
f"{project_name}_internal": None,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return update_service(state, update)
|
|
||||||
|
|
||||||
|
|
||||||
def set_service_defaults(state: State) -> State:
|
|
||||||
container_name = state.module.params["name"]
|
|
||||||
defaults = state.module.params["defaults"]
|
|
||||||
project = copy.deepcopy(state.after)
|
|
||||||
services = project["services"]
|
|
||||||
service = services[container_name]
|
|
||||||
|
|
||||||
_ = _recursive_update(service, defaults)
|
|
||||||
|
|
||||||
services.update({container_name: service})
|
|
||||||
|
|
||||||
return replace(state, after=project)
|
|
||||||
|
|
||||||
|
|
||||||
def update_service(state: State, update: dict[str, Any]) -> State:
|
|
||||||
project = copy.deepcopy(state.after)
|
|
||||||
service_name = state.module.params["name"]
|
|
||||||
|
|
||||||
_ = _recursive_update(project["services"][service_name], update)
|
|
||||||
|
|
||||||
return replace(state, after=project)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_service(state: State) -> State:
|
|
||||||
project = copy.deepcopy(state.after)
|
|
||||||
service_name = state.module.params["name"]
|
|
||||||
|
|
||||||
del project["services"][service_name]
|
|
||||||
|
|
||||||
return replace(state, after=project)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_labels(state: State, label_names: list[str]) -> State:
|
|
||||||
project = copy.deepcopy(state.after)
|
|
||||||
service_name = state.module.params["name"]
|
|
||||||
service = project["services"].get(service_name, {})
|
|
||||||
|
|
||||||
labels = service.get("labels", {})
|
|
||||||
|
|
||||||
if labels:
|
|
||||||
for label in labels:
|
|
||||||
if label in label_names:
|
|
||||||
try:
|
|
||||||
del service["labels"][label]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
service["labels"] = labels
|
|
||||||
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
del service["labels"]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
project["services"][service_name] = service
|
|
||||||
|
|
||||||
return replace(state, after=project)
|
|
||||||
|
|
||||||
|
|
||||||
def update_project(state: State) -> State:
|
def update_project(state: State) -> State:
|
||||||
|
"""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 = project.get("services", {})
|
||||||
|
@ -200,7 +108,7 @@ def update_project(state: State) -> State:
|
||||||
service_volume_name: None
|
service_volume_name: None
|
||||||
for service_volume_name in service_volume_names
|
for service_volume_name in service_volume_names
|
||||||
if service_volume_name not in project_volumes
|
if service_volume_name not in project_volumes
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if service_network_names := service.get("networks").keys():
|
if service_network_names := service.get("networks").keys():
|
||||||
|
@ -209,67 +117,37 @@ def update_project(state: State) -> State:
|
||||||
service_network_name: None
|
service_network_name: None
|
||||||
for service_network_name in service_network_names
|
for service_network_name in service_network_names
|
||||||
if service_network_name not in project_networks
|
if service_network_name not in project_networks
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return replace(state, after=project)
|
return replace(state, after=project)
|
||||||
|
|
||||||
|
|
||||||
def write_compose(state: State) -> State:
|
def write_compose(state: State) -> State:
|
||||||
|
"""Write the compose file to disk."""
|
||||||
file = state.compose_filepath
|
file = state.compose_filepath
|
||||||
|
|
||||||
with open(file, mode="w") as stream:
|
with Path(file).open(mode="w") as stream:
|
||||||
yaml.dump(state.after, stream)
|
yaml.dump(state.after, stream)
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|
||||||
def run_service(
|
def run_module(
|
||||||
extra_args: dict[str, Any] = {},
|
args: dict[str, Any] | None = None,
|
||||||
helper: Callable[[State], State] = lambda _: _,
|
execute: Callable[[State], State] = lambda _: _,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""Handle module setup and teardown."""
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec={**BASE_SERVICE_ARGS, **extra_args},
|
argument_spec={**BASE_ARGS, **(args or {})},
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
state = get_state(module)
|
state = get_state(module)
|
||||||
|
|
||||||
if module.params["state"] == "absent":
|
state = execute(state)
|
||||||
state = remove_service(state)
|
|
||||||
|
|
||||||
else:
|
if not state.module.check_mode:
|
||||||
for f in [apply_service_base, set_service_defaults, helper, update_project]:
|
write_compose(state)
|
||||||
state = f(state)
|
|
||||||
|
|
||||||
exit(state)
|
|
||||||
|
|
||||||
|
|
||||||
def run_label(
|
|
||||||
extra_args: dict[str, Any], helper: Callable[[State], State], label_names: list[str]
|
|
||||||
) -> None:
|
|
||||||
module = AnsibleModule(
|
|
||||||
argument_spec={**BASE_LABEL_ARGS, **extra_args},
|
|
||||||
supports_check_mode=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
state = get_state(module)
|
|
||||||
|
|
||||||
if module.params["state"] == "absent":
|
|
||||||
state = remove_labels(state, label_names)
|
|
||||||
|
|
||||||
else:
|
|
||||||
state = helper(state)
|
|
||||||
|
|
||||||
exit(state)
|
|
||||||
|
|
||||||
|
|
||||||
def exit(state: State) -> None:
|
|
||||||
# TODO: Check diff and set changed variable
|
|
||||||
|
|
||||||
if state.module.check_mode:
|
|
||||||
state.module.exit_json(**asdict(state.result)) # type: ignore[reportUnkownMemberType]
|
|
||||||
|
|
||||||
_ = write_compose(state)
|
|
||||||
|
|
||||||
state.module.exit_json(**asdict(state.result)) # type: ignore[reportUnkownMemberType]
|
state.module.exit_json(**asdict(state.result)) # type: ignore[reportUnkownMemberType]
|
||||||
|
|
4
plugins/module_utils/label/__init__.py
Normal file
4
plugins/module_utils/label/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Module utilities for ez_compose label modules."""
|
21
plugins/module_utils/label/common.py
Normal file
21
plugins/module_utils/label/common.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Label module utilities."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
||||||
|
State,
|
||||||
|
run_module,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(
|
||||||
|
extra_args: dict[str, Any] | None = None,
|
||||||
|
helper: Callable[[State], State] = lambda _: _,
|
||||||
|
) -> None:
|
||||||
|
"""Wrap module execution function for label helpers."""
|
||||||
|
run_module(extra_args or {}, helper)
|
37
plugins/module_utils/label/docker_volume_backupper.py
Normal file
37
plugins/module_utils/label/docker_volume_backupper.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Docker Volume Backup label helper."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.label.common as label
|
||||||
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.service.common as service
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
|
|
||||||
|
def helper(state: State) -> State:
|
||||||
|
"""Add labels to the service to stop it during backup."""
|
||||||
|
stop = state.module.params.get("stop", True)
|
||||||
|
project_name = state.module.params["project_name"]
|
||||||
|
|
||||||
|
update: dict[str, Any] = {}
|
||||||
|
|
||||||
|
if stop:
|
||||||
|
update["labels"] = {
|
||||||
|
"docker-volume-backup.stop-during-backup": project_name,
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
|
def run() -> None:
|
||||||
|
"""Run the backupper label helper."""
|
||||||
|
extra_args = {
|
||||||
|
"stop": {"type": "bool"},
|
||||||
|
}
|
||||||
|
label.run(extra_args, helper)
|
|
@ -1,27 +1,15 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.label.common as label
|
||||||
"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.service.common as service
|
||||||
|
|
||||||
RETURN = r"""
|
if TYPE_CHECKING:
|
||||||
"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_label,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
|
@ -43,7 +31,7 @@ def helper(state: State) -> State:
|
||||||
"labels": labels,
|
"labels": labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -53,7 +41,7 @@ def main():
|
||||||
"middleware": {"type": "str", "required": True},
|
"middleware": {"type": "str", "required": True},
|
||||||
"settings": {"type": "list", "required": True},
|
"settings": {"type": "list", "required": True},
|
||||||
}
|
}
|
||||||
run_label(extra_args, helper)
|
label.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,34 +1,22 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.label.common as label
|
||||||
"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.service.common as service
|
||||||
|
|
||||||
RETURN = r"""
|
if TYPE_CHECKING:
|
||||||
"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_label,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
service_name = state.module.params["name"]
|
service_name = state.module.params["name"]
|
||||||
project_name = state.module.params["project_name"]
|
project_name = state.module.params["project_name"]
|
||||||
rule = state.module.params["rule"]
|
rule = state.module.params["rule"]
|
||||||
service = state.module.params.get("service")
|
traefik_service = state.module.params.get("service")
|
||||||
entrypoints = state.module.params.get("entrypoints")
|
entrypoints = state.module.params.get("entrypoints")
|
||||||
middlewares = state.module.params.get("middlewares")
|
middlewares = state.module.params.get("middlewares")
|
||||||
certresolver = state.module.params.get("certresolver")
|
certresolver = state.module.params.get("certresolver")
|
||||||
|
@ -51,8 +39,8 @@ def helper(state: State) -> State:
|
||||||
if entrypoints:
|
if entrypoints:
|
||||||
labels[f"{prefix}.entrypoints"] = ",".join(entrypoints)
|
labels[f"{prefix}.entrypoints"] = ",".join(entrypoints)
|
||||||
|
|
||||||
if service:
|
if traefik_service:
|
||||||
labels[f"{prefix}.service"] = service
|
labels[f"{prefix}.service"] = traefik_service
|
||||||
|
|
||||||
if middlewares:
|
if middlewares:
|
||||||
labels[f"{prefix}.middlewares"] = ",".join(middlewares)
|
labels[f"{prefix}.middlewares"] = ",".join(middlewares)
|
||||||
|
@ -61,7 +49,7 @@ def helper(state: State) -> State:
|
||||||
"labels": labels,
|
"labels": labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -76,7 +64,7 @@ def main():
|
||||||
"entrypoints": {"type": "list"},
|
"entrypoints": {"type": "list"},
|
||||||
"middlewares": {"type": "list"},
|
"middlewares": {"type": "list"},
|
||||||
}
|
}
|
||||||
run_label(extra_args, helper)
|
label.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,27 +1,15 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.label.common as label
|
||||||
"""
|
import ansible_collections.snailed.ez_compose.plugins.module_utils.service.common as service
|
||||||
|
|
||||||
RETURN = r"""
|
if TYPE_CHECKING:
|
||||||
"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_label,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
@ -48,7 +36,7 @@ def helper(state: State) -> State:
|
||||||
"labels": labels,
|
"labels": labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -57,7 +45,7 @@ def main():
|
||||||
"service_name": {"type": "string"},
|
"service_name": {"type": "string"},
|
||||||
"port": {"type": "int"},
|
"port": {"type": "int"},
|
||||||
}
|
}
|
||||||
run_label(extra_args, helper)
|
label.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
4
plugins/module_utils/service/__init__.py
Normal file
4
plugins/module_utils/service/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Module utilities for ez_compose service modules."""
|
94
plugins/module_utils/service/common.py
Normal file
94
plugins/module_utils/service/common.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
"""Service module utilities."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import copy
|
||||||
|
from dataclasses import replace
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
||||||
|
State,
|
||||||
|
recursive_update,
|
||||||
|
run_module,
|
||||||
|
update_project,
|
||||||
|
)
|
||||||
|
|
||||||
|
BASE_SERVICE_ARGS = {
|
||||||
|
"project_name": {
|
||||||
|
"type": "str",
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "str",
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "str",
|
||||||
|
},
|
||||||
|
"defaults": {
|
||||||
|
"type": "dict",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def apply_base(state: State) -> State:
|
||||||
|
"""Apply base service configuration."""
|
||||||
|
service_name = state.module.params["name"]
|
||||||
|
project_name = state.module.params["project_name"]
|
||||||
|
image = state.module.params["image"]
|
||||||
|
|
||||||
|
new: dict[str, Any] = {
|
||||||
|
"service_name": f"{project_name}_{service_name}",
|
||||||
|
"hostname": f"{project_name}_{service_name}",
|
||||||
|
"image": image,
|
||||||
|
"restart": "unless-stopped",
|
||||||
|
"environment": {},
|
||||||
|
"labels": {},
|
||||||
|
"volumes": [],
|
||||||
|
"networks": {
|
||||||
|
f"{project_name}_internal": None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return update(state, new)
|
||||||
|
|
||||||
|
|
||||||
|
def set_defaults(state: State) -> State:
|
||||||
|
"""Set default values for a service."""
|
||||||
|
container_name = state.module.params["name"]
|
||||||
|
defaults = state.module.params["defaults"]
|
||||||
|
project = copy.deepcopy(state.after)
|
||||||
|
services = project["services"]
|
||||||
|
service = services[container_name]
|
||||||
|
|
||||||
|
_ = recursive_update(service, defaults)
|
||||||
|
|
||||||
|
services.update({container_name: service})
|
||||||
|
|
||||||
|
return replace(state, after=project)
|
||||||
|
|
||||||
|
|
||||||
|
def update(state: State, update: dict[str, Any]) -> State:
|
||||||
|
"""Update a service with the given dictionary."""
|
||||||
|
project = copy.deepcopy(state.after)
|
||||||
|
service_name = state.module.params["name"]
|
||||||
|
|
||||||
|
_ = recursive_update(project["services"][service_name], update)
|
||||||
|
|
||||||
|
return replace(state, after=project)
|
||||||
|
|
||||||
|
|
||||||
|
def run(
|
||||||
|
extra_args: dict[str, Any] | None = None,
|
||||||
|
helper: Callable[[State], State] = lambda _: _,
|
||||||
|
) -> None:
|
||||||
|
"""Wrap module execution function for service helpers."""
|
||||||
|
def execute(state: State) -> State:
|
||||||
|
for f in [apply_base, set_defaults, helper, update_project]:
|
||||||
|
state = f(state)
|
||||||
|
return state
|
||||||
|
|
||||||
|
run_module({**BASE_SERVICE_ARGS, **(extra_args or {})}, execute)
|
|
@ -1,34 +1,21 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
||||||
State,
|
finish,
|
||||||
exit,
|
|
||||||
get_state,
|
get_state,
|
||||||
remove_service,
|
|
||||||
update_project,
|
update_project,
|
||||||
update_service,
|
|
||||||
)
|
)
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
project_name = state.module.params["project_name"]
|
project_name = state.module.params["project_name"]
|
||||||
|
@ -44,7 +31,7 @@ def helper(state: State) -> State:
|
||||||
|
|
||||||
update["networks"] = networks
|
update["networks"] = networks
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -76,14 +63,10 @@ def main():
|
||||||
|
|
||||||
state = get_state(module)
|
state = get_state(module)
|
||||||
|
|
||||||
if module.params["state"] == "absent":
|
for f in [helper, update_project]:
|
||||||
state = remove_service(state)
|
state = f(state)
|
||||||
|
|
||||||
else:
|
finish(state)
|
||||||
for f in [helper, update_project]:
|
|
||||||
state = f(state)
|
|
||||||
|
|
||||||
exit(state)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,28 +1,14 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_service,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
command = state.module.params.get("command")
|
command = state.module.params.get("command")
|
||||||
|
@ -34,14 +20,14 @@ def helper(state: State) -> State:
|
||||||
if command:
|
if command:
|
||||||
update["command"] = command
|
update["command"] = command
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
extra_args = {
|
extra_args = {
|
||||||
"command": {"type": "list"},
|
"command": {"type": "list"},
|
||||||
}
|
}
|
||||||
run_service(extra_args, helper)
|
service.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,27 +1,14 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
if TYPE_CHECKING:
|
||||||
"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_service,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
|
@ -40,14 +27,14 @@ def helper(state: State) -> State:
|
||||||
"volumes": volumes,
|
"volumes": volumes,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
extra_args = {
|
extra_args = {
|
||||||
"read_only": {"type": "bool"},
|
"read_only": {"type": "bool"},
|
||||||
}
|
}
|
||||||
run_service(extra_args, helper)
|
service.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,27 +1,14 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
from typing import TYPE_CHECKING
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
if TYPE_CHECKING:
|
||||||
"""
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_service,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
|
@ -64,7 +51,7 @@ def helper(state: State) -> State:
|
||||||
"volumes": volumes,
|
"volumes": volumes,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -72,7 +59,7 @@ def main():
|
||||||
"archive": {"type": "str"},
|
"archive": {"type": "str"},
|
||||||
"backup_volumes": {"type": "list"},
|
"backup_volumes": {"type": "list"},
|
||||||
}
|
}
|
||||||
run_service(extra_args, helper)
|
service.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,29 +1,15 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
import shlex
|
import shlex
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
State,
|
|
||||||
run_service,
|
if TYPE_CHECKING:
|
||||||
update_service,
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
|
@ -40,7 +26,7 @@ def helper(state: State) -> State:
|
||||||
"source": service_name,
|
"source": service_name,
|
||||||
"target": "/var/lib/mysql",
|
"target": "/var/lib/mysql",
|
||||||
"type": "volume",
|
"type": "volume",
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
|
@ -55,7 +41,7 @@ def helper(state: State) -> State:
|
||||||
environment.update(
|
environment.update(
|
||||||
{
|
{
|
||||||
"MARIADB_ROOT_PASSWORD": root_password,
|
"MARIADB_ROOT_PASSWORD": root_password,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
if backup:
|
if backup:
|
||||||
|
@ -68,8 +54,8 @@ def helper(state: State) -> State:
|
||||||
f"-p {shlex.quote(password)} "
|
f"-p {shlex.quote(password)} "
|
||||||
f">/backup/{shlex.quote(project_name)}.sql"
|
f">/backup/{shlex.quote(project_name)}.sql"
|
||||||
"'"
|
"'"
|
||||||
)
|
),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
# mysqldump -psecret --all-databases > /tmp/dumps/dump.sql
|
# mysqldump -psecret --all-databases > /tmp/dumps/dump.sql
|
||||||
volumes.append(
|
volumes.append(
|
||||||
|
@ -77,7 +63,7 @@ def helper(state: State) -> State:
|
||||||
"type": "volume",
|
"type": "volume",
|
||||||
"source": f"{service_name}_backup",
|
"source": f"{service_name}_backup",
|
||||||
"target": "/backup",
|
"target": "/backup",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
update = {
|
update = {
|
||||||
|
@ -86,7 +72,7 @@ def helper(state: State) -> State:
|
||||||
"labels": labels,
|
"labels": labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -97,7 +83,7 @@ def main():
|
||||||
"password": {"type": "str", "required": True},
|
"password": {"type": "str", "required": True},
|
||||||
"root_password": {"type": "str"},
|
"root_password": {"type": "str"},
|
||||||
}
|
}
|
||||||
run_service(extra_args, helper)
|
service.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
|
@ -1,29 +1,15 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
# MIT License (see LICENSE)
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
# TODO: write ansible sections
|
from __future__ import annotations
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
import shlex
|
import shlex
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
State,
|
|
||||||
run_service,
|
if TYPE_CHECKING:
|
||||||
update_service,
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import State
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
def helper(state: State) -> State:
|
||||||
|
@ -39,7 +25,7 @@ def helper(state: State) -> State:
|
||||||
"source": service_name,
|
"source": service_name,
|
||||||
"target": "/var/lib/postgresql/data",
|
"target": "/var/lib/postgresql/data",
|
||||||
"type": "volume",
|
"type": "volume",
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
|
@ -60,8 +46,8 @@ def helper(state: State) -> State:
|
||||||
f"-U {shlex.quote(username)} "
|
f"-U {shlex.quote(username)} "
|
||||||
f"-f /backup/{shlex.quote(project_name)}.sql"
|
f"-f /backup/{shlex.quote(project_name)}.sql"
|
||||||
"'"
|
"'"
|
||||||
)
|
),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
volumes.append(
|
volumes.append(
|
||||||
|
@ -69,7 +55,7 @@ def helper(state: State) -> State:
|
||||||
"type": "volume",
|
"type": "volume",
|
||||||
"source": f"{service_name}_backup",
|
"source": f"{service_name}_backup",
|
||||||
"target": "/backup",
|
"target": "/backup",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
update = {
|
update = {
|
||||||
|
@ -78,7 +64,7 @@ def helper(state: State) -> State:
|
||||||
"labels": labels,
|
"labels": labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
return update_service(state, update)
|
return service.update(state, update)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -88,7 +74,7 @@ def main():
|
||||||
"username": {"type": "str", "required": True},
|
"username": {"type": "str", "required": True},
|
||||||
"password": {"type": "str", "required": True},
|
"password": {"type": "str", "required": True},
|
||||||
}
|
}
|
||||||
run_service(extra_args, helper)
|
service.run(extra_args, helper)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
14
plugins/module_utils/service/redis.py
Normal file
14
plugins/module_utils/service/redis.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
||||||
|
# MIT License (see LICENSE)
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from ansible_collections.snailed.ez_compose.plugins.module_utils.service import common as service
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
service.run()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,51 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
|
||||||
# MIT License (see LICENSE)
|
|
||||||
|
|
||||||
# TODO: write ansible sections
|
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import (
|
|
||||||
State,
|
|
||||||
run_label,
|
|
||||||
update_service,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def helper(state: State) -> State:
|
|
||||||
stop = state.module.params.get("stop", True)
|
|
||||||
project_name = state.module.params["project_name"]
|
|
||||||
|
|
||||||
update: dict[str, Any] = {}
|
|
||||||
|
|
||||||
if stop:
|
|
||||||
update["labels"] = {
|
|
||||||
"docker-volume-backup.stop-during-backup": project_name,
|
|
||||||
}
|
|
||||||
|
|
||||||
return update_service(state, update)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
extra_args = {
|
|
||||||
"stop": {"type": "bool"},
|
|
||||||
}
|
|
||||||
run_label(extra_args, helper)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
|
|
||||||
# MIT License (see LICENSE)
|
|
||||||
|
|
||||||
# TODO: write ansible sections
|
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations # pyright: ignore[reportGeneralTypeIssues]
|
|
||||||
|
|
||||||
from ansible_collections.snailed.ez_compose.plugins.module_utils.common import run_service
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
run_service()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,18 +1,27 @@
|
||||||
[tool.black]
|
[tool.ruff]
|
||||||
line-length = 100
|
line-length = 100
|
||||||
|
show-fixes = true
|
||||||
|
output-format = "grouped"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
ignore = ["ERA001", "TD002", "TD003"]
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
line-ending = "lf"
|
||||||
|
|
||||||
|
[tool.ruff.lint.mccabe]
|
||||||
|
max-complexity = 10
|
||||||
|
|
||||||
|
[tool.ruff.lint.pydocstyle]
|
||||||
|
convention = "numpy"
|
||||||
|
|
||||||
[tool.basedpyright]
|
[tool.basedpyright]
|
||||||
typeCheckingMode = "strict"
|
typeCheckingMode = "strict"
|
||||||
reportIgnoreCommentWithoutRule = true
|
|
||||||
reportUnusedCallResult = true
|
|
||||||
reportMissingTypeStubs = false
|
|
||||||
|
|
||||||
# handled by ruff
|
# Handled by ruff
|
||||||
reportUnusedVariable = false
|
reportIgnoreCommentWithoutRule = false
|
||||||
reportUnusedImport = false
|
reportUnusedImport = false
|
||||||
reportUndefinedVariable = false
|
reportUnusedClass = false
|
||||||
|
reportUnusedFunction = false
|
||||||
|
reportUnusedVariable = false
|
||||||
[tool.ruff.lint]
|
|
||||||
# Irrelevant for ansible
|
|
||||||
ignore = ["E402", "F404"]
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue