#!/usr/bin/python # coding: utf-8 -*- # Copyright (c) 2023, Takuya Nishimura <@nishipy> # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = r""" module: podman_container_exec author: - Takuya Nishimura (@nishipy) short_description: Executes a command in a running container. description: - Executes a command in a running container. options: name: description: - Name of the container where the command is executed. type: str required: true command: description: - The command to run in the container. - One of the I(command) or I(args) is required. type: str argv: description: - Passes the command as a list rather than a string. - One of the I(command) or I(args) is required. type: list elements: str detach: description: - If true, the command runs in the background. - The exec session is automatically removed when it completes. type: bool default: false env: description: - Set environment variables. type: dict executable: description: - The path to the podman executable. type: str default: podman privileged: description: - Give extended privileges to the container. type: bool default: false tty: description: - Allocate a pseudo-TTY. type: bool default: false user: description: - The username or UID used and, optionally, the groupname or GID for the specified command. - Both user and group may be symbolic or numeric. type: str workdir: description: - Working directory inside the container. type: str requirements: - podman notes: - See L(the Podman documentation,https://docs.podman.io/en/latest/markdown/podman-exec.1.html) for details of podman-exec(1). """ EXAMPLES = r""" - name: Execute a command with workdir containers.podman.podman_container_exec: name: ubi8 command: "cat redhat-release" workdir: /etc - name: Execute a command with a list of args and environment variables containers.podman.podman_container_exec: name: test_container argv: - /bin/sh - -c - echo $HELLO $BYE env: HELLO: hello world BYE: goodbye world - name: Execute command in background by using detach containers.podman.podman_container_exec: name: detach_container command: "cat redhat-release" detach: true """ RETURN = r""" stdout: type: str returned: success description: - The standard output of the command executed in the container. stderr: type: str returned: success description: - The standard output of the command executed in the container. rc: type: int returned: success sample: 0 description: - The exit code of the command executed in the container. exec_id: type: str returned: success and I(detach=true) sample: f99002e34c1087fd1aa08d5027e455bf7c2d6b74f019069acf6462a96ddf2a47 description: - The ID of the exec session. """ import shlex try: from ansible.module_utils.common.text.converters import to_text # noqa: F402 except ImportError: from ansible.module_utils.common.text import to_text # noqa: F402 from ansible.module_utils.basic import AnsibleModule from ansible_collections.containers.podman.plugins.module_utils.podman.common import ( run_podman_command, ) def run_container_exec(module: AnsibleModule) -> dict: """ Execute podman-container-exec for the given options """ exec_with_args = ["container", "exec"] # podman_container_exec always returns changed=true changed = True exec_options = [] name = module.params["name"] argv = module.params["argv"] command = module.params["command"] detach = module.params["detach"] env = module.params["env"] privileged = module.params["privileged"] tty = module.params["tty"] user = module.params["user"] workdir = module.params["workdir"] executable = module.params["executable"] if command is not None: argv = shlex.split(command) if detach: exec_options.append("--detach") if env is not None: for key, value in env.items(): if not isinstance(value, str): module.fail_json(msg="Specify string value %s on the env field" % (value)) to_text(value, errors="surrogate_or_strict") exec_options += ["--env", "%s=%s" % (key, value)] if privileged: exec_options.append("--privileged") if tty: exec_options.append("--tty") if user is not None: exec_options += ["--user", to_text(user, errors="surrogate_or_strict")] if workdir is not None: exec_options += ["--workdir", to_text(workdir, errors="surrogate_or_strict")] exec_options.append(name) exec_options.extend(argv) exec_with_args.extend(exec_options) rc, stdout, stderr = run_podman_command( module=module, executable=executable, args=exec_with_args, ignore_errors=True ) result = { "changed": changed, "podman_command": exec_options, "rc": rc, "stdout": stdout, "stderr": stderr, } if detach: result["exec_id"] = stdout.replace("\n", "") return result def main(): argument_spec = { "name": { "type": "str", "required": True, }, "command": { "type": "str", }, "argv": { "type": "list", "elements": "str", }, "detach": { "type": "bool", "default": False, }, "executable": { "type": "str", "default": "podman", }, "env": { "type": "dict", }, "privileged": { "type": "bool", "default": False, }, "tty": { "type": "bool", "default": False, }, "user": { "type": "str", }, "workdir": { "type": "str", }, } module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_one_of=[("argv", "command")], ) result = run_container_exec(module) module.exit_json(**result) if __name__ == "__main__": main()