# -*- coding: utf-8 -*- import os import subprocess from os import environ from pathlib import Path import requests from ansible.module_utils.basic import AnsibleModule DOCUMENTATION = """ module: tuck author: - Kenneth Benzie (Benie) short_description: Ansible kmodule for the tuck tool options: name: description: - GitHub project name of the package to manage type: str state: description: - Desired state of the package type: str choices: - "latest" - "absent" """ EXAMPLES = """ - name: install package tuck: name: kbenzie/tuck state: present - name: uninstall package tuck: name: kbenzie/tuck state: absent """ def installed(tuck) -> list[str]: result = subprocess.run( [tuck, "list", "--quiet"], capture_output=True, check=True, ) return result.stdout.decode("utf-8").split("\n") def present(tuck: Path, package: str) -> dict: if package in installed(tuck): return dict(changed=False) return latest(tuck, package) def latest(tuck: Path, package: str) -> dict: result = subprocess.run( [tuck, "install", package], capture_output=True, check=True, ) return dict(changed=True, stdout=result.stdout) def absent(tuck: Path, package: str) -> dict: if package not in installed(tuck): return dict(changed=False) result = subprocess.run( [tuck, "remove", package], capture_output=True, check=True, ) return dict(changed=True, stdout=result.stdout) def main(): module = AnsibleModule( argument_spec=dict( name=dict(type="str"), state=dict( type="str", choices=[ "absent", "latest", "present", ], default="present", ), ), supports_check_mode=False, ) tuck = Path(environ["HOME"]) / ".local" / "bin" / "tuck" try: if not (tuck.is_file() and os.access(tuck, os.X_OK)): response = requests.get("https://kbenzie.github.io/tuck/get.sh") response.raise_for_status() subprocess.run( ["/bin/sh"], input=response.text.encode("utf-8"), check=True, ) module.exit_json( **{ "absent": absent, "present": present, "latest": latest, }[module.params["state"]](tuck, module.params["name"]) ) except requests.RequestException as error: module.fail_json(f"failed to install tuck: {error}") except subprocess.CalledProcessError as error: module.fail_json(f"failed to install tuck: {error.stderr}") if __name__ == "__main__": main()