Skip to content

Commit

Permalink
Add podman_container_exec module (#627)
Browse files Browse the repository at this point in the history
* Add podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Update podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Add tests for podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Update examples for podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Fix CI errors

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Fix CI errors

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Fix typo

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Add workflow for podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Fix python version in the workflow for podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

* Fix python version in the workflow for podman_container_exec

Signed-off-by: nishipy <goodisonev4@gmail.com>

---------

Signed-off-by: nishipy <goodisonev4@gmail.com>
  • Loading branch information
nishipy authored Aug 22, 2023
1 parent c6ae4b9 commit bc3670f
Show file tree
Hide file tree
Showing 4 changed files with 418 additions and 0 deletions.
99 changes: 99 additions & 0 deletions .github/workflows/podman_container_exec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Podman container exec

on:
push:
paths:
- '.github/workflows/podman_container_exec.yml'
- 'ci/*.yml'
- 'ci/run_containers_tests.sh'
- 'ci/playbooks/containers/podman_container_exec.yml'
- 'plugins/modules/podman_container_exec.py'
- 'tests/integration/targets/podman_container_exec/**'
branches:
- master
pull_request:
paths:
- '.github/workflows/podman_container_exec.yml'
- 'ci/*.yml'
- 'ci/run_containers_tests.sh'
- 'ci/playbooks/containers/podman_container_exec.yml'
- 'plugins/modules/podman_container_exec.py'
- 'tests/integration/targets/podman_container_exec/**'
schedule:
- cron: 4 0 * * * # Run daily at 0:03 UTC

jobs:

test_podman_container_exec:
name: Podman container exec ${{ matrix.ansible-version }}-${{ matrix.os || 'ubuntu-22.04' }}
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
defaults:
run:
shell: bash
strategy:
fail-fast: false
matrix:
ansible-version:
- ansible<2.10
# - git+https://github.com/ansible/ansible.git@stable-2.11
- git+https://github.com/ansible/ansible.git@devel
os:
- ubuntu-22.04
python-version:
- "3.10"

steps:

- name: Check out repository
uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Upgrade pip and display Python and PIP versions
run: |
sudo apt-get update
sudo apt-get install -y python*-wheel python*-yaml
python -m pip install --upgrade pip
python -V
pip --version
- name: Set up pip cache
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ github.ref }}-units-VMs
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: Install Ansible ${{ matrix.ansible-version }}
run: python3 -m pip install --user --force-reinstall --upgrade '${{ matrix.ansible-version }}'

- name: Build and install the collection tarball
run: |
rm -rf /tmp/just_new_collection
~/.local/bin/ansible-galaxy collection build --output-path /tmp/just_new_collection --force
~/.local/bin/ansible-galaxy collection install -vvv --force /tmp/just_new_collection/*.tar.gz
- name: Run collection tests for Podman container exec
run: |
export PATH=~/.local/bin:$PATH
echo "Run ansible version"
command -v ansible
ansible --version
export ANSIBLE_CONFIG=$(pwd)/ci/ansible-dev.cfg
if [[ '${{ matrix.ansible-version }}' == 'ansible<2.10' ]]; then
export ANSIBLE_CONFIG=$(pwd)/ci/ansible-2.9.cfg
fi
echo $ANSIBLE_CONFIG
command -v ansible-playbook
pip --version
python --version
ansible-playbook --version
ansible-playbook -vv ci/playbooks/pre.yml \
-e host=localhost \
-i localhost, \
-e ansible_connection=local \
-e setup_python=false
TEST2RUN=podman_container_exec ./ci/run_containers_tests.sh
shell: bash
8 changes: 8 additions & 0 deletions ci/playbooks/containers/podman_container_exec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
- hosts: all
gather_facts: true
tasks:
- include_role:
name: podman_container_exec
vars:
ansible_python_interpreter: "{{ _ansible_python_interpreter }}"
244 changes: 244 additions & 0 deletions plugins/modules/podman_container_exec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
#!/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
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 enviroment 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
from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_text
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']

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, string_types):
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='podman', args=exec_with_args)

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,
},
'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()
Loading

0 comments on commit bc3670f

Please sign in to comment.