Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/[email protected]
- 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