diff --git a/plugins/module_utils/common.py b/plugins/module_utils/common.py new file mode 100644 index 0000000..495ea6d --- /dev/null +++ b/plugins/module_utils/common.py @@ -0,0 +1,67 @@ +# Copyright: (c) 2024, Luca Bilke <luca@bil.ke> +# MIT License (see LICENSE) + +from __future__ import annotations + +from typing import Any +import yaml +from pydantic import BaseModel, ConfigDict + +from ansible.module_utils.basic import AnsibleModule + + +class Result(BaseModel): + model_config = ConfigDict(frozen=True) + + changed: bool = False + diff: dict[str, Any] = {} + + +class Settings(BaseModel): + model_config = ConfigDict(frozen=True) + + projects_dir: str = "/usr/local/share/ez_compose/" + + +class State(BaseModel): + model_config = ConfigDict(frozen=True) + + module: AnsibleModule + result: Result + settings: Settings + compose_filename: str + before: dict[str, Any] = {} + after: dict[str, Any] = {} + + +def new_state(module: AnsibleModule) -> State: + settings = Settings(**module.params["settings"]) + + return State( + module=module, + result=Result(), + settings=settings, + compose_filename=( + f"{settings.projects_dir}/" + + f"{module.params['project_name']}/" + + f"{module.params['name']}.yml" + ), + ) + + +def get_compose(state: State) -> State: + file = state.compose_filename + + with open(file, "r") as stream: + compose = yaml.safe_load(stream) + + return state.model_copy(update={"before": compose}) + + +def write_compose(state: State) -> State: + file = state.compose_filename + + with open(file, mode="w") as stream: + yaml.dump(state.after, stream) + + return state diff --git a/plugins/modules/redis.py b/plugins/modules/redis.py new file mode 100644 index 0000000..fe05bc1 --- /dev/null +++ b/plugins/modules/redis.py @@ -0,0 +1,77 @@ +# Copyright: (c) 2024, Luca Bilke <luca@bil.ke> +# MIT License (see LICENSE) + +from __future__ import annotations + +import copy + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.snailed.ez_compose.plugins.module_utils.common import ( + State, + get_compose, + new_state, + write_compose, +) + + +def generate(state: State) -> State: + params = state.module.params + compose = copy.deepcopy(state.before) + + services = compose.get("services", {}) + + container = services.get(params["name"], {}) + container.update( + { + "image": params["image"], + } + ) + + services.update({params["name"]: container}) + + return state.model_copy(update={"after": compose}) + + +def main(): + module = AnsibleModule( + argument_spec={ + "state": { + "type": "str", + "default": "present", + "choices": ["present", "absent"], + }, + "name": { + "type": "str", + "required": True, + }, + "project_name": { + "type": "str", + "required": True, + }, + "image": { + "type": "str", + }, + "settings": { + "type": "dict", + "required": True, + }, + }, + supports_check_mode=True, + ) + + state = new_state(module) + + get_compose(state) + + generate(state) + + if module.check_mode: + module.exit_json(**state.result) # type: ignore[reportUnkownMemberType] + + write_compose(state) + + module.exit_json(**state.result) # type: ignore[reportUnkownMemberType] + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/template b/plugins/modules/template deleted file mode 100644 index 20c2348..0000000 --- a/plugins/modules/template +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2024, Luca Bilke <luca@bil.ke> -# MIT License (see LICENSE) - -from __future__ import annotations -from ansible.module_utils.basic import AnsibleModule - - -def main(): - global module - - module = AnsibleModule( - argument_spec={ - "state": {"type": "str", "default": "present", "choices": ["present", "absent"]}, - "name": {"type": "str"}, - "image": {"type": "str"}, - }, - supports_check_mode=True, - ) - - -if __name__ == "__main__": - main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d0faa40 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +ansible-core==2.17.* +pydantic==2.9.*