diff --git a/.github/workflows/podman_login_info.yml b/.github/workflows/podman_login_info.yml new file mode 100644 index 0000000..490aca5 --- /dev/null +++ b/.github/workflows/podman_login_info.yml @@ -0,0 +1,110 @@ +name: Podman login info + +on: + push: + paths: + - '.github/workflows/podman_login_info.yml' + - 'ci/*.yml' + - 'ci/run_containers_tests.sh' + - 'ci/playbooks/containers/podman_login_info.yml' + - 'plugins/modules/podman_login_info.py' + - 'tests/integration/targets/podman_login_info/**' + branches: + - master + pull_request: + paths: + - '.github/workflows/podman_login_info.yml' + - 'ci/*.yml' + - 'ci/run_containers_tests.sh' + - 'ci/playbooks/containers/podman_login_info.yml' + - 'plugins/modules/podman_login_info.py' + - 'tests/integration/targets/podman_login_info/**' + schedule: + - cron: 4 0 * * * # Run daily at 0:03 UTC + +jobs: + + test_podman_login_info: + name: Podman login info ${{ matrix.ansible-version }}-${{ matrix.os || 'ubuntu-latest' }} + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + ansible-version: + - ansible<2.10 + # - git+https://github.com/ansible/ansible.git@stable-2.10 + os: + - ubuntu-latest + python-version: + - 3.7 + include: + - os: ubuntu-20.04 + ansible-version: git+https://github.com/ansible/ansible.git@devel + python-version: 3.7 + steps: + + - name: Check out repository + uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + 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@v1 + 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 login info + run: | + export PATH=~/.local/bin:$PATH + + echo "Run ansible version" + command -v ansible + ansible --version + + if [[ '${{ matrix.ansible-version }}' == 'git+https://github.com/ansible/ansible.git@devel' ]]; then + export ANSIBLE_CONFIG=$(pwd)/ci/ansible-dev.cfg + elif [[ '${{ 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_login_info ./ci/run_containers_tests.sh + shell: bash diff --git a/ci/playbooks/containers/podman_login_info.yml b/ci/playbooks/containers/podman_login_info.yml new file mode 100644 index 0000000..499614c --- /dev/null +++ b/ci/playbooks/containers/podman_login_info.yml @@ -0,0 +1,8 @@ +--- +- hosts: all + gather_facts: true + tasks: + - include_role: + name: podman_login_info + vars: + ansible_python_interpreter: "{{ _ansible_python_interpreter }}" diff --git a/plugins/modules/podman_login_info.py b/plugins/modules/podman_login_info.py new file mode 100644 index 0000000..0ff72e4 --- /dev/null +++ b/plugins/modules/podman_login_info.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# 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_login_info +author: + - "Clemens Lange (@clelange)" +version_added: '1.0.0' +short_description: Return the logged-in user if any for a given registry +notes: [] +description: + - Return the logged-in user if any for a given registry. +requirements: + - "Podman installed on host" +options: + registry: + description: + - Registry server. + type: str + required: true + authfile: + description: + - Path of the authentication file. Default is + ``${XDG_RUNTIME_DIR}/containers/auth.json`` + (Not available for remote commands) You can also override the default + path of the authentication file by setting the ``REGISTRY_AUTH_FILE`` + environment variable. ``export REGISTRY_AUTH_FILE=path`` + type: path + executable: + description: + - Path to C(podman) executable if it is not in the C($PATH) on the + machine running C(podman) + default: 'podman' + type: str +""" + +EXAMPLES = r""" +- name: Return the logged-in user for docker hub registry + containers.podman.podman_login_info: + registry: docker.io + +- name: Return the logged-in user for quay.io registry + containers.podman.podman_login_info: + registry: quay.io +""" + +RETURN = r""" +login: + description: Logged in user for a registry + returned: always + type: dict + sample: { + "logged_in": true, + "registry": "docker.io", + "username": "clelange", + } +""" + +import json +from ansible.module_utils.basic import AnsibleModule + + +def get_login_info(module, executable, authfile, registry): + command = [executable, 'login', '--get-login'] + result = dict( + registry=registry, + username='', + logged_in=False, + ) + if authfile: + command.extend(['--authfile', authfile]) + if registry: + command.append(registry) + rc, out, err = module.run_command(command) + if rc != 0: + if 'Error: not logged into' in err: + # The error message is e.g. 'Error: not logged into docker.io' + # Therefore get last word to extract registry name + result["registry"] = err.split()[-1] + err = '' + return result + module.fail_json(msg="Unable to gather info for %s: %s" % (registry, err)) + result["username"] = out.strip() + result["logged_in"] = True + return result + + +def main(): + module = AnsibleModule( + argument_spec=dict( + executable=dict(type='str', default='podman'), + authfile=dict(type='path'), + registry=dict(type='str', required=True) + ), + supports_check_mode=True, + ) + + registry = module.params['registry'] + authfile = module.params['authfile'] + executable = module.get_bin_path(module.params['executable'], required=True) + + inspect_results = get_login_info(module, executable, authfile, registry) + + results = { + "changed": False, + "login": inspect_results, + } + + module.exit_json(**results) + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/podman_login_info/tasks/main.yml b/tests/integration/targets/podman_login_info/tasks/main.yml new file mode 100644 index 0000000..020c844 --- /dev/null +++ b/tests/integration/targets/podman_login_info/tasks/main.yml @@ -0,0 +1,62 @@ +- name: Test podman_login_info + block: + + - name: Print podman version + command: podman version + + - name: Get login info with invalid executable + containers.podman.podman_login_info: + executable: podman_invalid + registry: quay.io + register: invalid_executable + ignore_errors: yes + + - name: Check invalid executable results + assert: + that: + - invalid_executable is failed + + - name: Get login info without specifying registry + containers.podman.podman_login_info: + executable: podman_invalid + register: missing_registry + ignore_errors: yes + + - name: Check missing registry results + assert: + that: + - missing_registry is failed + + - name: Get login info for a non-existing registry + containers.podman.podman_login_info: + registry: non-existing.registry + register: non_existing_registry + + - name: Check non-existing registry results + assert: + that: + - "'login' in non_existing_registry" + - non_existing_registry.login + - "'registry' in non_existing_registry.login" + - "'username' in non_existing_registry.login" + - "'logged_in' in non_existing_registry.login" + - "non_existing_registry.login.registry == 'non-existing.registry'" + - "non_existing_registry.login.username == ''" + - "non_existing_registry.login.logged_in == False" + + - name: Get login info for a non-existing authfile + # This will return not logged in even if logged in via different authfile + containers.podman.podman_login_info: + registry: quay.io + authfile: non-existing.authfile.json + register: non_existing_authfile + + - name: Check non-existing authfile results + assert: + that: + - "'login' in non_existing_authfile" + - non_existing_authfile.login + - "'username' in non_existing_authfile.login" + - "'logged_in' in non_existing_authfile.login" + - "non_existing_authfile.login.username == ''" + - "non_existing_authfile.login.logged_in == False"