summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/containers/podman
diff options
context:
space:
mode:
Diffstat (limited to 'collections-debian-merged/ansible_collections/containers/podman')
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/CHANGELOG.rst316
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/CODE-OF-CONDUCT.md3
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/COPYING674
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/FILES.json845
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/MANIFEST.json35
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/README.md105
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/SECURITY.md4
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/changelogs/changelog.yaml182
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/changelogs/config.yaml31
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/galaxy.yml.in30
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/connection/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/connection/buildah.py202
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/connection/podman.py224
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/common.py28
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py1479
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py736
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container.py916
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container_info.py405
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_containers.py162
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image.py774
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image_info.py234
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_login_info.py117
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_logout.py154
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network.py614
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network_info.py138
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod.py232
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod_info.py145
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume.py477
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume_info.py100
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/setup.cfg38
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/setup.py8
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/.gitignore1
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml43
-rwxr-xr-xcollections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh24
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory12
-rwxr-xr-xcollections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh28
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory15
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml462
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile32
-rwxr-xr-xcollections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh5
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml30
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml224
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml179
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml40
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml75
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml240
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml204
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml169
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml234
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml204
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml46
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml67
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml153
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml103
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml88
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml642
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile3
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml190
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml50
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml62
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml52
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml224
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml60
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml613
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml48
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml39
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml120
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml103
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml267
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml65
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt5
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt5
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt3
-rw-r--r--collections-debian-merged/ansible_collections/containers/podman/tests/sanity/requirements.txt8
78 files changed, 14645 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/containers/podman/CHANGELOG.rst b/collections-debian-merged/ansible_collections/containers/podman/CHANGELOG.rst
new file mode 100644
index 00000000..6352efb2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/CHANGELOG.rst
@@ -0,0 +1,316 @@
+================================================
+Ansible Podman modules and plugins Release Notes
+================================================
+
+.. contents:: Topics
+
+
+v1.4.1
+======
+
+Release Summary
+---------------
+
+Bugfixes for podman container
+
+Bugfixes
+--------
+
+- podman_container - Convert gidmap to list for podman_container
+- podman_container - Convert log-opts to dictionary and idempotent
+
+v1.4.0
+======
+
+Release Summary
+---------------
+
+New modules and bugfixes, new network options
+
+Minor Changes
+-------------
+
+- podman_container - Add log level for Podman in module
+- podman_container - Add mac_address field to podman_container module
+- podman_container - Add strict image compare with hashes
+- podman_container - Improve compatibility with docker_container by adding aliases
+- podman_container - Move containers logic to module utils
+- podman_image - reuse existing results in present()
+- podman_network - Add IPv6 to network
+- podman_network - Add support of network options like MTU, VLAN
+- podman_pod - Move pod logic to separate library
+
+Bugfixes
+--------
+
+- podman_container - Fix force restart option for containers
+- podman_container - Fix idempotency for volume GID and UID
+- podman_container - Fix no_hosts idempotency for newer version
+- podman_container - Remove 'detach' when creating container
+- podman_image - Fix doc defaults for podman_image
+- podman_logout - Handle podman logout not logging out when logged in via different tool
+- podman_network - Correct IP range example for podman_network
+
+New Modules
+-----------
+
+- containers.podman.podman_containers - Manage multiple Podman containers at once
+- containers.podman.podman_login_info - Get info about Podman logged in registries
+- containers.podman.podman_logout - Log out with Podman from registries
+
+v1.3.2
+======
+
+Release Summary
+---------------
+
+bugfixes
+
+Bugfixes
+--------
+
+- podman_container - Fix signals case for podman_container
+
+v1.3.1
+======
+
+Release Summary
+---------------
+
+bugfixes
+
+Bugfixes
+--------
+
+- multiple modules - fix diff calculation for lower/upper cases
+- podman_container - Add note about containerPort setting
+- podman_container - Fix init option it's boolean not string
+- podman_container - Remove pyyaml from requirements
+- podman_network - Check if dnsname plugin installed for CNI
+- podman_volume - Set options for a volume as list and fix idempotency
+
+v1.3.0
+======
+
+Release Summary
+---------------
+
+New podman_network module and bugfixes
+
+Minor Changes
+-------------
+
+- Create podman_network module for podman networks management
+
+Bugfixes
+--------
+
+- podman_volume - Fix return data from podman_volume module
+
+New Modules
+-----------
+
+- containers.podman.podman_network - Manage Podman networks
+
+v1.2.0
+======
+
+Release Summary
+---------------
+
+Add changelog file.
+
+Minor Changes
+-------------
+
+- Add changelog file to collection.
+
+v1.1.4
+======
+
+Release Summary
+---------------
+
+Pip install and minor fixes.
+
+Minor Changes
+-------------
+
+- Add pip installation for podman collection.
+
+v1.1.3
+======
+
+Release Summary
+---------------
+
+Idempotency fixes for podman containers.
+
+Bugfixes
+--------
+
+- podman_container - Fix idempotency for case with = in env
+- podman_container - Fix issue with idempotency uts, ipc with pod
+
+v1.1.2
+======
+
+Release Summary
+---------------
+
+Urgent fix for podman connection plugin.
+
+Bugfixes
+--------
+
+- podman_connection - Chown file for users when copy them to container
+
+v1.1.1
+======
+
+Release Summary
+---------------
+
+New modules for volumes management.
+
+Minor Changes
+-------------
+
+- Create podman_volume module for volumes management
+
+Bugfixes
+--------
+
+- podman_volume_info - Improve podman volume info tests with new module
+
+New Modules
+-----------
+
+- containers.podman.podman_volume - Manage Podman volumes
+
+v1.1.0
+======
+
+Release Summary
+---------------
+
+New modules for pods management.
+
+Minor Changes
+-------------
+
+- Add podman pod and pod info modules
+
+Bugfixes
+--------
+
+- podman_container - Fix idempotency for networks and add tests
+
+New Modules
+-----------
+
+- containers.podman.podman_pod - Manage Podman pods
+- containers.podman.podman_pod_info - Retrieve information about Podman pods
+
+v1.0.5
+======
+
+Release Summary
+---------------
+
+Idempotency and another bugfixes for podman connection plugin.
+
+Bugfixes
+--------
+
+- podman_connection - Add check for empty dir for podman connection mount
+- podman_connection - Increase verbosity for mount failure messages
+- podman_container - Improve idempotency for volumes with slashesAdd idempotency for ulimits and tests
+- podman_container - Improve ports idempotency and support UDP
+
+v1.0.4
+======
+
+Release Summary
+---------------
+
+Idempotency and Podman v2 fixes
+
+Bugfixes
+--------
+
+- podman_container - Add idempotency for ulimits and tests
+- podman_container - Fix idempotency for podman > 2 versions
+
+v1.0.3
+======
+
+Release Summary
+---------------
+
+Relicense under GPLv3 and clean up modules
+
+Minor Changes
+-------------
+
+- Relicense under GPLv3 and clean up modules
+
+v1.0.2
+======
+
+Release Summary
+---------------
+
+Idempotency fixes
+
+Bugfixes
+--------
+
+- podman_container - Add idempotency for existing local volumes
+
+v1.0.1
+======
+
+Release Summary
+---------------
+
+Idempotency and images improvements
+
+Bugfixes
+--------
+
+- podman_container - Add inspect of image and user idempotency
+- podman_image - Add option for tls_verify=false for images
+
+v1.0.0
+======
+
+Release Summary
+---------------
+
+Initial release of collection with new modules
+
+Minor Changes
+-------------
+
+- buildah_connection - add support of specific user
+- buildah_connection - added Buildah connection rootless
+- podman_connection - add user flags before container id in podman exec
+
+Bugfixes
+--------
+
+- buildah_connection - Fix buildah debug output for py2
+- podman_connection - Run pause=false w/o message condition
+- podman_container - Add idempotency for user and stop signal
+- podman_container - Fix idempotency issues with workdir and volumes
+- podman_container - Fix image, healthcheck and other idempotency
+- podman_container - Improve idempotency of podman_container in uts, ipc, networks, cpu_shares
+- podman_image - only set changed=true if there is a new image
+- podman_image - use correct option for remove_signatures flag
+
+New Modules
+-----------
+
+- containers.podman.podman_container - Manage Podman containers
+- containers.podman.podman_network_info module - Retrieve information about Podman networks
diff --git a/collections-debian-merged/ansible_collections/containers/podman/CODE-OF-CONDUCT.md b/collections-debian-merged/ansible_collections/containers/podman/CODE-OF-CONDUCT.md
new file mode 100644
index 00000000..3833bfad
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/CODE-OF-CONDUCT.md
@@ -0,0 +1,3 @@
+## The Podman Ansible Collections Project Community Code of Conduct
+
+The Podman Ansible Collections project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
diff --git a/collections-debian-merged/ansible_collections/containers/podman/COPYING b/collections-debian-merged/ansible_collections/containers/podman/COPYING
new file mode 100644
index 00000000..f288702d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/collections-debian-merged/ansible_collections/containers/podman/FILES.json b/collections-debian-merged/ansible_collections/containers/podman/FILES.json
new file mode 100644
index 00000000..d77f43ce
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/FILES.json
@@ -0,0 +1,845 @@
+{
+ "files": [
+ {
+ "name": ".",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "setup.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "df77e31936daa4f2509685b9442e8518931651064d466d9f6e0b597ebf92d6cd",
+ "format": 1
+ },
+ {
+ "name": "galaxy.yml.in",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ba21f50b97b7f801dd811f96d4941327fccab34b13311e9bfcc5facfeec16999",
+ "format": 1
+ },
+ {
+ "name": "CHANGELOG.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2405397f51e1165e32f6143c192a63190ba6cd6fec2589a0ec8edf3cb884ea5b",
+ "format": 1
+ },
+ {
+ "name": "plugins",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/podman",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/podman/common.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3f05e994e92dbafccf88acbc4cd13c60502cac1d91d6d5e9541c209e381d2ce8",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/podman/podman_container_lib.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8730c3b385230d19c49a18c630e032c897fcf292ef17bd0c0026e8dd301b93ca",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/podman/podman_pod_lib.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7013f0aff8ce4bd19a256b513d4da891a334e1f242d483de0b703023eeaefd23",
+ "format": 1
+ },
+ {
+ "name": "plugins/module_utils/podman/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/connection",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/connection/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/connection/buildah.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4a3396273b074751c294160d2a72e106cf50a700254b458928409797d73d73f9",
+ "format": 1
+ },
+ {
+ "name": "plugins/connection/podman.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2156de75c958b386a6d680ea568f62c918b0dd3f3c2ffbc34dd5fc02fe24e961",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_image.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bb4317ba8c692f6f7a7b82b6dd12aecf1c58764f942cec52aaeb16e3ea6be74b",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_network.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3b0d6e4e17de28057599dbaa4d2b643e96ff84a1b573e9513e79fe00233cdd56",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_pod_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "66d47cc3b8116869afbc4c970529e6480cb7722862ac25f451292508f9cbd886",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_containers.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8da4189ce3a6c1156b1e427130c27e3d918883bc29815ba4001299fb326546ca",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_container_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "662767f6eb1a1284a77b4405c7dca2930faf4217da86026cccf05110e0e6320d",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_logout.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e93b33f6350423f84574a347f33e94bd071162ef2b79bc0b8ec7b2e71f667164",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_container.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5083df6679d0f401fc987e69777585ed3edd4d49c7a64e13d9c8cbdfa213fe14",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_image_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "65047995f92d7dd14ae3c11a5deae3dd3fe916a8eacfea1094f0a4d702ad1380",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_volume.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5382fcb5c1320bd9fac247984b98d3f9086dd03aa3f49328c299a3d54086c172",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_volume_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "eb8cf9d38d438d24589d547458f4c0ba8341f687eb8a1ded30de1fc0b8933c83",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_network_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9beb6e0c733ca304f38f95116dfd89569df21a68428039ef59ec9650314c5222",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_login_info.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a73d1481551913253f811d95984eec7c19e5ea91847f3fe381cde9176e74222f",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/podman_pod.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "32f847ca079e085fb43414221e9f1aa95cd7d13e20f526af665e54922817b283",
+ "format": 1
+ },
+ {
+ "name": "SECURITY.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b73dc04e41dbb3774a3244e8e40d13eb97d169caa3e1230a622e077d60c1edd9",
+ "format": 1
+ },
+ {
+ "name": "tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3f3f7888f8d4b02194b01ebfc162e12751a736bfa0c78dc5af2a9f4d933c87d6",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6844ce4970c7650072fd11d5c31a0323b8f868619f6038357ef7cae671665a7f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2088981c37e04eba3c9a66e0801d4ea440ad3c987f9785611a1872b89bd0a55b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection/test_connection.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a0c126383c62ba38cf5688d282006c1bc4943d95927bb1e95d3db02a1180c03b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_buildah",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_buildah/runme.sh",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "706de11cf3d424148cbe8060c09e0417ab24cb35d9b4fb7af47595d43722f9b3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_buildah/test_connection.inventory",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5012fc0a2af812b87b675f31cd605ecf8d80fe32667b6ed20ea51fe0c8685742",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "37fe448f10fdc2ebf7537cafc0177d680aa4999f9924c092354fc625b28e905b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a174d23da44b07628cd0328f7568cd40dc35f2203cb3694d90dcb9cef7c3d045",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_volume_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f9499fbf029050fa869b66c40f32297868fcf0e1d4962d67569ecfe87dd8adbb",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "970e52c046870ea2407a8d3397a4648629445f551ff485a5875beed3a1382198",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image/files",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image/files/Containerfile",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ec6bc9968ca494ec22fcb0bed27fc12ddf2241fea1fe58d0d8a4f0b33487b506",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_image/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bfaeb2c66cf4d6275a46f871060ed4bcfc67ef03ffb51df25f537465cfedbd72",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_logout",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_logout/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_logout/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2eb01bf694efdc5320cb8a897f91a42bc63c35f86001c7c45a96ab5ce6cce748",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d66ff4f4f62398759fec5b771c23d6135fd6f6432f0b9fb3b6f3313b8d966dea",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod/tasks/root-pod.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "dd8435b69bbf1d78ddcdda0e13a91b0f0afc66fb4158cf973b830fbaf2e37c8e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod/tasks/net-pod.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "85291241762740e1984c2081ff345d4923ad7d5dbd54d3be9986951c5310ed1e",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_pod/tasks/network-tests.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0f181c4be5e5193fec17680d59e7800d889c9677a1614eb5e13f0bf286e4e42f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_login_info",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_login_info/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_login_info/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a3fd41d974fd43741834251b14d4650e11d97600f59f3e29916e957ae5f8eab0",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_podman",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_podman/runme.sh",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "0d90338274f3a8d2540a17265b3064918c8989a266fd16348cc1b17678d0d877",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/connection_podman/test_connection.inventory",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f75a535c614dbdf71e61eb605b4bd1e857bbec85ff3ae9da0eff6f138f1ae56d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_network/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5a78be16b7f719d896b1f738c944bcf6bfa12abbf44898974b015fd908380c99",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_containers",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_containers/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_containers/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "72cb66e4c58b8f2f3003ae0b8ee4f6fd89edf21ac85a6edd9a3eea1a00001b07",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/files",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/files/Dockerfile",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "afd12e628f7b02a9135c6aa80ee72c226a98bac5b76545b564c4ebd1ab56f772",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/files/start.sh",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bb80ab18f5df29c7c77f8acea5285af4f0f4d1ddac161801d0ff26ac242c2d86",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "164d3be94b787a04cb92878d4325f48b66d355112313b3739a0ccf54ee18ce9d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2e1a16ec44234318280017bbdbc36394ca4cc360a19d501cc8a6d862bf4fd4b2",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "96fc295d3eefde4ac79d7b57cad36b2061f76ea11c8c61442737da8a5316a5d3",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bf27db386dfc434fa6454393a16d868e435a6622b8de12a3601b026dc0ed651c",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "543a6ce2e1a6fb59eb0723f77f41a5877980276d10b89a3e0fa032fa5a390c13",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ea839d720ca73f8ca2adfaa495dd2422e504bed7b55c667ef03e1c7c2e689755",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1a48eed443ea3c636af09a6b4fc582a4cb5b54a9a9c89ed6e174270a3933b1ae",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6b6bda6cff4560e2feba738e98cab6b4547f514b07d663653164561cfb2e9f3d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "157287f51969989865cd7c1a34849fc5a9145e2f9ac283d306ce3077f082e0bf",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "96b0be29c3574812dd33e4e117a91819635b121c66a24ce5eeec2615d7d4280b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fb1c39f891db71f677c686783c7e32449bc2249d2cccf0083746c9d02acc06b1",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "44535a061ffd8b6043430b4330041e1aaf255bc08daf4148b34fbc0df63ad42f",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8ae87843b586035a0d596f9bb531107d60f73a5caec7f67ad4c33269a3514f73",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b629ff1c9a41aa5721f4018b8e8e75b01f867304ba3e34f1b9e39403cc38b33a",
+ "format": 1
+ },
+ {
+ "name": "tests/.gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.11.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a8d07f551872f701cc0e0bf370322ce927d42b4d2672232cc8d575f47a9b0f51",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.10.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a8d07f551872f701cc0e0bf370322ce927d42b4d2672232cc8d575f47a9b0f51",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.9.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f735f0fbd58c43ff739387278d2ea8983a6a97898c68c9fc82f75dff499ee135",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "471c16a6346df1b74757306a436cbab143fe65c30e6f9cda1f5c7179d6012b73",
+ "format": 1
+ },
+ {
+ "name": "README.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5b64357ef4e01867ec98b3e67294979e274a8f2c73c5edebb95678a7c25f4815",
+ "format": 1
+ },
+ {
+ "name": "CODE-OF-CONDUCT.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5b42ff686c8d61fc9879d2512a9fa01f8810a7274318e7952ad3322eeea02f11",
+ "format": 1
+ },
+ {
+ "name": "changelogs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "changelogs/config.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "72cc16b684890f4595ab75ffdd6f80f5ae19bc84cbb2d82606bc840eb7842209",
+ "format": 1
+ },
+ {
+ "name": "changelogs/changelog.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fc1f5607fed0a3d804d5ab8e904da83b4085fbdc97cf80f8328c98da400bb78a",
+ "format": 1
+ },
+ {
+ "name": "setup.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7478e980356fe29366647e7c7d6687b7da68d1ea763d4ca865a75ca9498db1c2",
+ "format": 1
+ },
+ {
+ "name": "COPYING",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986",
+ "format": 1
+ }
+ ],
+ "format": 1
+} \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/containers/podman/MANIFEST.json b/collections-debian-merged/ansible_collections/containers/podman/MANIFEST.json
new file mode 100644
index 00000000..398f0d5a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/MANIFEST.json
@@ -0,0 +1,35 @@
+{
+ "collection_info": {
+ "namespace": "containers",
+ "name": "podman",
+ "version": "1.4.1",
+ "authors": [
+ "Sagi Shnaidman <sshnaidm@redhat.com>",
+ "Ansible team"
+ ],
+ "readme": "README.md",
+ "tags": [
+ "containers",
+ "podman",
+ "libpod"
+ ],
+ "description": "Podman container Ansible modules",
+ "license": [
+ "GPL-3.0-or-later"
+ ],
+ "license_file": null,
+ "dependencies": {},
+ "repository": "https://github.com/containers/ansible-podman-collections.git",
+ "documentation": "https://github.com/containers/ansible-podman-collections",
+ "homepage": "https://github.com/containers/ansible-podman-collections",
+ "issues": "https://github.com/containers/ansible-podman-collections/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc"
+ },
+ "file_manifest_file": {
+ "name": "FILES.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "43a0dc3c62bd183588c40a607b7fcd8a232007b3f2786767c9d2cc494afe5cbf",
+ "format": 1
+ },
+ "format": 1
+} \ No newline at end of file
diff --git a/collections-debian-merged/ansible_collections/containers/podman/README.md b/collections-debian-merged/ansible_collections/containers/podman/README.md
new file mode 100644
index 00000000..a8b9b1f7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/README.md
@@ -0,0 +1,105 @@
+[![GitHub Actions CI/CD build status — Collection test suite](https://github.com/containers/ansible-podman-collections/workflows/Collection%20build%20and%20tests/badge.svg?branch=master)](https://github.com/containers/ansible-podman-collections/actions?query=workflow%3A%22Collection%20build%20and%20tests)
+
+# Ansible Collection: containers.podman
+
+This repo hosts the `containers.podman` Ansible Collection.
+
+The collection includes the Podman container plugins to help the build and management of Podman containers.
+
+## Installation and Usage
+
+### Installing the Collection from Ansible Galaxy
+
+Before using the Podman collection, you need to install the collection with the `ansible-galaxy` CLI:
+
+`ansible-galaxy collection install containers.podman`
+
+You can also include it in a `requirements.yml` file and install it via
+`ansible-galaxy collection install -r requirements.yml` using the format:
+
+```yaml
+collections:
+- name: containers.podman
+```
+
+or clone by your own:
+
+```bash
+mkdir -p ~/.ansible/collections/ansible_collections/containers
+git clone https://github.com/containers/ansible-podman-collections.git ~/.ansible/collections/ansible_collections/containers/podman
+```
+
+### Playbooks
+
+To use a module from Podman collection, please reference the full namespace, collection name,
+and modules name that you want to use:
+
+```yaml
+---
+- name: Using Podman collection
+ hosts: localhost
+ tasks:
+ - name: Run redis container
+ containers.podman.podman_container:
+ name: myredis
+ image: redis
+ command: redis-server --appendonly yes
+ state: present
+ recreate: yes
+ expose:
+ - 6379
+ volumes_from:
+ - mydata
+```
+
+Or you can add full namespace and collection name in the `collections` element:
+
+```yaml
+---
+- name: Using Podman collection
+ hosts: localhost
+ collections:
+ - containers.podman
+ tasks:
+ - name: Build and push an image using existing credentials
+ podman_image:
+ name: nginx
+ path: /path/to/build/dir
+ push: yes
+ push_args:
+ dest: quay.io/acme
+```
+
+## Contributing
+
+We are accepting Github pull requests and issues.
+There are many ways in which you can participate in the project, for example:
+
+- Submit bugs and feature requests, and help us verify them
+- Submit and review source code changes in Github pull requests
+- Add new modules for Podman containers and images
+
+## Testing and Development
+
+If you want to develop new content for this collection or improve what is already
+here, the easiest way to work on the collection is to clone it into one of the configured
+[`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths),
+and work on it there.
+
+### Testing with `ansible-test`
+
+We use `ansible-test` for sanity.
+
+## More Information
+
+TBD
+
+## Communication
+
+Please submit Github issues for communication any issues.
+You can ask Podman related questions on `#podman` channel of Ansible Podman questions
+on `#ansible-podman` channel on Freenode IRC.
+
+## License
+
+GPL-3.0-or-later
diff --git a/collections-debian-merged/ansible_collections/containers/podman/SECURITY.md b/collections-debian-merged/ansible_collections/containers/podman/SECURITY.md
new file mode 100644
index 00000000..aa1f6c18
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/SECURITY.md
@@ -0,0 +1,4 @@
+## Security and Disclosure Information Policy for the Podman Ansible Collections Project
+
+The Podman Ansible Collections Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.
+
diff --git a/collections-debian-merged/ansible_collections/containers/podman/changelogs/changelog.yaml b/collections-debian-merged/ansible_collections/containers/podman/changelogs/changelog.yaml
new file mode 100644
index 00000000..bf1f2a0d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/changelogs/changelog.yaml
@@ -0,0 +1,182 @@
+ancestor: null
+releases:
+ 1.0.0:
+ changes:
+ bugfixes:
+ - buildah_connection - Fix buildah debug output for py2
+ - podman_connection - Run pause=false w/o message condition
+ - podman_container - Add idempotency for user and stop signal
+ - podman_container - Fix idempotency issues with workdir and volumes
+ - podman_container - Fix image, healthcheck and other idempotency
+ - podman_container - Improve idempotency of podman_container in uts, ipc, networks,
+ cpu_shares
+ - podman_image - only set changed=true if there is a new image
+ - podman_image - use correct option for remove_signatures flag
+ minor_changes:
+ - buildah_connection - add support of specific user
+ - buildah_connection - added Buildah connection rootless
+ - podman_connection - add user flags before container id in podman exec
+ release_summary: Initial release of collection with new modules
+ modules:
+ - description: Manage Podman containers
+ name: podman_container
+ namespace: ''
+ - description: Retrieve information about Podman networks
+ name: podman_network_info module
+ namespace: ''
+ release_date: '2020-05-20'
+ 1.0.1:
+ changes:
+ bugfixes:
+ - podman_container - Add inspect of image and user idempotency
+ - podman_image - Add option for tls_verify=false for images
+ release_summary: Idempotency and images improvements
+ release_date: '2020-06-01'
+ 1.0.2:
+ changes:
+ bugfixes:
+ - podman_container - Add idempotency for existing local volumes
+ release_summary: Idempotency fixes
+ release_date: '2020-06-05'
+ 1.0.3:
+ changes:
+ minor_changes:
+ - Relicense under GPLv3 and clean up modules
+ release_summary: Relicense under GPLv3 and clean up modules
+ release_date: '2020-06-08'
+ 1.0.4:
+ changes:
+ bugfixes:
+ - podman_container - Add idempotency for ulimits and tests
+ - podman_container - Fix idempotency for podman > 2 versions
+ release_summary: Idempotency and Podman v2 fixes
+ release_date: '2020-06-29'
+ 1.0.5:
+ changes:
+ bugfixes:
+ - podman_connection - Add check for empty dir for podman connection mount
+ - podman_connection - Increase verbosity for mount failure messages
+ - podman_container - Improve idempotency for volumes with slashesAdd idempotency
+ for ulimits and tests
+ - podman_container - Improve ports idempotency and support UDP
+ release_summary: Idempotency and another bugfixes for podman connection plugin.
+ release_date: '2020-07-09'
+ 1.1.0:
+ changes:
+ bugfixes:
+ - podman_container - Fix idempotency for networks and add tests
+ minor_changes:
+ - Add podman pod and pod info modules
+ release_summary: New modules for pods management.
+ modules:
+ - description: Manage Podman pods
+ name: podman_pod
+ namespace: ''
+ - description: Retrieve information about Podman pods
+ name: podman_pod_info
+ namespace: ''
+ release_date: '2020-07-19'
+ 1.1.1:
+ changes:
+ bugfixes:
+ - podman_volume_info - Improve podman volume info tests with new module
+ minor_changes:
+ - Create podman_volume module for volumes management
+ release_summary: New modules for volumes management.
+ modules:
+ - description: Manage Podman volumes
+ name: podman_volume
+ namespace: ''
+ release_date: '2020-07-22'
+ 1.1.2:
+ changes:
+ bugfixes:
+ - podman_connection - Chown file for users when copy them to container
+ release_summary: Urgent fix for podman connection plugin.
+ release_date: '2020-07-26'
+ 1.1.3:
+ changes:
+ bugfixes:
+ - podman_container - Fix idempotency for case with = in env
+ - podman_container - Fix issue with idempotency uts, ipc with pod
+ release_summary: Idempotency fixes for podman containers.
+ release_date: '2020-07-29'
+ 1.1.4:
+ changes:
+ minor_changes:
+ - Add pip installation for podman collection.
+ release_summary: Pip install and minor fixes.
+ release_date: '2020-08-06'
+ 1.2.0:
+ changes:
+ minor_changes:
+ - Add changelog file to collection.
+ release_summary: Add changelog file.
+ release_date: '2020-08-17'
+ 1.3.0:
+ changes:
+ bugfixes:
+ - podman_volume - Fix return data from podman_volume module
+ minor_changes:
+ - Create podman_network module for podman networks management
+ release_summary: New podman_network module and bugfixes
+ modules:
+ - description: Manage Podman networks
+ name: podman_network
+ namespace: ''
+ release_date: '2020-09-03'
+ 1.3.1:
+ changes:
+ bugfixes:
+ - multiple modules - fix diff calculation for lower/upper cases
+ - podman_container - Add note about containerPort setting
+ - podman_container - Fix init option it's boolean not string
+ - podman_container - Remove pyyaml from requirements
+ - podman_network - Check if dnsname plugin installed for CNI
+ - podman_volume - Set options for a volume as list and fix idempotency
+ release_summary: bugfixes
+ release_date: '2020-10-09'
+ 1.3.2:
+ changes:
+ bugfixes:
+ - podman_container - Fix signals case for podman_container
+ release_summary: bugfixes
+ release_date: '2020-10-20'
+ 1.4.0:
+ changes:
+ bugfixes:
+ - podman_container - Fix force restart option for containers
+ - podman_logout - Handle podman logout not logging out when logged in via different tool
+ - podman_network - Correct IP range example for podman_network
+ - podman_image - Fix doc defaults for podman_image
+ - podman_container - Remove 'detach' when creating container
+ - podman_container - Fix no_hosts idempotency for newer version
+ - podman_container - Fix idempotency for volume GID and UID
+ minor_changes:
+ - podman_container - Add log level for Podman in module
+ - podman_container - Add strict image compare with hashes
+ - podman_container - Move containers logic to module utils
+ - podman_pod - Move pod logic to separate library
+ - podman_container - Improve compatibility with docker_container by adding aliases
+ - podman_image - reuse existing results in present()
+ - podman_container - Add mac_address field to podman_container module
+ - podman_network - Add IPv6 to network
+ - podman_network - Add support of network options like MTU, VLAN
+ release_summary: New modules and bugfixes, new network options
+ modules:
+ - description: Log out with Podman from registries
+ name: podman_logout
+ namespace: ''
+ - description: Get info about Podman logged in registries
+ name: podman_login_info
+ namespace: ''
+ - description: Manage multiple Podman containers at once
+ name: podman_containers
+ namespace: ''
+ release_date: '2020-09-03'
+ 1.4.1:
+ changes:
+ bugfixes:
+ - podman_container - Convert gidmap to list for podman_container
+ - podman_container - Convert log-opts to dictionary and idempotent
+ release_summary: Bugfixes for podman container
diff --git a/collections-debian-merged/ansible_collections/containers/podman/changelogs/config.yaml b/collections-debian-merged/ansible_collections/containers/podman/changelogs/config.yaml
new file mode 100644
index 00000000..39c40f1e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/changelogs/config.yaml
@@ -0,0 +1,31 @@
+changelog_filename_template: ../CHANGELOG.rst
+changelog_filename_version_depth: 0
+changes_file: changelog.yaml
+changes_format: combined
+ignore_other_fragment_extensions: true
+keep_fragments: false
+mention_ancestor: true
+new_plugins_after_name: removed_features
+notesdir: fragments
+prelude_section_name: release_summary
+prelude_section_title: Release Summary
+sections:
+- - major_changes
+ - Major Changes
+- - minor_changes
+ - Minor Changes
+- - breaking_changes
+ - Breaking Changes / Porting Guide
+- - deprecated_features
+ - Deprecated Features
+- - removed_features
+ - Removed Features (previously deprecated)
+- - security_fixes
+ - Security Fixes
+- - bugfixes
+ - Bugfixes
+- - known_issues
+ - Known Issues
+title: Ansible Podman modules and plugins
+trivial_section_name: trivial
+use_fqcn: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/galaxy.yml.in b/collections-debian-merged/ansible_collections/containers/podman/galaxy.yml.in
new file mode 100644
index 00000000..9c40e3f4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/galaxy.yml.in
@@ -0,0 +1,30 @@
+namespace: containers
+name: podman
+# version:
+readme: README.md
+authors:
+ - Sagi Shnaidman <sshnaidm@redhat.com>
+ - Ansible team
+description: Podman container Ansible modules
+license: GPL-3.0-or-later
+tags:
+ - containers
+ - podman
+ - libpod
+dependencies: {}
+repository: https://github.com/containers/ansible-podman-collections.git
+documentation: https://github.com/containers/ansible-podman-collections
+homepage: https://github.com/containers/ansible-podman-collections
+issues: https://github.com/containers/ansible-podman-collections/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
+build_ignore:
+ - ci
+ - tests/output
+ - build_artifact
+ - "*.tar.gz"
+ - ".gitignore"
+ - ".history"
+ - ".vscode"
+ - ".idea"
+ - ".github"
+ - contrib
+ - importer_result.json
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/__init__.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/__init__.py
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/buildah.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/buildah.py
new file mode 100644
index 00000000..748c0ec7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/buildah.py
@@ -0,0 +1,202 @@
+# Based on the docker connection plugin
+# Copyright (c) 2017 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+# Connection plugin for building container images using buildah tool
+# https://github.com/projectatomic/buildah
+#
+# Written by: Tomas Tomecek (https://github.com/TomasTomecek)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+DOCUMENTATION = '''
+ connection: buildah
+ short_description: Interact with an existing buildah container
+ description:
+ - Run commands or put/fetch files to an existing container using buildah tool.
+ author: Tomas Tomecek (ttomecek@redhat.com)
+ options:
+ remote_addr:
+ description:
+ - The ID of the container you want to access.
+ default: inventory_hostname
+ vars:
+ - name: ansible_host
+# keyword:
+# - name: hosts
+ remote_user:
+ description:
+ - User specified via name or ID which is used to execute commands inside the container.
+ ini:
+ - section: defaults
+ key: remote_user
+ env:
+ - name: ANSIBLE_REMOTE_USER
+ vars:
+ - name: ansible_user
+# keyword:
+# - name: remote_user
+'''
+
+import os
+import shlex
+import shutil
+import subprocess
+
+from ansible.errors import AnsibleError
+from ansible.module_utils._text import to_bytes, to_native, to_text
+from ansible.plugins.connection import ConnectionBase, ensure_connect
+from ansible.utils.display import Display
+
+display = Display()
+
+
+# this _has to be_ named Connection
+class Connection(ConnectionBase):
+ """
+ This is a connection plugin for buildah: it uses buildah binary to interact with the containers
+ """
+
+ # String used to identify this Connection class from other classes
+ transport = 'containers.podman.buildah'
+ has_pipelining = True
+
+ def __init__(self, play_context, new_stdin, *args, **kwargs):
+ super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
+
+ self._container_id = self._play_context.remote_addr
+ self._connected = False
+ # container filesystem will be mounted here on host
+ self._mount_point = None
+ # `buildah inspect` doesn't contain info about what the default user is -- if it's not
+ # set, it's empty
+ self.user = self._play_context.remote_user
+ display.vvvv("Using buildah connection from collection")
+
+ def _set_user(self):
+ self._buildah(b"config", [b"--user=" + to_bytes(self.user, errors='surrogate_or_strict')])
+
+ def _buildah(self, cmd, cmd_args=None, in_data=None, outfile_stdout=None):
+ """
+ run buildah executable
+
+ :param cmd: buildah's command to execute (str)
+ :param cmd_args: list of arguments to pass to the command (list of str/bytes)
+ :param in_data: data passed to buildah's stdin
+ :param outfile_stdout: file for writing STDOUT to
+ :return: return code, stdout, stderr
+ """
+ buildah_exec = 'buildah'
+ local_cmd = [buildah_exec]
+
+ if isinstance(cmd, str):
+ local_cmd.append(cmd)
+ else:
+ local_cmd.extend(cmd)
+ if self.user and self.user != 'root':
+ if cmd == 'run':
+ local_cmd.extend(("--user", self.user))
+ elif cmd == 'copy':
+ local_cmd.extend(("--chown", self.user))
+ local_cmd.append(self._container_id)
+
+ if cmd_args:
+ if isinstance(cmd_args, str):
+ local_cmd.append(cmd_args)
+ else:
+ local_cmd.extend(cmd_args)
+
+ local_cmd = [to_bytes(i, errors='surrogate_or_strict')
+ for i in local_cmd]
+
+ display.vvv("RUN %s" % (local_cmd,), host=self._container_id)
+ if outfile_stdout:
+ stdout_fd = open(outfile_stdout, "wb")
+ else:
+ stdout_fd = subprocess.PIPE
+ p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
+ stdout=stdout_fd, stderr=subprocess.PIPE)
+
+ stdout, stderr = p.communicate(input=in_data)
+ display.vvvv("STDOUT %s" % to_text(stdout))
+ display.vvvv("STDERR %s" % to_text(stderr))
+ display.vvvv("RC CODE %s" % p.returncode)
+ stdout = to_bytes(stdout, errors='surrogate_or_strict')
+ stderr = to_bytes(stderr, errors='surrogate_or_strict')
+ return p.returncode, stdout, stderr
+
+ def _connect(self):
+ """
+ no persistent connection is being maintained, mount container's filesystem
+ so we can easily access it
+ """
+ super(Connection, self)._connect()
+ rc, self._mount_point, stderr = self._buildah("mount")
+ if rc != 0:
+ display.v("Failed to mount container %s: %s" % (self._container_id, stderr.strip()))
+ else:
+ self._mount_point = self._mount_point.strip() + to_bytes(os.path.sep, errors='surrogate_or_strict')
+ display.vvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr))
+ self._connected = True
+
+ @ensure_connect
+ def exec_command(self, cmd, in_data=None, sudoable=False):
+ """ run specified command in a running OCI container using buildah """
+ super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
+
+ # shlex.split has a bug with text strings on Python-2.6 and can only handle text strings on Python-3
+ cmd_args_list = shlex.split(to_native(cmd, errors='surrogate_or_strict'))
+
+ rc, stdout, stderr = self._buildah("run", cmd_args_list, in_data)
+
+ display.vvvv("STDOUT %r\nSTDERR %r" % (stderr, stderr))
+ return rc, stdout, stderr
+
+ def put_file(self, in_path, out_path):
+ """ Place a local file located in 'in_path' inside container at 'out_path' """
+ super(Connection, self).put_file(in_path, out_path)
+ display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
+ if not self._mount_point or self.user:
+ rc, stdout, stderr = self._buildah(
+ "copy", [in_path, out_path])
+ if rc != 0:
+ raise AnsibleError(
+ "Failed to copy file from %s to %s in container %s\n%s" % (
+ in_path, out_path, self._container_id, stderr)
+ )
+ else:
+ real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
+ shutil.copyfile(
+ to_bytes(in_path, errors='surrogate_or_strict'),
+ to_bytes(real_out_path, errors='surrogate_or_strict')
+ )
+
+ def fetch_file(self, in_path, out_path):
+ """ obtain file specified via 'in_path' from the container and place it at 'out_path' """
+ super(Connection, self).fetch_file(in_path, out_path)
+ display.vvv("FETCH %s TO %s" %
+ (in_path, out_path), host=self._container_id)
+ if not self._mount_point:
+ rc, stdout, stderr = self._buildah(
+ "run",
+ ["cat", to_bytes(in_path, errors='surrogate_or_strict')],
+ outfile_stdout=out_path)
+ if rc != 0:
+ raise AnsibleError("Failed to fetch file from %s to %s from container %s\n%s" % (
+ in_path, out_path, self._container_id, stderr))
+ else:
+ real_in_path = self._mount_point + \
+ to_bytes(in_path, errors='surrogate_or_strict')
+ shutil.copyfile(
+ to_bytes(real_in_path, errors='surrogate_or_strict'),
+ to_bytes(out_path, errors='surrogate_or_strict')
+ )
+
+ def close(self):
+ """ unmount container's filesystem """
+ super(Connection, self).close()
+ rc, stdout, stderr = self._buildah("umount")
+ display.vvvv("RC %s STDOUT %r STDERR %r" % (rc, stdout, stderr))
+ self._connected = False
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/podman.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/podman.py
new file mode 100644
index 00000000..2e46bd9c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/connection/podman.py
@@ -0,0 +1,224 @@
+# Based on the buildah connection plugin
+# Copyright (c) 2018 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+# Connection plugin to interact with existing podman containers.
+# https://github.com/containers/libpod
+#
+# Written by: Tomas Tomecek (https://github.com/TomasTomecek)
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import distutils.spawn
+import os
+import shlex
+import shutil
+import subprocess
+
+from ansible.errors import AnsibleError
+from ansible.module_utils._text import to_bytes, to_native
+from ansible.plugins.connection import ConnectionBase, ensure_connect
+from ansible.utils.display import Display
+
+display = Display()
+
+
+DOCUMENTATION = '''
+ author: Tomas Tomecek (ttomecek@redhat.com)
+ connection: podman
+ short_description: Interact with an existing podman container
+ description:
+ - Run commands or put/fetch files to an existing container using podman tool.
+ options:
+ remote_addr:
+ description:
+ - The ID of the container you want to access.
+ default: inventory_hostname
+ vars:
+ - name: ansible_host
+ remote_user:
+ description:
+ - User specified via name or UID which is used to execute commands inside the container. If you
+ specify the user via UID, you must set C(ANSIBLE_REMOTE_TMP) to a path that exits
+ inside the container and is writable by Ansible.
+ ini:
+ - section: defaults
+ key: remote_user
+ env:
+ - name: ANSIBLE_REMOTE_USER
+ vars:
+ - name: ansible_user
+ podman_extra_args:
+ description:
+ - Extra arguments to pass to the podman command line.
+ default: ''
+ ini:
+ - section: defaults
+ key: podman_extra_args
+ vars:
+ - name: ansible_podman_extra_args
+ env:
+ - name: ANSIBLE_PODMAN_EXTRA_ARGS
+ podman_executable:
+ description:
+ - Executable for podman command.
+ default: podman
+ vars:
+ - name: ansible_podman_executable
+ env:
+ - name: ANSIBLE_PODMAN_EXECUTABLE
+'''
+
+
+# this _has to be_ named Connection
+class Connection(ConnectionBase):
+ """
+ This is a connection plugin for podman. It uses podman binary to interact with the containers
+ """
+
+ # String used to identify this Connection class from other classes
+ transport = 'containers.podman.podman'
+ has_pipelining = True
+
+ def __init__(self, play_context, new_stdin, *args, **kwargs):
+ super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
+
+ self._container_id = self._play_context.remote_addr
+ self._connected = False
+ # container filesystem will be mounted here on host
+ self._mount_point = None
+ self.user = self._play_context.remote_user
+ display.vvvv("Using podman connection from collection")
+
+ def _podman(self, cmd, cmd_args=None, in_data=None, use_container_id=True):
+ """
+ run podman executable
+
+ :param cmd: podman's command to execute (str or list)
+ :param cmd_args: list of arguments to pass to the command (list of str/bytes)
+ :param in_data: data passed to podman's stdin
+ :return: return code, stdout, stderr
+ """
+ podman_exec = self.get_option('podman_executable')
+ podman_cmd = distutils.spawn.find_executable(podman_exec)
+ if not podman_cmd:
+ raise AnsibleError("%s command not found in PATH" % podman_exec)
+ local_cmd = [podman_cmd]
+ if self.get_option('podman_extra_args'):
+ local_cmd += shlex.split(
+ to_native(
+ self.get_option('podman_extra_args'),
+ errors='surrogate_or_strict'))
+ if isinstance(cmd, str):
+ local_cmd.append(cmd)
+ else:
+ local_cmd.extend(cmd)
+
+ if use_container_id:
+ local_cmd.append(self._container_id)
+ if cmd_args:
+ local_cmd += cmd_args
+ local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
+
+ display.vvv("RUN %s" % (local_cmd,), host=self._container_id)
+ p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ stdout, stderr = p.communicate(input=in_data)
+ display.vvvvv("STDOUT %s" % stdout)
+ display.vvvvv("STDERR %s" % stderr)
+ display.vvvvv("RC CODE %s" % p.returncode)
+ stdout = to_bytes(stdout, errors='surrogate_or_strict')
+ stderr = to_bytes(stderr, errors='surrogate_or_strict')
+ return p.returncode, stdout, stderr
+
+ def _connect(self):
+ """
+ no persistent connection is being maintained, mount container's filesystem
+ so we can easily access it
+ """
+ super(Connection, self)._connect()
+ rc, self._mount_point, stderr = self._podman("mount")
+ if rc != 0:
+ display.vvvv("Failed to mount container %s: %s" % (self._container_id, stderr.strip()))
+ elif not os.listdir(self._mount_point.strip()):
+ display.vvvv("Failed to mount container with CGroups2: empty dir %s" % self._mount_point.strip())
+ self._mount_point = None
+ else:
+ self._mount_point = self._mount_point.strip()
+ display.vvvvv("MOUNTPOINT %s RC %s STDERR %r" % (self._mount_point, rc, stderr))
+ self._connected = True
+
+ @ensure_connect
+ def exec_command(self, cmd, in_data=None, sudoable=False):
+ """ run specified command in a running OCI container using podman """
+ super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
+
+ # shlex.split has a bug with text strings on Python-2.6 and can only handle text strings on Python-3
+ cmd_args_list = shlex.split(to_native(cmd, errors='surrogate_or_strict'))
+ exec_args_list = ["exec"]
+ if self.user:
+ exec_args_list.extend(("--user", self.user))
+
+ rc, stdout, stderr = self._podman(exec_args_list, cmd_args_list, in_data)
+
+ display.vvvvv("STDOUT %r STDERR %r" % (stderr, stderr))
+ return rc, stdout, stderr
+
+ def put_file(self, in_path, out_path):
+ """ Place a local file located in 'in_path' inside container at 'out_path' """
+ super(Connection, self).put_file(in_path, out_path)
+ display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._container_id)
+ if not self._mount_point or self.user:
+ rc, stdout, stderr = self._podman(
+ "cp", [in_path, self._container_id + ":" + out_path], use_container_id=False
+ )
+ if rc != 0:
+ rc, stdout, stderr = self._podman(
+ "cp", ["--pause=false", in_path, self._container_id + ":" + out_path], use_container_id=False
+ )
+ if rc != 0:
+ raise AnsibleError(
+ "Failed to copy file from %s to %s in container %s\n%s" % (
+ in_path, out_path, self._container_id, stderr)
+ )
+ if self.user:
+ rc, stdout, stderr = self._podman(
+ "exec", ["chown", self.user, out_path])
+ if rc != 0:
+ raise AnsibleError(
+ "Failed to chown file %s for user %s in container %s\n%s" % (
+ out_path, self.user, self._container_id, stderr)
+ )
+ else:
+ real_out_path = self._mount_point + to_bytes(out_path, errors='surrogate_or_strict')
+ shutil.copyfile(
+ to_bytes(in_path, errors='surrogate_or_strict'),
+ to_bytes(real_out_path, errors='surrogate_or_strict')
+ )
+
+ def fetch_file(self, in_path, out_path):
+ """ obtain file specified via 'in_path' from the container and place it at 'out_path' """
+ super(Connection, self).fetch_file(in_path, out_path)
+ display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._container_id)
+ if not self._mount_point:
+ rc, stdout, stderr = self._podman(
+ "cp", [self._container_id + ":" + in_path, out_path], use_container_id=False)
+ if rc != 0:
+ raise AnsibleError("Failed to fetch file from %s to %s from container %s\n%s" % (
+ in_path, out_path, self._container_id, stderr))
+ else:
+ real_in_path = self._mount_point + to_bytes(in_path, errors='surrogate_or_strict')
+ shutil.copyfile(
+ to_bytes(real_in_path, errors='surrogate_or_strict'),
+ to_bytes(out_path, errors='surrogate_or_strict')
+ )
+
+ def close(self):
+ """ unmount container's filesystem """
+ super(Connection, self).close()
+ # we actually don't need to unmount since the container is mounted anyway
+ # rc, stdout, stderr = self._podman("umount")
+ # display.vvvvv("RC %s STDOUT %r STDERR %r" % (rc, stdout, stderr))
+ self._connected = False
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/__init__.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/__init__.py
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/__init__.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/__init__.py
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/common.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/common.py
new file mode 100644
index 00000000..d7b0ed79
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/common.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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
+
+
+def run_podman_command(module, executable='podman', args=None, expected_rc=0, ignore_errors=False):
+ if not isinstance(executable, list):
+ command = [executable]
+ if args is not None:
+ command.extend(args)
+ rc, out, err = module.run_command(command)
+ if not ignore_errors and rc != expected_rc:
+ module.fail_json(
+ msg='Failed to run {command} {args}: {err}'.format(
+ command=command, args=args, err=err))
+ return rc, out, err
+
+
+def lower_keys(x):
+ if isinstance(x, list):
+ return [lower_keys(v) for v in x]
+ elif isinstance(x, dict):
+ return dict((k.lower(), lower_keys(v)) for k, v in x.items())
+ else:
+ return x
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py
new file mode 100644
index 00000000..b9fdc431
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py
@@ -0,0 +1,1479 @@
+from __future__ import (absolute_import, division, print_function)
+import json # noqa: F402
+from distutils.version import LooseVersion # noqa: F402
+
+from ansible.module_utils._text import to_bytes, to_native # noqa: F402
+from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
+
+__metaclass__ = type
+
+ARGUMENTS_SPEC_CONTAINER = dict(
+ name=dict(required=True, type='str'),
+ executable=dict(default='podman', type='str'),
+ state=dict(type='str', default='started', choices=[
+ 'absent', 'present', 'stopped', 'started']),
+ image=dict(type='str'),
+ annotation=dict(type='dict'),
+ authfile=dict(type='path'),
+ blkio_weight=dict(type='int'),
+ blkio_weight_device=dict(type='dict'),
+ cap_add=dict(type='list', elements='str', aliases=['capabilities']),
+ cap_drop=dict(type='list', elements='str'),
+ cgroup_parent=dict(type='path'),
+ cgroupns=dict(type='str'),
+ cgroups=dict(type='str', choices=['default', 'disabled']),
+ cidfile=dict(type='path'),
+ cmd_args=dict(type='list', elements='str'),
+ conmon_pidfile=dict(type='path'),
+ command=dict(type='raw'),
+ cpu_period=dict(type='int'),
+ cpu_rt_period=dict(type='int'),
+ cpu_rt_runtime=dict(type='int'),
+ cpu_shares=dict(type='int'),
+ cpus=dict(type='str'),
+ cpuset_cpus=dict(type='str'),
+ cpuset_mems=dict(type='str'),
+ detach=dict(type='bool', default=True),
+ debug=dict(type='bool', default=False),
+ detach_keys=dict(type='str'),
+ device=dict(type='list', elements='str'),
+ device_read_bps=dict(type='list'),
+ device_read_iops=dict(type='list'),
+ device_write_bps=dict(type='list'),
+ device_write_iops=dict(type='list'),
+ dns=dict(type='list', elements='str', aliases=['dns_servers']),
+ dns_option=dict(type='str', aliases=['dns_opts']),
+ dns_search=dict(type='str', aliases=['dns_search_domains']),
+ entrypoint=dict(type='str'),
+ env=dict(type='dict'),
+ env_file=dict(type='path'),
+ env_host=dict(type='bool'),
+ etc_hosts=dict(type='dict', aliases=['add_hosts']),
+ expose=dict(type='list', elements='str', aliases=[
+ 'exposed', 'exposed_ports']),
+ force_restart=dict(type='bool', default=False,
+ aliases=['restart']),
+ gidmap=dict(type='list', elements='str'),
+ group_add=dict(type='list', aliases=['groups']),
+ healthcheck=dict(type='str'),
+ healthcheck_interval=dict(type='str'),
+ healthcheck_retries=dict(type='int'),
+ healthcheck_start_period=dict(type='str'),
+ healthcheck_timeout=dict(type='str'),
+ hostname=dict(type='str'),
+ http_proxy=dict(type='bool'),
+ image_volume=dict(type='str', choices=['bind', 'tmpfs', 'ignore']),
+ image_strict=dict(type='bool', default=False),
+ init=dict(type='bool'),
+ init_path=dict(type='str'),
+ interactive=dict(type='bool'),
+ ip=dict(type='str'),
+ ipc=dict(type='str', aliases=['ipc_mode']),
+ kernel_memory=dict(type='str'),
+ label=dict(type='dict', aliases=['labels']),
+ label_file=dict(type='str'),
+ log_driver=dict(type='str', choices=[
+ 'k8s-file', 'journald', 'json-file']),
+ log_level=dict(
+ type='str',
+ choices=["debug", "info", "warn", "error", "fatal", "panic"]),
+ log_opt=dict(type='dict', aliases=['log_options'],
+ options=dict(
+ max_size=dict(type='str'),
+ path=dict(type='str'),
+ tag=dict(type='str'))),
+ mac_address=dict(type='str'),
+ memory=dict(type='str'),
+ memory_reservation=dict(type='str'),
+ memory_swap=dict(type='str'),
+ memory_swappiness=dict(type='int'),
+ mount=dict(type='str'),
+ network=dict(type='list', elements='str', aliases=['net', 'network_mode']),
+ no_hosts=dict(type='bool'),
+ oom_kill_disable=dict(type='bool'),
+ oom_score_adj=dict(type='int'),
+ pid=dict(type='str', aliases=['pid_mode']),
+ pids_limit=dict(type='str'),
+ pod=dict(type='str'),
+ privileged=dict(type='bool'),
+ publish=dict(type='list', elements='str', aliases=[
+ 'ports', 'published', 'published_ports']),
+ publish_all=dict(type='bool'),
+ read_only=dict(type='bool'),
+ read_only_tmpfs=dict(type='bool'),
+ recreate=dict(type='bool', default=False),
+ restart_policy=dict(type='str'),
+ rm=dict(type='bool', aliases=['remove', 'auto_remove']),
+ rootfs=dict(type='bool'),
+ security_opt=dict(type='list', elements='str'),
+ shm_size=dict(type='str'),
+ sig_proxy=dict(type='bool'),
+ stop_signal=dict(type='int'),
+ stop_timeout=dict(type='int'),
+ subgidname=dict(type='str'),
+ subuidname=dict(type='str'),
+ sysctl=dict(type='dict'),
+ systemd=dict(type='bool'),
+ tmpfs=dict(type='dict'),
+ tty=dict(type='bool'),
+ uidmap=dict(type='list', elements='str'),
+ ulimit=dict(type='list', aliases=['ulimits']),
+ user=dict(type='str'),
+ userns=dict(type='str', aliases=['userns_mode']),
+ uts=dict(type='str'),
+ volume=dict(type='list', elements='str', aliases=['volumes']),
+ volumes_from=dict(type='list', elements='str'),
+ workdir=dict(type='str', aliases=['working_dir'])
+)
+
+
+class PodmanModuleParams:
+ """Creates list of arguments for podman CLI command.
+
+ Arguments:
+ action {str} -- action type from 'run', 'stop', 'create', 'delete',
+ 'start'
+ params {dict} -- dictionary of module parameters
+
+ """
+
+ def __init__(self, action, params, podman_version, module):
+ self.params = params
+ self.action = action
+ self.podman_version = podman_version
+ self.module = module
+
+ def construct_command_from_params(self):
+ """Create a podman command from given module parameters.
+
+ Returns:
+ list -- list of byte strings for Popen command
+ """
+ if self.action in ['start', 'stop', 'delete']:
+ return self.start_stop_delete()
+ if self.action in ['create', 'run']:
+ cmd = [self.action, '--name', self.params['name']]
+ all_param_methods = [func for func in dir(self)
+ if callable(getattr(self, func))
+ and func.startswith("addparam")]
+ params_set = (i for i in self.params if self.params[i] is not None)
+ for param in params_set:
+ func_name = "_".join(["addparam", param])
+ if func_name in all_param_methods:
+ cmd = getattr(self, func_name)(cmd)
+ cmd.append(self.params['image'])
+ if self.params['command']:
+ if isinstance(self.params['command'], list):
+ cmd += self.params['command']
+ else:
+ cmd += self.params['command'].split()
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def start_stop_delete(self):
+
+ if self.action in ['stop', 'start']:
+ cmd = [self.action, self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ if self.action == 'delete':
+ cmd = ['rm', '-f', self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def check_version(self, param, minv=None, maxv=None):
+ if minv and LooseVersion(minv) > LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported from podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+ if maxv and LooseVersion(maxv) < LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported till podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+
+ def addparam_annotation(self, c):
+ for annotate in self.params['annotation'].items():
+ c += ['--annotation', '='.join(annotate)]
+ return c
+
+ def addparam_authfile(self, c):
+ return c + ['--authfile', self.params['authfile']]
+
+ def addparam_blkio_weight(self, c):
+ return c + ['--blkio-weight', self.params['blkio_weight']]
+
+ def addparam_blkio_weight_device(self, c):
+ for blkio in self.params['blkio_weight_device'].items():
+ c += ['--blkio-weight-device', ':'.join(blkio)]
+ return c
+
+ def addparam_cap_add(self, c):
+ for cap_add in self.params['cap_add']:
+ c += ['--cap-add', cap_add]
+ return c
+
+ def addparam_cap_drop(self, c):
+ for cap_drop in self.params['cap_drop']:
+ c += ['--cap-drop', cap_drop]
+ return c
+
+ def addparam_cgroups(self, c):
+ self.check_version('--cgroups', minv='1.6.0')
+ return c + ['--cgroups=%s' % self.params['cgroups']]
+
+ def addparam_cgroupns(self, c):
+ self.check_version('--cgroupns', minv='1.6.2')
+ return c + ['--cgroupns=%s' % self.params['cgroupns']]
+
+ def addparam_cgroup_parent(self, c):
+ return c + ['--cgroup-parent', self.params['cgroup_parent']]
+
+ def addparam_cidfile(self, c):
+ return c + ['--cidfile', self.params['cidfile']]
+
+ def addparam_conmon_pidfile(self, c):
+ return c + ['--conmon-pidfile', self.params['conmon_pidfile']]
+
+ def addparam_cpu_period(self, c):
+ return c + ['--cpu-period', self.params['cpu_period']]
+
+ def addparam_cpu_rt_period(self, c):
+ return c + ['--cpu-rt-period', self.params['cpu_rt_period']]
+
+ def addparam_cpu_rt_runtime(self, c):
+ return c + ['--cpu-rt-runtime', self.params['cpu_rt_runtime']]
+
+ def addparam_cpu_shares(self, c):
+ return c + ['--cpu-shares', self.params['cpu_shares']]
+
+ def addparam_cpus(self, c):
+ return c + ['--cpus', self.params['cpus']]
+
+ def addparam_cpuset_cpus(self, c):
+ return c + ['--cpuset-cpus', self.params['cpuset_cpus']]
+
+ def addparam_cpuset_mems(self, c):
+ return c + ['--cpuset-mems', self.params['cpuset_mems']]
+
+ def addparam_detach(self, c):
+ return c + ['--detach=%s' % self.params['detach']]
+
+ def addparam_detach_keys(self, c):
+ return c + ['--detach-keys', self.params['detach_keys']]
+
+ def addparam_device(self, c):
+ for dev in self.params['device']:
+ c += ['--device', dev]
+ return c
+
+ def addparam_device_read_bps(self, c):
+ for dev in self.params['device_read_bps']:
+ c += ['--device-read-bps', dev]
+ return c
+
+ def addparam_device_read_iops(self, c):
+ for dev in self.params['device_read_iops']:
+ c += ['--device-read-iops', dev]
+ return c
+
+ def addparam_device_write_bps(self, c):
+ for dev in self.params['device_write_bps']:
+ c += ['--device-write-bps', dev]
+ return c
+
+ def addparam_device_write_iops(self, c):
+ for dev in self.params['device_write_iops']:
+ c += ['--device-write-iops', dev]
+ return c
+
+ def addparam_dns(self, c):
+ return c + ['--dns', ','.join(self.params['dns'])]
+
+ def addparam_dns_option(self, c):
+ return c + ['--dns-option', self.params['dns_option']]
+
+ def addparam_dns_search(self, c):
+ return c + ['--dns-search', self.params['dns_search']]
+
+ def addparam_entrypoint(self, c):
+ return c + ['--entrypoint', self.params['entrypoint']]
+
+ def addparam_env(self, c):
+ for env_value in self.params['env'].items():
+ c += ['--env',
+ b"=".join([to_bytes(k, errors='surrogate_or_strict')
+ for k in env_value])]
+ return c
+
+ def addparam_env_file(self, c):
+ return c + ['--env-file', self.params['env_file']]
+
+ def addparam_env_host(self, c):
+ self.check_version('--env-host', minv='1.5.0')
+ return c + ['--env-host=%s' % self.params['env_host']]
+
+ def addparam_etc_hosts(self, c):
+ for host_ip in self.params['etc_hosts'].items():
+ c += ['--add-host', ':'.join(host_ip)]
+ return c
+
+ def addparam_expose(self, c):
+ for exp in self.params['expose']:
+ c += ['--expose', exp]
+ return c
+
+ def addparam_gidmap(self, c):
+ for gidmap in self.params['gidmap']:
+ c += ['--gidmap', gidmap]
+ return c
+
+ def addparam_group_add(self, c):
+ for g in self.params['group_add']:
+ c += ['--group-add', g]
+ return c
+
+ def addparam_healthcheck(self, c):
+ return c + ['--healthcheck-command', self.params['healthcheck']]
+
+ def addparam_healthcheck_interval(self, c):
+ return c + ['--healthcheck-interval',
+ self.params['healthcheck_interval']]
+
+ def addparam_healthcheck_retries(self, c):
+ return c + ['--healthcheck-retries',
+ self.params['healthcheck_retries']]
+
+ def addparam_healthcheck_start_period(self, c):
+ return c + ['--healthcheck-start-period',
+ self.params['healthcheck_start_period']]
+
+ def addparam_healthcheck_timeout(self, c):
+ return c + ['--healthcheck-timeout',
+ self.params['healthcheck_timeout']]
+
+ def addparam_hostname(self, c):
+ return c + ['--hostname', self.params['hostname']]
+
+ def addparam_http_proxy(self, c):
+ return c + ['--http-proxy=%s' % self.params['http_proxy']]
+
+ def addparam_image_volume(self, c):
+ return c + ['--image-volume', self.params['image_volume']]
+
+ def addparam_init(self, c):
+ if self.params['init']:
+ c += ['--init']
+ return c
+
+ def addparam_init_path(self, c):
+ return c + ['--init-path', self.params['init_path']]
+
+ def addparam_interactive(self, c):
+ return c + ['--interactive=%s' % self.params['interactive']]
+
+ def addparam_ip(self, c):
+ return c + ['--ip', self.params['ip']]
+
+ def addparam_ipc(self, c):
+ return c + ['--ipc', self.params['ipc']]
+
+ def addparam_kernel_memory(self, c):
+ return c + ['--kernel-memory', self.params['kernel_memory']]
+
+ def addparam_label(self, c):
+ for label in self.params['label'].items():
+ c += ['--label', b'='.join([to_bytes(l, errors='surrogate_or_strict')
+ for l in label])]
+ return c
+
+ def addparam_label_file(self, c):
+ return c + ['--label-file', self.params['label_file']]
+
+ def addparam_log_driver(self, c):
+ return c + ['--log-driver', self.params['log_driver']]
+
+ def addparam_log_opt(self, c):
+ for k, v in self.params['log_opt'].items():
+ if v is not None:
+ c += ['--log-opt',
+ b"=".join([to_bytes(k.replace('max_size', 'max-size'),
+ errors='surrogate_or_strict'),
+ to_bytes(v,
+ errors='surrogate_or_strict')])]
+ return c
+
+ def addparam_log_level(self, c):
+ return c + ['--log-level', self.params['log_level']]
+
+ def addparam_mac_address(self, c):
+ return c + ['--mac-address', self.params['mac_address']]
+
+ def addparam_memory(self, c):
+ return c + ['--memory', self.params['memory']]
+
+ def addparam_memory_reservation(self, c):
+ return c + ['--memory-reservation', self.params['memory_reservation']]
+
+ def addparam_memory_swap(self, c):
+ return c + ['--memory-swap', self.params['memory_swap']]
+
+ def addparam_memory_swappiness(self, c):
+ return c + ['--memory-swappiness', self.params['memory_swappiness']]
+
+ def addparam_mount(self, c):
+ return c + ['--mount', self.params['mount']]
+
+ def addparam_network(self, c):
+ return c + ['--network', ",".join(self.params['network'])]
+
+ def addparam_no_hosts(self, c):
+ return c + ['--no-hosts=%s' % self.params['no_hosts']]
+
+ def addparam_oom_kill_disable(self, c):
+ return c + ['--oom-kill-disable=%s' % self.params['oom_kill_disable']]
+
+ def addparam_oom_score_adj(self, c):
+ return c + ['--oom-score-adj', self.params['oom_score_adj']]
+
+ def addparam_pid(self, c):
+ return c + ['--pid', self.params['pid']]
+
+ def addparam_pids_limit(self, c):
+ return c + ['--pids-limit', self.params['pids_limit']]
+
+ def addparam_pod(self, c):
+ return c + ['--pod', self.params['pod']]
+
+ def addparam_privileged(self, c):
+ return c + ['--privileged=%s' % self.params['privileged']]
+
+ def addparam_publish(self, c):
+ for pub in self.params['publish']:
+ c += ['--publish', pub]
+ return c
+
+ def addparam_publish_all(self, c):
+ return c + ['--publish-all=%s' % self.params['publish_all']]
+
+ def addparam_read_only(self, c):
+ return c + ['--read-only=%s' % self.params['read_only']]
+
+ def addparam_read_only_tmpfs(self, c):
+ return c + ['--read-only-tmpfs=%s' % self.params['read_only_tmpfs']]
+
+ def addparam_restart_policy(self, c):
+ return c + ['--restart=%s' % self.params['restart_policy']]
+
+ def addparam_rm(self, c):
+ if self.params['rm']:
+ c += ['--rm']
+ return c
+
+ def addparam_rootfs(self, c):
+ return c + ['--rootfs=%s' % self.params['rootfs']]
+
+ def addparam_security_opt(self, c):
+ for secopt in self.params['security_opt']:
+ c += ['--security-opt', secopt]
+ return c
+
+ def addparam_shm_size(self, c):
+ return c + ['--shm-size', self.params['shm_size']]
+
+ def addparam_sig_proxy(self, c):
+ return c + ['--sig-proxy=%s' % self.params['sig_proxy']]
+
+ def addparam_stop_signal(self, c):
+ return c + ['--stop-signal', self.params['stop_signal']]
+
+ def addparam_stop_timeout(self, c):
+ return c + ['--stop-timeout', self.params['stop_timeout']]
+
+ def addparam_subgidname(self, c):
+ return c + ['--subgidname', self.params['subgidname']]
+
+ def addparam_subuidname(self, c):
+ return c + ['--subuidname', self.params['subuidname']]
+
+ def addparam_sysctl(self, c):
+ for sysctl in self.params['sysctl'].items():
+ c += ['--sysctl',
+ b"=".join([to_bytes(k, errors='surrogate_or_strict')
+ for k in sysctl])]
+ return c
+
+ def addparam_systemd(self, c):
+ return c + ['--systemd=%s' % self.params['systemd']]
+
+ def addparam_tmpfs(self, c):
+ for tmpfs in self.params['tmpfs'].items():
+ c += ['--tmpfs', ':'.join(tmpfs)]
+ return c
+
+ def addparam_tty(self, c):
+ return c + ['--tty=%s' % self.params['tty']]
+
+ def addparam_uidmap(self, c):
+ for uidmap in self.params['uidmap']:
+ c += ['--uidmap', uidmap]
+ return c
+
+ def addparam_ulimit(self, c):
+ for u in self.params['ulimit']:
+ c += ['--ulimit', u]
+ return c
+
+ def addparam_user(self, c):
+ return c + ['--user', self.params['user']]
+
+ def addparam_userns(self, c):
+ return c + ['--userns', self.params['userns']]
+
+ def addparam_uts(self, c):
+ return c + ['--uts', self.params['uts']]
+
+ def addparam_volume(self, c):
+ for vol in self.params['volume']:
+ if vol:
+ c += ['--volume', vol]
+ return c
+
+ def addparam_volumes_from(self, c):
+ for vol in self.params['volumes_from']:
+ c += ['--volumes-from', vol]
+ return c
+
+ def addparam_workdir(self, c):
+ return c + ['--workdir', self.params['workdir']]
+
+ # Add your own args for podman command
+ def addparam_cmd_args(self, c):
+ return c + self.params['cmd_args']
+
+
+class PodmanDefaults:
+ def __init__(self, image_info, podman_version):
+ self.version = podman_version
+ self.image_info = image_info
+ self.defaults = {
+ "blkio_weight": 0,
+ "cgroups": "default",
+ "cidfile": "",
+ "cpus": 0.0,
+ "cpu_shares": 0,
+ "cpu_quota": 0,
+ "cpu_period": 0,
+ "cpu_rt_runtime": 0,
+ "cpu_rt_period": 0,
+ "cpuset_cpus": "",
+ "cpuset_mems": "",
+ "detach": True,
+ "device": [],
+ "env_host": False,
+ "etc_hosts": {},
+ "group_add": [],
+ "ipc": "",
+ "kernelmemory": "0",
+ "log_driver": "k8s-file",
+ "log_level": "error",
+ "memory": "0",
+ "memory_swap": "0",
+ "memory_reservation": "0",
+ # "memory_swappiness": -1,
+ "no_hosts": False,
+ # libpod issue with networks in inspection
+ "oom_score_adj": 0,
+ "pid": "",
+ "privileged": False,
+ "rm": False,
+ "security_opt": [],
+ "stop_signal": self.image_info['config'].get('stopsignal', "15"),
+ "tty": False,
+ "user": self.image_info.get('user', ''),
+ "workdir": self.image_info['config'].get('workingdir', '/'),
+ "uts": "",
+ }
+
+ def default_dict(self):
+ # make here any changes to self.defaults related to podman version
+ # https://github.com/containers/libpod/pull/5669
+ if (LooseVersion(self.version) >= LooseVersion('1.8.0')
+ and LooseVersion(self.version) < LooseVersion('1.9.0')):
+ self.defaults['cpu_shares'] = 1024
+ if (LooseVersion(self.version) >= LooseVersion('2.0.0')):
+ self.defaults['network'] = ["slirp4netns"]
+ self.defaults['ipc'] = "private"
+ self.defaults['uts'] = "private"
+ self.defaults['pid'] = "private"
+ return self.defaults
+
+
+class PodmanContainerDiff:
+ def __init__(self, module, module_params, info, image_info, podman_version):
+ self.module = module
+ self.module_params = module_params
+ self.version = podman_version
+ self.default_dict = None
+ self.info = lower_keys(info)
+ self.image_info = lower_keys(image_info)
+ self.params = self.defaultize()
+ self.diff = {'before': {}, 'after': {}}
+ self.non_idempotent = {
+ 'env_file', # We can't get env vars from file to check
+ 'env_host',
+ }
+
+ def defaultize(self):
+ params_with_defaults = {}
+ self.default_dict = PodmanDefaults(
+ self.image_info, self.version).default_dict()
+ for p in self.module_params:
+ if self.module_params[p] is None and p in self.default_dict:
+ params_with_defaults[p] = self.default_dict[p]
+ else:
+ params_with_defaults[p] = self.module_params[p]
+ return params_with_defaults
+
+ def _diff_update_and_compare(self, param_name, before, after):
+ if before != after:
+ self.diff['before'].update({param_name: before})
+ self.diff['after'].update({param_name: after})
+ return True
+ return False
+
+ def diffparam_annotation(self):
+ before = self.info['config']['annotations'] or {}
+ after = before.copy()
+ if self.module_params['annotation'] is not None:
+ after.update(self.params['annotation'])
+ return self._diff_update_and_compare('annotation', before, after)
+
+ def diffparam_env_host(self):
+ # It's impossible to get from inspest, recreate it if not default
+ before = False
+ after = self.params['env_host']
+ return self._diff_update_and_compare('env_host', before, after)
+
+ def diffparam_blkio_weight(self):
+ before = self.info['hostconfig']['blkioweight']
+ after = self.params['blkio_weight']
+ return self._diff_update_and_compare('blkio_weight', before, after)
+
+ def diffparam_blkio_weight_device(self):
+ before = self.info['hostconfig']['blkioweightdevice']
+ if before == [] and self.module_params['blkio_weight_device'] is None:
+ after = []
+ else:
+ after = self.params['blkio_weight_device']
+ return self._diff_update_and_compare('blkio_weight_device', before, after)
+
+ def diffparam_cap_add(self):
+ before = self.info['effectivecaps'] or []
+ after = []
+ if self.module_params['cap_add'] is not None:
+ after += ["cap_" + i.lower()
+ for i in self.module_params['cap_add']]
+ after += before
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('cap_add', before, after)
+
+ def diffparam_cap_drop(self):
+ before = self.info['effectivecaps'] or []
+ after = before[:]
+ if self.module_params['cap_drop'] is not None:
+ for c in ["cap_" + i.lower() for i in self.module_params['cap_drop']]:
+ if c in after:
+ after.remove(c)
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('cap_drop', before, after)
+
+ def diffparam_cgroup_parent(self):
+ before = self.info['hostconfig']['cgroupparent']
+ after = self.params['cgroup_parent']
+ if after is None:
+ after = before
+ return self._diff_update_and_compare('cgroup_parent', before, after)
+
+ def diffparam_cgroups(self):
+ # Cgroups output is not supported in all versions
+ if 'cgroups' in self.info['hostconfig']:
+ before = self.info['hostconfig']['cgroups']
+ after = self.params['cgroups']
+ return self._diff_update_and_compare('cgroups', before, after)
+ return False
+
+ def diffparam_cidfile(self):
+ before = self.info['hostconfig']['containeridfile']
+ after = self.params['cidfile']
+ return self._diff_update_and_compare('cidfile', before, after)
+
+ def diffparam_command(self):
+ # TODO(sshnaidm): to inspect image to get the default command
+ if self.module_params['command'] is not None:
+ before = self.info['config']['cmd']
+ after = self.params['command']
+ if isinstance(after, str):
+ after = [i.lower() for i in after.split()]
+ elif isinstance(after, list):
+ after = [i.lower() for i in after]
+ return self._diff_update_and_compare('command', before, after)
+ return False
+
+ def diffparam_conmon_pidfile(self):
+ before = self.info['conmonpidfile']
+ if self.module_params['conmon_pidfile'] is None:
+ after = before
+ else:
+ after = self.params['conmon_pidfile']
+ return self._diff_update_and_compare('conmon_pidfile', before, after)
+
+ def diffparam_cpu_period(self):
+ before = self.info['hostconfig']['cpuperiod']
+ after = self.params['cpu_period']
+ return self._diff_update_and_compare('cpu_period', before, after)
+
+ def diffparam_cpu_rt_period(self):
+ before = self.info['hostconfig']['cpurealtimeperiod']
+ after = self.params['cpu_rt_period']
+ return self._diff_update_and_compare('cpu_rt_period', before, after)
+
+ def diffparam_cpu_rt_runtime(self):
+ before = self.info['hostconfig']['cpurealtimeruntime']
+ after = self.params['cpu_rt_runtime']
+ return self._diff_update_and_compare('cpu_rt_runtime', before, after)
+
+ def diffparam_cpu_shares(self):
+ before = self.info['hostconfig']['cpushares']
+ after = self.params['cpu_shares']
+ return self._diff_update_and_compare('cpu_shares', before, after)
+
+ def diffparam_cpus(self):
+ before = int(self.info['hostconfig']['nanocpus']) / 1000000000
+ after = self.params['cpus']
+ return self._diff_update_and_compare('cpus', before, after)
+
+ def diffparam_cpuset_cpus(self):
+ before = self.info['hostconfig']['cpusetcpus']
+ after = self.params['cpuset_cpus']
+ return self._diff_update_and_compare('cpuset_cpus', before, after)
+
+ def diffparam_cpuset_mems(self):
+ before = self.info['hostconfig']['cpusetmems']
+ after = self.params['cpuset_mems']
+ return self._diff_update_and_compare('cpuset_mems', before, after)
+
+ def diffparam_device(self):
+ before = [":".join([i['pathonhost'], i['pathincontainer']])
+ for i in self.info['hostconfig']['devices']]
+ after = [":".join(i.split(":")[:2]) for i in self.params['device']]
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('devices', before, after)
+
+ def diffparam_device_read_bps(self):
+ before = self.info['hostconfig']['blkiodevicereadbps'] or []
+ before = ["%s:%s" % (i['path'], i['rate']) for i in before]
+ after = self.params['device_read_bps'] or []
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('device_read_bps', before, after)
+
+ def diffparam_device_read_iops(self):
+ before = self.info['hostconfig']['blkiodevicereadiops'] or []
+ before = ["%s:%s" % (i['path'], i['rate']) for i in before]
+ after = self.params['device_read_iops'] or []
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('device_read_iops', before, after)
+
+ def diffparam_device_write_bps(self):
+ before = self.info['hostconfig']['blkiodevicewritebps'] or []
+ before = ["%s:%s" % (i['path'], i['rate']) for i in before]
+ after = self.params['device_write_bps'] or []
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('device_write_bps', before, after)
+
+ def diffparam_device_write_iops(self):
+ before = self.info['hostconfig']['blkiodevicewriteiops'] or []
+ before = ["%s:%s" % (i['path'], i['rate']) for i in before]
+ after = self.params['device_write_iops'] or []
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('device_write_iops', before, after)
+
+ # Limited idempotency, it can't guess default values
+ def diffparam_env(self):
+ env_before = self.info['config']['env'] or {}
+ before = {i.split("=")[0]: "=".join(i.split("=")[1:])
+ for i in env_before}
+ after = before.copy()
+ if self.params['env']:
+ after.update({
+ k: v
+ for k, v in self.params['env'].items()
+ })
+ return self._diff_update_and_compare('env', before, after)
+
+ def diffparam_etc_hosts(self):
+ if self.info['hostconfig']['extrahosts']:
+ before = dict([i.split(":")
+ for i in self.info['hostconfig']['extrahosts']])
+ else:
+ before = {}
+ after = self.params['etc_hosts']
+ return self._diff_update_and_compare('etc_hosts', before, after)
+
+ def diffparam_group_add(self):
+ before = self.info['hostconfig']['groupadd']
+ after = self.params['group_add']
+ return self._diff_update_and_compare('group_add', before, after)
+
+ # Healthcheck is only defined in container config if a healthcheck
+ # was configured; otherwise the config key isn't part of the config.
+ def diffparam_healthcheck(self):
+ if 'healthcheck' in self.info['config']:
+ # the "test" key is a list of 2 items where the first one is
+ # "CMD-SHELL" and the second one is the actual healthcheck command.
+ before = self.info['config']['healthcheck']['test'][1]
+ else:
+ before = ''
+ after = self.params['healthcheck'] or before
+ return self._diff_update_and_compare('healthcheck', before, after)
+
+ # Because of hostname is random generated, this parameter has partial idempotency only.
+ def diffparam_hostname(self):
+ before = self.info['config']['hostname']
+ after = self.params['hostname'] or before
+ return self._diff_update_and_compare('hostname', before, after)
+
+ def diffparam_image(self):
+ before_id = self.info['image']
+ after_id = self.image_info['id']
+ if before_id == after_id:
+ return self._diff_update_and_compare('image', before_id, after_id)
+ before = self.info['config']['image']
+ after = self.params['image']
+ mode = self.params['image_strict']
+ if mode is None or not mode:
+ # In a idempotency 'lite mode' assume all images from different registries are the same
+ before = before.replace(":latest", "")
+ after = after.replace(":latest", "")
+ before = before.split("/")[-1]
+ after = after.split("/")[-1]
+ else:
+ return self._diff_update_and_compare('image', before_id, after_id)
+ return self._diff_update_and_compare('image', before, after)
+
+ def diffparam_ipc(self):
+ before = self.info['hostconfig']['ipcmode']
+ after = self.params['ipc']
+ if self.params['pod'] and not self.module_params['ipc']:
+ after = before
+ return self._diff_update_and_compare('ipc', before, after)
+
+ def diffparam_label(self):
+ before = self.info['config']['labels'] or {}
+ after = self.image_info.get('labels') or {}
+ if self.params['label']:
+ after.update({
+ str(k).lower(): str(v).lower()
+ for k, v in self.params['label'].items()
+ })
+ return self._diff_update_and_compare('label', before, after)
+
+ def diffparam_log_driver(self):
+ before = self.info['hostconfig']['logconfig']['type']
+ after = self.params['log_driver']
+ return self._diff_update_and_compare('log_driver', before, after)
+
+ def diffparam_log_level(self):
+ excom = self.info['exitcommand']
+ if '--log-level' in excom:
+ before = excom[excom.index('--log-level') + 1].lower()
+ else:
+ before = self.params['log_level']
+ after = self.params['log_level']
+ return self._diff_update_and_compare('log_level', before, after)
+
+ # Parameter has limited idempotency, unable to guess the default log_path
+ def diffparam_log_opt(self):
+ before, after = {}, {}
+ # Log path
+ if 'logpath' in self.info:
+ path_before = self.info['logpath']
+ if (self.module_params['log_opt'] and
+ 'path' in self.module_params['log_opt'] and
+ self.module_params['log_opt']['path'] is not None):
+ path_after = self.params['log_opt']['path']
+ else:
+ path_after = path_before
+ if path_before != path_after:
+ before.update({'log-path': path_before})
+ after.update({'log-path': path_after})
+
+ # Log tag
+ if 'logtag' in self.info:
+ tag_before = self.info['logtag']
+ if (self.module_params['log_opt'] and
+ 'tag' in self.module_params['log_opt'] and
+ self.module_params['log_opt']['tag'] is not None):
+ tag_after = self.params['log_opt']['tag']
+ else:
+ tag_after = ''
+ if tag_before != tag_after:
+ before.update({'log-tag': tag_before})
+ after.update({'log-tag': tag_after})
+
+ return self._diff_update_and_compare('log_opt', before, after)
+
+ def diffparam_mac_address(self):
+ before = str(self.info['networksettings']['macaddress'])
+ if self.module_params['mac_address'] is not None:
+ after = self.params['mac_address']
+ else:
+ after = before
+ return self._diff_update_and_compare('mac_address', before, after)
+
+ def diffparam_memory(self):
+ before = str(self.info['hostconfig']['memory'])
+ after = self.params['memory']
+ return self._diff_update_and_compare('memory', before, after)
+
+ def diffparam_memory_swap(self):
+ # By default it's twice memory parameter
+ before = str(self.info['hostconfig']['memoryswap'])
+ after = self.params['memory_swap']
+ if (self.module_params['memory_swap'] is None
+ and self.params['memory'] != 0
+ and self.params['memory'].isdigit()):
+ after = str(int(self.params['memory']) * 2)
+ return self._diff_update_and_compare('memory_swap', before, after)
+
+ def diffparam_memory_reservation(self):
+ before = str(self.info['hostconfig']['memoryreservation'])
+ after = self.params['memory_reservation']
+ return self._diff_update_and_compare('memory_reservation', before, after)
+
+ def diffparam_network(self):
+ net_mode_before = self.info['hostconfig']['networkmode']
+ net_mode_after = ''
+ before = list(self.info['networksettings'].get('networks', {}))
+ after = self.params['network'] or []
+ # If container is in pod and no networks are provided
+ if not self.module_params['network'] and self.params['pod']:
+ after = before
+ return self._diff_update_and_compare('network', before, after)
+ # Check special network modes
+ if after in [['bridge'], ['host'], ['slirp4netns'], ['none']]:
+ net_mode_after = after[0]
+ # If changes are only for network mode and container has no networks
+ if net_mode_after and not before:
+ # Remove differences between v1 and v2
+ net_mode_after = net_mode_after.replace('bridge', 'default')
+ net_mode_after = net_mode_after.replace('slirp4netns', 'default')
+ net_mode_before = net_mode_before.replace('bridge', 'default')
+ net_mode_before = net_mode_before.replace('slirp4netns', 'default')
+ return self._diff_update_and_compare('network', net_mode_before, net_mode_after)
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('network', before, after)
+
+ def diffparam_no_hosts(self):
+ before = not bool(self.info['hostspath'])
+ # For newer verions of Podman
+ if 'resolvconfpath' in self.info:
+ before = not bool(self.info['resolvconfpath'])
+ after = self.params['no_hosts']
+ if self.params['network'] == ['none']:
+ after = True
+ return self._diff_update_and_compare('no_hosts', before, after)
+
+ def diffparam_oom_score_adj(self):
+ before = self.info['hostconfig']['oomscoreadj']
+ after = self.params['oom_score_adj']
+ return self._diff_update_and_compare('oom_score_adj', before, after)
+
+ def diffparam_privileged(self):
+ before = self.info['hostconfig']['privileged']
+ after = self.params['privileged']
+ return self._diff_update_and_compare('privileged', before, after)
+
+ def diffparam_pid(self):
+ before = self.info['hostconfig']['pidmode']
+ after = self.params['pid']
+ return self._diff_update_and_compare('pid', before, after)
+
+ # TODO(sshnaidm) Need to add port ranges support
+ def diffparam_publish(self):
+ ports = self.info['hostconfig']['portbindings']
+ before = [":".join([
+ j[0]['hostip'],
+ str(j[0]["hostport"]),
+ i.replace('/tcp', '')
+ ]).strip(':') for i, j in ports.items()]
+ after = self.params['publish'] or []
+ if self.params['publish_all']:
+ image_ports = self.image_info['config'].get('exposedports', {})
+ if image_ports:
+ after += list(image_ports.keys())
+ after = [i.replace("/tcp", "") for i in after]
+ # No support for port ranges yet
+ for ports in after:
+ if "-" in ports:
+ return self._diff_update_and_compare('publish', '', '')
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('publish', before, after)
+
+ def diffparam_rm(self):
+ before = self.info['hostconfig']['autoremove']
+ after = self.params['rm']
+ return self._diff_update_and_compare('rm', before, after)
+
+ def diffparam_security_opt(self):
+ before = self.info['hostconfig']['securityopt']
+ # In rootful containers with apparmor there is a default security opt
+ before = [o for o in before if 'apparmor=containers-default' not in o]
+ after = self.params['security_opt']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('security_opt', before, after)
+
+ def diffparam_stop_signal(self):
+ signals = {
+ "sighup": "1",
+ "sigint": "2",
+ "sigquit": "3",
+ "sigill": "4",
+ "sigtrap": "5",
+ "sigabrt": "6",
+ "sigiot": "6",
+ "sigbus": "7",
+ "sigfpe": "8",
+ "sigkill": "9",
+ "sigusr1": "10",
+ "sigsegv": "11",
+ "sigusr2": "12",
+ "sigpipe": "13",
+ "sigalrm": "14",
+ "sigterm": "15",
+ "sigstkflt": "16",
+ "sigchld": "17",
+ "sigcont": "18",
+ "sigstop": "19",
+ "sigtstp": "20",
+ "sigttin": "21",
+ "sigttou": "22",
+ "sigurg": "23",
+ "sigxcpu": "24",
+ "sigxfsz": "25",
+ "sigvtalrm": "26",
+ "sigprof": "27",
+ "sigwinch": "28",
+ "sigio": "29",
+ "sigpwr": "30",
+ "sigsys": "31"
+ }
+ before = str(self.info['config']['stopsignal'])
+ if not before.isdigit():
+ before = signals[before.lower()]
+ after = str(self.params['stop_signal'])
+ if not after.isdigit():
+ after = signals[after.lower()]
+ return self._diff_update_and_compare('stop_signal', before, after)
+
+ def diffparam_tty(self):
+ before = self.info['config']['tty']
+ after = self.params['tty']
+ return self._diff_update_and_compare('tty', before, after)
+
+ def diffparam_user(self):
+ before = self.info['config']['user']
+ after = self.params['user']
+ return self._diff_update_and_compare('user', before, after)
+
+ def diffparam_ulimit(self):
+ after = self.params['ulimit'] or []
+ # In case of latest podman
+ if 'createcommand' in self.info['config']:
+ ulimits = []
+ for k, c in enumerate(self.info['config']['createcommand']):
+ if c == '--ulimit':
+ ulimits.append(self.info['config']['createcommand'][k + 1])
+ before = ulimits
+ before, after = sorted(before), sorted(after)
+ return self._diff_update_and_compare('ulimit', before, after)
+ if after:
+ ulimits = self.info['hostconfig']['ulimits']
+ before = {
+ u['name'].replace('rlimit_', ''): "%s:%s" % (u['soft'], u['hard']) for u in ulimits}
+ after = {i.split('=')[0]: i.split('=')[1]
+ for i in self.params['ulimit']}
+ new_before = []
+ new_after = []
+ for u in list(after.keys()):
+ # We don't support unlimited ulimits because it depends on platform
+ if u in before and "-1" not in after[u]:
+ new_before.append([u, before[u]])
+ new_after.append([u, after[u]])
+ return self._diff_update_and_compare('ulimit', new_before, new_after)
+ return self._diff_update_and_compare('ulimit', '', '')
+
+ def diffparam_uts(self):
+ before = self.info['hostconfig']['utsmode']
+ after = self.params['uts']
+ if self.params['pod'] and not self.module_params['uts']:
+ after = before
+ return self._diff_update_and_compare('uts', before, after)
+
+ def diffparam_volume(self):
+ def clean_volume(x):
+ '''Remove trailing and double slashes from volumes.'''
+ return x.replace("//", "/").rstrip("/")
+
+ before = self.info['mounts']
+ before_local_vols = []
+ if before:
+ volumes = []
+ local_vols = []
+ for m in before:
+ if m['type'] != 'volume':
+ volumes.append([m['source'], m['destination']])
+ elif m['type'] == 'volume':
+ local_vols.append([m['name'], m['destination']])
+ before = [":".join(v) for v in volumes]
+ before_local_vols = [":".join(v) for v in local_vols]
+ if self.params['volume'] is not None:
+ after = [":".join(
+ [clean_volume(i) for i in v.split(":")[:2]]
+ ) for v in self.params['volume']]
+ else:
+ after = []
+ if before_local_vols:
+ after = list(set(after).difference(before_local_vols))
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('volume', before, after)
+
+ def diffparam_volumes_from(self):
+ # Possibly volumesfrom is not in config
+ before = self.info['hostconfig'].get('volumesfrom', []) or []
+ after = self.params['volumes_from'] or []
+ return self._diff_update_and_compare('volumes_from', before, after)
+
+ def diffparam_workdir(self):
+ before = self.info['config']['workingdir']
+ after = self.params['workdir']
+ return self._diff_update_and_compare('workdir', before, after)
+
+ def is_different(self):
+ diff_func_list = [func for func in dir(self)
+ if callable(getattr(self, func)) and func.startswith(
+ "diffparam")]
+ fail_fast = not bool(self.module._diff)
+ different = False
+ for func_name in diff_func_list:
+ dff_func = getattr(self, func_name)
+ if dff_func():
+ if fail_fast:
+ return True
+ different = True
+ # Check non idempotent parameters
+ for p in self.non_idempotent:
+ if self.module_params[p] is not None and self.module_params[p] not in [{}, [], '']:
+ different = True
+ return different
+
+
+def ensure_image_exists(module, image, module_params):
+ """If image is passed, ensure it exists, if not - pull it or fail.
+
+ Arguments:
+ module {obj} -- ansible module object
+ image {str} -- name of image
+
+ Returns:
+ list -- list of image actions - if it pulled or nothing was done
+ """
+ image_actions = []
+ module_exec = module_params['executable']
+ if not image:
+ return image_actions
+ rc, out, err = module.run_command([module_exec, 'image', 'exists', image])
+ if rc == 0:
+ return image_actions
+ rc, out, err = module.run_command([module_exec, 'image', 'pull', image])
+ if rc != 0:
+ module.fail_json(msg="Can't pull image %s" % image, stdout=out,
+ stderr=err)
+ image_actions.append("pulled image %s" % image)
+ return image_actions
+
+
+class PodmanContainer:
+ """Perform container tasks.
+
+ Manages podman container, inspects it and checks its current state
+ """
+
+ def __init__(self, module, name, module_params):
+ """Initialize PodmanContainer class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ name {str} -- name of container
+ """
+
+ self.module = module
+ self.module_params = module_params
+ self.name = name
+ self.stdout, self.stderr = '', ''
+ self.info = self.get_info()
+ self.version = self._get_podman_version()
+ self.diff = {}
+ self.actions = []
+
+ @property
+ def exists(self):
+ """Check if container exists."""
+ return bool(self.info != {})
+
+ @property
+ def different(self):
+ """Check if container is different."""
+ diffcheck = PodmanContainerDiff(
+ self.module,
+ self.module_params,
+ self.info,
+ self.get_image_info(),
+ self.version)
+ is_different = diffcheck.is_different()
+ diffs = diffcheck.diff
+ if self.module._diff and is_different and diffs['before'] and diffs['after']:
+ self.diff['before'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['before'].items())]) + "\n"
+ self.diff['after'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['after'].items())]) + "\n"
+ return is_different
+
+ @property
+ def running(self):
+ """Return True if container is running now."""
+ return self.exists and self.info['State']['Running']
+
+ @property
+ def stopped(self):
+ """Return True if container exists and is not running now."""
+ return self.exists and not self.info['State']['Running']
+
+ def get_info(self):
+ """Inspect container and gather info about it."""
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'container', b'inspect', self.name])
+ return json.loads(out)[0] if rc == 0 else {}
+
+ def get_image_info(self):
+ """Inspect container image and gather info about it."""
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'image', b'inspect', self.module_params['image']])
+ return json.loads(out)[0] if rc == 0 else {}
+
+ def _get_podman_version(self):
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'--version'])
+ if rc != 0 or not out or "version" not in out:
+ self.module.fail_json(msg="%s run failed!" %
+ self.module_params['executable'])
+ return out.split("version")[1].strip()
+
+ def _perform_action(self, action):
+ """Perform action with container.
+
+ Arguments:
+ action {str} -- action to perform - start, create, stop, run,
+ delete
+ """
+ b_command = PodmanModuleParams(action,
+ self.module_params,
+ self.version,
+ self.module,
+ ).construct_command_from_params()
+ if action == 'create':
+ b_command.remove(b'--detach=True')
+ full_cmd = " ".join([self.module_params['executable']]
+ + [to_native(i) for i in b_command])
+ self.actions.append(full_cmd)
+ if self.module.check_mode:
+ self.module.log(
+ "PODMAN-CONTAINER-DEBUG (check_mode): %s" % full_cmd)
+ else:
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'container'] + b_command,
+ expand_user_and_vars=False)
+ self.module.log("PODMAN-CONTAINER-DEBUG: %s" % full_cmd)
+ if self.module_params['debug']:
+ self.module.log("PODMAN-CONTAINER-DEBUG STDOUT: %s" % out)
+ self.module.log("PODMAN-CONTAINER-DEBUG STDERR: %s" % err)
+ self.module.log("PODMAN-CONTAINER-DEBUG RC: %s" % rc)
+ self.stdout = out
+ self.stderr = err
+ if rc != 0:
+ self.module.fail_json(
+ msg="Can't %s container %s" % (action, self.name),
+ stdout=out, stderr=err)
+
+ def run(self):
+ """Run the container."""
+ self._perform_action('run')
+
+ def delete(self):
+ """Delete the container."""
+ self._perform_action('delete')
+
+ def stop(self):
+ """Stop the container."""
+ self._perform_action('stop')
+
+ def start(self):
+ """Start the container."""
+ self._perform_action('start')
+
+ def create(self):
+ """Create the container."""
+ self._perform_action('create')
+
+ def recreate(self):
+ """Recreate the container."""
+ self.delete()
+ self.run()
+
+ def restart(self):
+ """Restart the container."""
+ self.stop()
+ self.start()
+
+
+class PodmanManager:
+ """Module manager class.
+
+ Defines according to parameters what actions should be applied to container
+ """
+
+ def __init__(self, module, params):
+ """Initialize PodmanManager class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ """
+
+ self.module = module
+ self.results = {
+ 'changed': False,
+ 'actions': [],
+ 'container': {},
+ }
+ self.module_params = params
+ self.name = self.module_params['name']
+ self.executable = \
+ self.module.get_bin_path(self.module_params['executable'],
+ required=True)
+ self.image = self.module_params['image']
+ image_actions = ensure_image_exists(
+ self.module, self.image, self.module_params)
+ self.results['actions'] += image_actions
+ self.state = self.module_params['state']
+ self.restart = self.module_params['force_restart']
+ self.recreate = self.module_params['recreate']
+ self.container = PodmanContainer(
+ self.module, self.name, self.module_params)
+
+ def update_container_result(self, changed=True):
+ """Inspect the current container, update results with last info, exit.
+
+ Keyword Arguments:
+ changed {bool} -- whether any action was performed
+ (default: {True})
+ """
+ facts = self.container.get_info() if changed else self.container.info
+ out, err = self.container.stdout, self.container.stderr
+ self.results.update({'changed': changed, 'container': facts,
+ 'podman_actions': self.container.actions},
+ stdout=out, stderr=err)
+ if self.container.diff:
+ self.results.update({'diff': self.container.diff})
+ if self.module.params['debug'] or self.module_params['debug']:
+ self.results.update({'podman_version': self.container.version})
+
+ def make_started(self):
+ """Run actions if desired state is 'started'."""
+ if self.container.running and \
+ (self.container.different or self.recreate):
+ self.container.recreate()
+ self.results['actions'].append('recreated %s' %
+ self.container.name)
+ self.update_container_result()
+ return
+ elif self.container.running and not self.container.different:
+ if self.restart:
+ self.container.restart()
+ self.results['actions'].append('restarted %s' %
+ self.container.name)
+ self.update_container_result()
+ return
+ self.update_container_result(changed=False)
+ return
+ elif not self.container.exists:
+ self.container.run()
+ self.results['actions'].append('started %s' % self.container.name)
+ self.update_container_result()
+ return
+ elif self.container.stopped and self.container.different:
+ self.container.recreate()
+ self.results['actions'].append('recreated %s' %
+ self.container.name)
+ self.update_container_result()
+ return
+ elif self.container.stopped and not self.container.different:
+ self.container.start()
+ self.results['actions'].append('started %s' % self.container.name)
+ self.update_container_result()
+ return
+
+ def make_stopped(self):
+ """Run actions if desired state is 'stopped'."""
+ if not self.container.exists and not self.image:
+ self.module.fail_json(msg='Cannot create container when image'
+ ' is not specified!')
+ if not self.container.exists:
+ self.container.create()
+ self.results['actions'].append('created %s' % self.container.name)
+ self.update_container_result()
+ return
+ if self.container.stopped:
+ self.update_container_result(changed=False)
+ return
+ elif self.container.running:
+ self.container.stop()
+ self.results['actions'].append('stopped %s' % self.container.name)
+ self.update_container_result()
+ return
+
+ def make_absent(self):
+ """Run actions if desired state is 'absent'."""
+ if not self.container.exists:
+ self.results.update({'changed': False})
+ elif self.container.exists:
+ self.container.delete()
+ self.results['actions'].append('deleted %s' % self.container.name)
+ self.results.update({'changed': True})
+ self.results.update({'container': {},
+ 'podman_actions': self.container.actions})
+
+ def execute(self):
+ """Execute the desired action according to map of actions & states."""
+ states_map = {
+ 'present': self.make_started,
+ 'started': self.make_started,
+ 'absent': self.make_absent,
+ 'stopped': self.make_stopped
+ }
+ process_action = states_map[self.state]
+ process_action()
+ return self.results
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py
new file mode 100644
index 00000000..c3f0e4e3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py
@@ -0,0 +1,736 @@
+from __future__ import (absolute_import, division, print_function)
+import json
+from distutils.version import LooseVersion
+
+from ansible.module_utils._text import to_bytes, to_native
+
+from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
+
+__metaclass__ = type
+
+ARGUMENTS_SPEC_POD = dict(
+ state=dict(
+ type='str',
+ default="created",
+ choices=[
+ 'created',
+ 'killed',
+ 'restarted',
+ 'absent',
+ 'started',
+ 'stopped',
+ 'paused',
+ 'unpaused',
+ ]),
+ recreate=dict(type='bool', default=False),
+ add_host=dict(type='list', required=False, elements='str'),
+ cgroup_parent=dict(type='str', required=False),
+ dns=dict(type='list', elements='str', required=False),
+ dns_opt=dict(type='list', elements='str', required=False),
+ dns_search=dict(type='list', elements='str', required=False),
+ hostname=dict(type='str', required=False),
+ infra=dict(type='bool', required=False),
+ infra_conmon_pidfile=dict(type='str', required=False),
+ infra_command=dict(type='str', required=False),
+ infra_image=dict(type='str', required=False),
+ ip=dict(type='str', required=False),
+ label=dict(type='dict', required=False),
+ label_file=dict(type='str', required=False),
+ mac_address=dict(type='str', required=False),
+ name=dict(type='str', required=True),
+ network=dict(type='str', required=False),
+ no_hosts=dict(type='bool', required=False),
+ pod_id_file=dict(type='str', required=False),
+ publish=dict(type='list', required=False,
+ elements='str', aliases=['ports']),
+ share=dict(type='str', required=False),
+ executable=dict(type='str', required=False, default='podman'),
+ debug=dict(type='bool', default=False),
+)
+
+
+class PodmanPodModuleParams:
+ """Creates list of arguments for podman CLI command.
+
+ Arguments:
+ action {str} -- action type from 'run', 'stop', 'create', 'delete',
+ 'start'
+ params {dict} -- dictionary of module parameters
+
+ """
+
+ def __init__(self, action, params, podman_version, module):
+ self.params = params
+ self.action = action
+ self.podman_version = podman_version
+ self.module = module
+
+ def construct_command_from_params(self):
+ """Create a podman command from given module parameters.
+
+ Returns:
+ list -- list of byte strings for Popen command
+ """
+ if self.action in ['start', 'restart', 'stop', 'delete', 'pause',
+ 'unpause', 'kill']:
+ return self._simple_action()
+ if self.action in ['create']:
+ return self._create_action()
+ self.module.fail_json(msg="Unknown action %s" % self.action)
+
+ def _simple_action(self):
+ if self.action in ['start', 'restart', 'stop', 'pause', 'unpause', 'kill']:
+ cmd = [self.action, self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ if self.action == 'delete':
+ cmd = ['rm', '-f', self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+ self.module.fail_json(msg="Unknown action %s" % self.action)
+
+ def _create_action(self):
+ cmd = [self.action]
+ all_param_methods = [func for func in dir(self)
+ if callable(getattr(self, func))
+ and func.startswith("addparam")]
+ params_set = (i for i in self.params if self.params[i] is not None)
+ for param in params_set:
+ func_name = "_".join(["addparam", param])
+ if func_name in all_param_methods:
+ cmd = getattr(self, func_name)(cmd)
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def check_version(self, param, minv=None, maxv=None):
+ if minv and LooseVersion(minv) > LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported from podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+ if maxv and LooseVersion(maxv) < LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported till podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+
+ def addparam_add_host(self, c):
+ for g in self.params['add_host']:
+ c += ['--add-host', g]
+ return c
+
+ def addparam_cgroup_parent(self, c):
+ return c + ['--cgroup-parent', self.params['cgroup_parent']]
+
+ def addparam_dns(self, c):
+ for g in self.params['dns']:
+ c += ['--dns', g]
+ return c
+
+ def addparam_dns_opt(self, c):
+ for g in self.params['dns_opt']:
+ c += ['--dns-opt', g]
+ return c
+
+ def addparam_dns_search(self, c):
+ for g in self.params['dns_search']:
+ c += ['--dns-search', g]
+ return c
+
+ def addparam_hostname(self, c):
+ return c + ['--hostname', self.params['hostname']]
+
+ def addparam_infra(self, c):
+ return c + [b'='.join([b'--infra',
+ to_bytes(self.params['infra'],
+ errors='surrogate_or_strict')])]
+
+ def addparam_infra_conmon_pidfile(self, c):
+ return c + ['--infra-conmon-pidfile', self.params['infra_conmon_pidfile']]
+
+ def addparam_infra_command(self, c):
+ return c + ['--infra-command', self.params['infra_command']]
+
+ def addparam_infra_image(self, c):
+ return c + ['--infra-image', self.params['infra_image']]
+
+ def addparam_ip(self, c):
+ return c + ['--ip', self.params['ip']]
+
+ def addparam_label(self, c):
+ for label in self.params['label'].items():
+ c += ['--label', b'='.join(
+ [to_bytes(l, errors='surrogate_or_strict') for l in label])]
+ return c
+
+ def addparam_label_file(self, c):
+ return c + ['--label-file', self.params['label_file']]
+
+ def addparam_mac_address(self, c):
+ return c + ['--mac-address', self.params['mac_address']]
+
+ def addparam_name(self, c):
+ return c + ['--name', self.params['name']]
+
+ def addparam_network(self, c):
+ return c + ['--network', self.params['network']]
+
+ def addparam_no_hosts(self, c):
+ return c + ["=".join('--no-hosts', self.params['no_hosts'])]
+
+ def addparam_pod_id_file(self, c):
+ return c + ['--pod-id-file', self.params['pod_id_file']]
+
+ def addparam_publish(self, c):
+ for g in self.params['publish']:
+ c += ['--publish', g]
+ return c
+
+ def addparam_share(self, c):
+ return c + ['--share', self.params['share']]
+
+
+class PodmanPodDefaults:
+ def __init__(self, module, podman_version):
+ self.module = module
+ self.version = podman_version
+ self.defaults = {
+ 'add_host': [],
+ 'dns': [],
+ 'dns_opt': [],
+ 'dns_search': [],
+ 'infra': True,
+ 'label': {},
+ }
+
+ def default_dict(self):
+ # make here any changes to self.defaults related to podman version
+ # https://github.com/containers/libpod/pull/5669
+ # if (LooseVersion(self.version) >= LooseVersion('1.8.0')
+ # and LooseVersion(self.version) < LooseVersion('1.9.0')):
+ # self.defaults['cpu_shares'] = 1024
+ return self.defaults
+
+
+class PodmanPodDiff:
+ def __init__(self, module, module_params, info, infra_info, podman_version):
+ self.module = module
+ self.module_params = module_params
+ self.version = podman_version
+ self.default_dict = None
+ self.info = lower_keys(info)
+ self.infra_info = lower_keys(infra_info)
+ self.params = self.defaultize()
+ self.diff = {'before': {}, 'after': {}}
+ self.non_idempotent = {}
+
+ def defaultize(self):
+ params_with_defaults = {}
+ self.default_dict = PodmanPodDefaults(
+ self.module, self.version).default_dict()
+ for p in self.module_params:
+ if self.module_params[p] is None and p in self.default_dict:
+ params_with_defaults[p] = self.default_dict[p]
+ else:
+ params_with_defaults[p] = self.module_params[p]
+ return params_with_defaults
+
+ def _diff_update_and_compare(self, param_name, before, after):
+ if before != after:
+ self.diff['before'].update({param_name: before})
+ self.diff['after'].update({param_name: after})
+ return True
+ return False
+
+ def diffparam_add_host(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('add_host', '', '')
+ before = self.infra_info['hostconfig']['extrahosts'] or []
+ after = self.params['add_host']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('add_host', before, after)
+
+ def diffparam_cgroup_parent(self):
+ if 'cgroupparent' in self.info:
+ before = self.info['cgroupparent']
+ elif 'config' in self.info and self.info['config'].get('cgroupparent'):
+ before = self.info['config']['cgroupparent']
+ after = self.params['cgroup_parent'] or before
+ return self._diff_update_and_compare('cgroup_parent', before, after)
+
+ def diffparam_dns(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('dns', '', '')
+ before = self.infra_info['hostconfig']['dns'] or []
+ after = self.params['dns']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('dns', before, after)
+
+ def diffparam_dns_opt(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('dns_opt', '', '')
+ before = self.infra_info['hostconfig']['dnsoptions'] or []
+ after = self.params['dns_opt']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('dns_opt', before, after)
+
+ def diffparam_dns_search(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('dns_search', '', '')
+ before = self.infra_info['hostconfig']['dnssearch'] or []
+ after = self.params['dns_search']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('dns_search', before, after)
+
+ def diffparam_hostname(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('hostname', '', '')
+ before = self.infra_info['config']['hostname']
+ after = self.params['hostname'] or before
+ return self._diff_update_and_compare('hostname', before, after)
+
+ # TODO(sshnaidm): https://github.com/containers/podman/issues/6968
+ def diffparam_infra(self):
+ if 'state' in self.info and 'infracontainerid' in self.info['state']:
+ before = self.info['state']['infracontainerid'] != ""
+ else:
+ # TODO(sshnaidm): https://github.com/containers/podman/issues/6968
+ before = 'infracontainerid' in self.info
+ after = self.params['infra']
+ return self._diff_update_and_compare('infra', before, after)
+
+ # TODO(sshnaidm): https://github.com/containers/podman/issues/6969
+ # def diffparam_infra_command(self):
+ # before = str(self.info['hostconfig']['infra_command'])
+ # after = self.params['infra_command']
+ # return self._diff_update_and_compare('infra_command', before, after)
+
+ def diffparam_infra_image(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('infra_image', '', '')
+ before = str(self.infra_info['imagename'])
+ after = before
+ if self.module_params['infra_image']:
+ after = self.params['infra_image']
+ before = before.replace(":latest", "")
+ after = after.replace(":latest", "")
+ before = before.split("/")[-1]
+ after = after.split("/")[-1]
+ return self._diff_update_and_compare('infra_image', before, after)
+
+ # TODO(sshnaidm): https://github.com/containers/podman/pull/6956
+ # def diffparam_ip(self):
+ # before = str(self.info['hostconfig']['ip'])
+ # after = self.params['ip']
+ # return self._diff_update_and_compare('ip', before, after)
+
+ def diffparam_label(self):
+ if 'config' in self.info and 'labels' in self.info['config']:
+ before = self.info['config'].get('labels') or {}
+ else:
+ before = self.info['labels'] if 'labels' in self.info else {}
+ after = self.params['label']
+ return self._diff_update_and_compare('label', before, after)
+
+ # TODO(sshnaidm): https://github.com/containers/podman/pull/6956
+ # def diffparam_mac_address(self):
+ # before = str(self.info['hostconfig']['mac_address'])
+ # after = self.params['mac_address']
+ # return self._diff_update_and_compare('mac_address', before, after)
+
+ def diffparam_network(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('network', [], [])
+ net_mode_before = self.infra_info['hostconfig']['networkmode']
+ net_mode_after = ''
+ before = self.infra_info['networksettings'].get('networks', [])
+ after = self.params['network']
+ # Currently supported only 'host' and 'none' network modes idempotency
+ if after in ['bridge', 'host', 'slirp4netns']:
+ net_mode_after = after
+ elif after:
+ after = after.split(",")
+ else:
+ after = []
+ if net_mode_after and not before:
+ # Remove differences between v1 and v2
+ net_mode_after = net_mode_after.replace('bridge', 'default')
+ net_mode_after = net_mode_after.replace('slirp4netns', 'default')
+ net_mode_before = net_mode_before.replace('bridge', 'default')
+ net_mode_before = net_mode_before.replace('slirp4netns', 'default')
+ return self._diff_update_and_compare('network', net_mode_before, net_mode_after)
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('network', before, after)
+
+ # TODO(sshnaidm)
+ # def diffparam_no_hosts(self):
+ # before = str(self.info['hostconfig']['no_hosts'])
+ # after = self.params['no_hosts']
+ # return self._diff_update_and_compare('no_hosts', before, after)
+
+ # TODO(sshnaidm) Need to add port ranges support
+ def diffparam_publish(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('publish', '', '')
+ ports = self.infra_info['hostconfig']['portbindings']
+ before = [":".join([
+ j[0]['hostip'],
+ str(j[0]["hostport"]),
+ i.replace('/tcp', '')
+ ]).strip(':') for i, j in ports.items()]
+ after = self.params['publish'] or []
+ after = [i.replace("/tcp", "") for i in after]
+ # No support for port ranges yet
+ for ports in after:
+ if "-" in ports:
+ return self._diff_update_and_compare('publish', '', '')
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('publish', before, after)
+
+ def diffparam_share(self):
+ if not self.infra_info:
+ return self._diff_update_and_compare('share', '', '')
+ if 'sharednamespaces' in self.info:
+ before = self.info['sharednamespaces']
+ elif 'config' in self.info:
+ before = [
+ i.split('shares')[1].lower()
+ for i in self.info['config'] if 'shares' in i]
+ # TODO(sshnaidm): to discover why in podman v1 'cgroup' appears
+ before.remove('cgroup')
+ else:
+ before = []
+ if self.params['share'] is not None:
+ after = self.params['share'].split(",")
+ else:
+ after = ['uts', 'ipc', 'net']
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('share', before, after)
+
+ def is_different(self):
+ diff_func_list = [func for func in dir(self)
+ if callable(getattr(self, func)) and func.startswith(
+ "diffparam")]
+ fail_fast = not bool(self.module._diff)
+ different = False
+ for func_name in diff_func_list:
+ dff_func = getattr(self, func_name)
+ if dff_func():
+ if fail_fast:
+ return True
+ different = True
+ # Check non idempotent parameters
+ for p in self.non_idempotent:
+ if self.module_params[p] is not None and self.module_params[p] not in [{}, [], '']:
+ different = True
+ return different
+
+
+class PodmanPod:
+ """Perform pod tasks.
+
+ Manages podman pod, inspects it and checks its current state
+ """
+
+ def __init__(self, module, name, module_params):
+ """Initialize PodmanPod class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ name {str} -- name of pod
+ """
+
+ self.module = module
+ self.module_params = module_params
+ self.name = name
+ self.stdout, self.stderr = '', ''
+ self.info = self.get_info()
+ self.infra_info = self.get_infra_info()
+ self.version = self._get_podman_version()
+ self.diff = {}
+ self.actions = []
+
+ @property
+ def exists(self):
+ """Check if pod exists."""
+ return bool(self.info != {})
+
+ @property
+ def different(self):
+ """Check if pod is different."""
+ diffcheck = PodmanPodDiff(
+ self.module,
+ self.module_params,
+ self.info,
+ self.infra_info,
+ self.version)
+ is_different = diffcheck.is_different()
+ diffs = diffcheck.diff
+ if self.module._diff and is_different and diffs['before'] and diffs['after']:
+ self.diff['before'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['before'].items())]) + "\n"
+ self.diff['after'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['after'].items())]) + "\n"
+ return is_different
+
+ @property
+ def running(self):
+ """Return True if pod is running now."""
+ if 'status' in self.info['State']:
+ return self.info['State']['status'] == 'Running'
+ return self.info['State'] == 'Running'
+
+ @property
+ def paused(self):
+ """Return True if pod is paused now."""
+ if 'status' in self.info['State']:
+ return self.info['State']['status'] == 'Paused'
+ return self.info['State'] == 'Paused'
+
+ @property
+ def stopped(self):
+ """Return True if pod exists and is not running now."""
+ if not self.exists:
+ return False
+ if 'status' in self.info['State']:
+ return not (self.info['State']['status'] == 'Running')
+ return not (self.info['State'] == 'Running')
+
+ def get_info(self):
+ """Inspect pod and gather info about it."""
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'pod', b'inspect', self.name])
+ return json.loads(out) if rc == 0 else {}
+
+ def get_infra_info(self):
+ """Inspect pod and gather info about it."""
+ if not self.info:
+ return {}
+ if 'InfraContainerID' in self.info:
+ infra_container_id = self.info['InfraContainerID']
+ elif 'State' in self.info and 'infraContainerID' in self.info['State']:
+ infra_container_id = self.info['State']['infraContainerID']
+ else:
+ return {}
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'inspect', infra_container_id])
+ return json.loads(out)[0] if rc == 0 else {}
+
+ def _get_podman_version(self):
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'--version'])
+ if rc != 0 or not out or "version" not in out:
+ self.module.fail_json(msg="%s run failed!" % self.module_params['executable'])
+ return out.split("version")[1].strip()
+
+ def _perform_action(self, action):
+ """Perform action with pod.
+
+ Arguments:
+ action {str} -- action to perform - start, create, stop, pause
+ unpause, delete, restart, kill
+ """
+ b_command = PodmanPodModuleParams(action,
+ self.module_params,
+ self.version,
+ self.module,
+ ).construct_command_from_params()
+ full_cmd = " ".join([self.module_params['executable'], 'pod']
+ + [to_native(i) for i in b_command])
+ self.module.log("PODMAN-POD-DEBUG: %s" % full_cmd)
+ self.actions.append(full_cmd)
+ if not self.module.check_mode:
+ rc, out, err = self.module.run_command(
+ [self.module_params['executable'], b'pod'] + b_command,
+ expand_user_and_vars=False)
+ self.stdout = out
+ self.stderr = err
+ if rc != 0:
+ self.module.fail_json(
+ msg="Can't %s pod %s" % (action, self.name),
+ stdout=out, stderr=err)
+
+ def delete(self):
+ """Delete the pod."""
+ self._perform_action('delete')
+
+ def stop(self):
+ """Stop the pod."""
+ self._perform_action('stop')
+
+ def start(self):
+ """Start the pod."""
+ self._perform_action('start')
+
+ def create(self):
+ """Create the pod."""
+ self._perform_action('create')
+
+ def recreate(self):
+ """Recreate the pod."""
+ self.delete()
+ self.create()
+
+ def restart(self):
+ """Restart the pod."""
+ self._perform_action('restart')
+
+ def kill(self):
+ """Kill the pod."""
+ self._perform_action('kill')
+
+ def pause(self):
+ """Pause the pod."""
+ self._perform_action('pause')
+
+ def unpause(self):
+ """Unpause the pod."""
+ self._perform_action('unpause')
+
+
+class PodmanPodManager:
+ """Module manager class.
+
+ Defines according to parameters what actions should be applied to pod
+ """
+
+ def __init__(self, module, params):
+ """Initialize PodmanManager class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ """
+
+ self.module = module
+ self.module_params = params
+ self.results = {
+ 'changed': False,
+ 'actions': [],
+ 'pod': {},
+ }
+ self.name = self.module_params['name']
+ self.executable = \
+ self.module.get_bin_path(self.module_params['executable'],
+ required=True)
+ self.state = self.module_params['state']
+ self.recreate = self.module_params['recreate']
+ self.pod = PodmanPod(self.module, self.name, self.module_params)
+
+ def update_pod_result(self, changed=True):
+ """Inspect the current pod, update results with last info, exit.
+
+ Keyword Arguments:
+ changed {bool} -- whether any action was performed
+ (default: {True})
+ """
+ facts = self.pod.get_info() if changed else self.pod.info
+ out, err = self.pod.stdout, self.pod.stderr
+ self.results.update({'changed': changed, 'pod': facts,
+ 'podman_actions': self.pod.actions},
+ stdout=out, stderr=err)
+ if self.pod.diff:
+ self.results.update({'diff': self.pod.diff})
+ if self.module.params['debug'] or self.module_params['debug']:
+ self.results.update({'podman_version': self.pod.version})
+
+ def execute(self):
+ """Execute the desired action according to map of actions & states."""
+ states_map = {
+ 'created': self.make_created,
+ 'started': self.make_started,
+ 'stopped': self.make_stopped,
+ 'absent': self.make_absent,
+ 'killed': self.make_killed,
+ 'paused': self.make_paused,
+ 'unpaused': self.make_unpaused,
+
+ }
+ process_action = states_map[self.state]
+ process_action()
+ return self.results
+
+ def _create_or_recreate_pod(self):
+ """Ensure pod exists and is exactly as it should be by input params."""
+ changed = False
+ if self.pod.exists:
+ if self.pod.different or self.recreate:
+ self.pod.recreate()
+ self.results['actions'].append('recreated %s' % self.pod.name)
+ changed = True
+ elif not self.pod.exists:
+ self.pod.create()
+ self.results['actions'].append('created %s' % self.pod.name)
+ changed = True
+ return changed
+
+ def make_created(self):
+ """Run actions if desired state is 'created'."""
+ if self.pod.exists and not self.pod.different:
+ self.update_pod_result(changed=False)
+ return
+ self._create_or_recreate_pod()
+ self.update_pod_result()
+
+ def make_killed(self):
+ """Run actions if desired state is 'killed'."""
+ self._create_or_recreate_pod()
+ self.pod.kill()
+ self.results['actions'].append('killed %s' % self.pod.name)
+ self.update_pod_result()
+
+ def make_paused(self):
+ """Run actions if desired state is 'paused'."""
+ changed = self._create_or_recreate_pod()
+ if self.pod.paused:
+ self.update_pod_result(changed=changed)
+ return
+ self.pod.pause()
+ self.results['actions'].append('paused %s' % self.pod.name)
+ self.update_pod_result()
+
+ def make_unpaused(self):
+ """Run actions if desired state is 'unpaused'."""
+ changed = self._create_or_recreate_pod()
+ if not self.pod.paused:
+ self.update_pod_result(changed=changed)
+ return
+ self.pod.unpause()
+ self.results['actions'].append('unpaused %s' % self.pod.name)
+ self.update_pod_result()
+
+ def make_started(self):
+ """Run actions if desired state is 'started'."""
+ changed = self._create_or_recreate_pod()
+ if not changed and self.pod.running:
+ self.update_pod_result(changed=changed)
+ return
+
+ # self.pod.unpause() TODO(sshnaidm): to unpause if state == started?
+ self.pod.start()
+ self.results['actions'].append('started %s' % self.pod.name)
+ self.update_pod_result()
+
+ def make_stopped(self):
+ """Run actions if desired state is 'stopped'."""
+ changed = self._create_or_recreate_pod()
+ if changed or self.pod.stopped:
+ self.update_pod_result(changed=changed)
+ return
+ elif self.pod.running:
+ self.pod.stop()
+ self.results['actions'].append('stopped %s' % self.pod.name)
+ self.update_pod_result()
+
+ def make_absent(self):
+ """Run actions if desired state is 'absent'."""
+ if not self.pod.exists:
+ self.results.update({'changed': False})
+ elif self.pod.exists:
+ self.pod.delete()
+ self.results['actions'].append('deleted %s' % self.pod.name)
+ self.results.update({'changed': True})
+ self.results.update({'pod': {},
+ 'podman_actions': self.pod.actions})
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/__init__.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/__init__.py
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container.py
new file mode 100644
index 00000000..99b14a39
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container.py
@@ -0,0 +1,916 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# flake8: noqa: E501
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = r"""
+module: podman_container
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.0.0'
+short_description: Manage podman containers
+notes: []
+description:
+ - Start, stop, restart and manage Podman containers
+requirements:
+ - podman
+options:
+ name:
+ description:
+ - Name of the container
+ required: True
+ type: str
+ 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
+ state:
+ description:
+ - I(absent) - A container matching the specified name will be stopped and
+ removed.
+ - I(present) - Asserts the existence of a container matching the name and
+ any provided configuration parameters. If no container matches the
+ name, a container will be created. If a container matches the name but
+ the provided configuration does not match, the container will be
+ updated, if it can be. If it cannot be updated, it will be removed and
+ re-created with the requested config. Image version will be taken into
+ account when comparing configuration. Use the recreate option to force
+ the re-creation of the matching container.
+ - I(started) - Asserts there is a running container matching the name and
+ any provided configuration. If no container matches the name, a
+ container will be created and started. Use recreate to always re-create
+ a matching container, even if it is running. Use force_restart to force
+ a matching container to be stopped and restarted.
+ - I(stopped) - Asserts that the container is first I(present), and then
+ if the container is running moves it to a stopped state.
+ type: str
+ default: started
+ choices:
+ - absent
+ - present
+ - stopped
+ - started
+ image:
+ description:
+ - Repository path (or image name) and tag used to create the container.
+ If an image is not found, the image will be pulled from the registry.
+ If no tag is included, C(latest) will be used.
+ - Can also be an image ID. If this is the case, the image is assumed to
+ be available locally.
+ type: str
+ annotation:
+ description:
+ - Add an annotation to the container. The format is key value, multiple
+ times.
+ type: dict
+ 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
+ blkio_weight:
+ description:
+ - Block IO weight (relative weight) accepts a weight value between 10 and
+ 1000
+ type: int
+ blkio_weight_device:
+ description:
+ - Block IO weight (relative device weight, format DEVICE_NAME[:]WEIGHT).
+ type: dict
+ cap_add:
+ description:
+ - List of capabilities to add to the container.
+ type: list
+ elements: str
+ aliases:
+ - capabilities
+ cap_drop:
+ description:
+ - List of capabilities to drop from the container.
+ type: list
+ elements: str
+ cgroup_parent:
+ description:
+ - Path to cgroups under which the cgroup for the container will be
+ created.
+ If the path is not absolute, the path is considered to be relative to
+ the cgroups path of the init process. Cgroups will be created if they
+ do not already exist.
+ type: path
+ cgroupns:
+ description:
+ - Path to cgroups under which the cgroup for the container will be
+ created.
+ type: str
+ cgroups:
+ description:
+ - Determines whether the container will create CGroups.
+ Valid values are enabled and disabled, which the default being enabled.
+ The disabled option will force the container to not create CGroups,
+ and thus conflicts with CGroup options cgroupns and cgroup-parent.
+ type: str
+ choices:
+ - default
+ - disabled
+ cidfile:
+ description:
+ - Write the container ID to the file
+ type: path
+ cmd_args:
+ description:
+ - Any additional command options you want to pass to podman command,
+ cmd_args - ['--other-param', 'value']
+ Be aware module doesn't support idempotency if this is set.
+ type: list
+ elements: str
+ conmon_pidfile:
+ description:
+ - Write the pid of the conmon process to a file.
+ conmon runs in a separate process than Podman,
+ so this is necessary when using systemd to restart Podman containers.
+ type: path
+ command:
+ description:
+ - Override command of container. Can be a string or a list.
+ type: raw
+ cpu_period:
+ description:
+ - Limit the CPU real-time period in microseconds
+ type: int
+ cpu_rt_period:
+ description:
+ - Limit the CPU real-time period in microseconds.
+ Limit the container's Real Time CPU usage. This flag tell the kernel to
+ restrict the container's Real Time CPU usage to the period you specify.
+ type: int
+ cpu_rt_runtime:
+ description:
+ - Limit the CPU real-time runtime in microseconds.
+ This flag tells the kernel to limit the amount of time in a given CPU
+ period Real Time tasks may consume.
+ type: int
+ cpu_shares:
+ description:
+ - CPU shares (relative weight)
+ type: int
+ cpus:
+ description:
+ - Number of CPUs. The default is 0.0 which means no limit.
+ type: str
+ cpuset_cpus:
+ description:
+ - CPUs in which to allow execution (0-3, 0,1)
+ type: str
+ cpuset_mems:
+ description:
+ - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only
+ effective on NUMA systems.
+ type: str
+ detach:
+ description:
+ - Run container in detach mode
+ type: bool
+ default: True
+ debug:
+ description:
+ - Return additional information which can be helpful for investigations.
+ type: bool
+ default: False
+ detach_keys:
+ description:
+ - Override the key sequence for detaching a container. Format is a single
+ character or ctrl-value
+ type: str
+ device:
+ description:
+ - Add a host device to the container.
+ The format is <device-on-host>[:<device-on-container>][:<permissions>]
+ (e.g. device /dev/sdc:/dev/xvdc:rwm)
+ type: list
+ elements: str
+ device_read_bps:
+ description:
+ - Limit read rate (bytes per second) from a device
+ (e.g. device-read-bps /dev/sda:1mb)
+ type: list
+ device_read_iops:
+ description:
+ - Limit read rate (IO per second) from a device
+ (e.g. device-read-iops /dev/sda:1000)
+ type: list
+ device_write_bps:
+ description:
+ - Limit write rate (bytes per second) to a device
+ (e.g. device-write-bps /dev/sda:1mb)
+ type: list
+ device_write_iops:
+ description:
+ - Limit write rate (IO per second) to a device
+ (e.g. device-write-iops /dev/sda:1000)
+ type: list
+ dns:
+ description:
+ - Set custom DNS servers
+ type: list
+ elements: str
+ aliases:
+ - dns_servers
+ dns_option:
+ description:
+ - Set custom DNS options
+ type: str
+ aliases:
+ - dns_opts
+ dns_search:
+ description:
+ - Set custom DNS search domains (Use dns_search with '' if you don't wish
+ to set the search domain)
+ type: str
+ aliases:
+ - dns_search_domains
+ entrypoint:
+ description:
+ - Overwrite the default ENTRYPOINT of the image
+ type: str
+ env:
+ description:
+ - Set environment variables.
+ This option allows you to specify arbitrary environment variables that
+ are available for the process that will be launched inside of the
+ container.
+ type: dict
+ env_file:
+ description:
+ - Read in a line delimited file of environment variables
+ type: path
+ env_host:
+ description:
+ - Use all current host environment variables in container.
+ Defaults to false.
+ type: bool
+ etc_hosts:
+ description:
+ - Dict of host-to-IP mappings, where each host name is a key in the
+ dictionary. Each host name will be added to the container's
+ ``/etc/hosts`` file.
+ type: dict
+ aliases:
+ - add_hosts
+ expose:
+ description:
+ - Expose a port, or a range of ports (e.g. expose "3300-3310") to set up
+ port redirection on the host system.
+ type: list
+ elements: str
+ aliases:
+ - exposed
+ - exposed_ports
+ force_restart:
+ description:
+ - Force restart of container.
+ type: bool
+ default: False
+ aliases:
+ - restart
+ gidmap:
+ description:
+ - Run the container in a new user namespace using the supplied mapping.
+ type: list
+ elements: str
+ group_add:
+ description:
+ - Add additional groups to run as
+ type: list
+ aliases:
+ - groups
+ healthcheck:
+ description:
+ - Set or alter a healthcheck command for a container.
+ type: str
+ healthcheck_interval:
+ description:
+ - Set an interval for the healthchecks
+ (a value of disable results in no automatic timer setup)
+ (default "30s")
+ type: str
+ healthcheck_retries:
+ description:
+ - The number of retries allowed before a healthcheck is considered to be
+ unhealthy. The default value is 3.
+ type: int
+ healthcheck_start_period:
+ description:
+ - The initialization time needed for a container to bootstrap.
+ The value can be expressed in time format like 2m3s. The default value
+ is 0s
+ type: str
+ healthcheck_timeout:
+ description:
+ - The maximum time allowed to complete the healthcheck before an interval
+ is considered failed. Like start-period, the value can be expressed in
+ a time format such as 1m22s. The default value is 30s
+ type: str
+ hostname:
+ description:
+ - Container host name. Sets the container host name that is available
+ inside the container.
+ type: str
+ http_proxy:
+ description:
+ - By default proxy environment variables are passed into the container if
+ set for the podman process. This can be disabled by setting the
+ http_proxy option to false. The environment variables passed in
+ include http_proxy, https_proxy, ftp_proxy, no_proxy, and also the
+ upper case versions of those.
+ Defaults to true
+ type: bool
+ image_volume:
+ description:
+ - Tells podman how to handle the builtin image volumes.
+ The options are bind, tmpfs, or ignore (default bind)
+ type: str
+ choices:
+ - 'bind'
+ - 'tmpfs'
+ - 'ignore'
+ image_strict:
+ description:
+ - Whether to compare images in idempotency by taking into account a full
+ name with registry and namespaces.
+ type: bool
+ default: False
+ init:
+ description:
+ - Run an init inside the container that forwards signals and reaps
+ processes. The default is false.
+ type: bool
+ init_path:
+ description:
+ - Path to the container-init binary.
+ type: str
+ interactive:
+ description:
+ - Keep STDIN open even if not attached. The default is false.
+ When set to true, keep stdin open even if not attached.
+ The default is false.
+ type: bool
+ ip:
+ description:
+ - Specify a static IP address for the container, for example
+ '10.88.64.128'.
+ Can only be used if no additional CNI networks to join were specified
+ via 'network:', and if the container is not joining another container's
+ network namespace via 'network container:<name|id>'.
+ The address must be within the default CNI network's pool
+ (default 10.88.0.0/16).
+ type: str
+ ipc:
+ description:
+ - Default is to create a private IPC namespace (POSIX SysV IPC) for the
+ container
+ type: str
+ aliases:
+ - ipc_mode
+ kernel_memory:
+ description:
+ - Kernel memory limit
+ (format <number>[<unit>], where unit = b, k, m or g)
+ Note - idempotency is supported for integers only.
+ type: str
+ label:
+ description:
+ - Add metadata to a container, pass dictionary of label names and values
+ aliases:
+ - labels
+ type: dict
+ label_file:
+ description:
+ - Read in a line delimited file of labels
+ type: str
+ log_driver:
+ description:
+ - Logging driver. Used to set the log driver for the container.
+ For example log_driver "k8s-file".
+ type: str
+ choices:
+ - k8s-file
+ - journald
+ - json-file
+ log_level:
+ description:
+ - Logging level for Podman. Log messages above specified level
+ ("debug"|"info"|"warn"|"error"|"fatal"|"panic") (default "error")
+ type: str
+ choices:
+ - debug
+ - info
+ - warn
+ - error
+ - fatal
+ - panic
+ log_opt:
+ description:
+ - Logging driver specific options. Used to set the path to the container
+ log file.
+ type: dict
+ aliases:
+ - log_options
+ suboptions:
+ path:
+ description:
+ - Specify a path to the log file (e.g. /var/log/container/mycontainer.json).
+ type: str
+ required: false
+ max_size:
+ description:
+ - Specify a max size of the log file (e.g 10mb).
+ type: str
+ required: false
+ tag:
+ description:
+ - Specify a custom log tag for the container.
+ type: str
+ required: false
+
+ mac_address:
+ description:
+ - Specify a MAC address for the container, for example
+ '92:d0:c6:0a:29:33'.
+ Don't forget that it must be unique within one Ethernet network.
+ type: str
+ memory:
+ description:
+ - Memory limit (format 10k, where unit = b, k, m or g)
+ Note - idempotency is supported for integers only.
+ type: str
+ memory_reservation:
+ description:
+ - Memory soft limit (format 100m, where unit = b, k, m or g)
+ Note - idempotency is supported for integers only.
+ type: str
+ memory_swap:
+ description:
+ - A limit value equal to memory plus swap. Must be used with the -m
+ (--memory) flag.
+ The swap LIMIT should always be larger than -m (--memory) value.
+ By default, the swap LIMIT will be set to double the value of --memory
+ Note - idempotency is supported for integers only.
+ type: str
+ memory_swappiness:
+ description:
+ - Tune a container's memory swappiness behavior. Accepts an integer
+ between 0 and 100.
+ type: int
+ mount:
+ description:
+ - Attach a filesystem mount to the container. bind or tmpfs
+ For example mount
+ "type=bind,source=/path/on/host,destination=/path/in/container"
+ type: str
+ network:
+ description:
+ - Set the Network mode for the container
+ * bridge create a network stack on the default bridge
+ * none no networking
+ * container:<name|id> reuse another container's network stack
+ * host use the podman host network stack.
+ * <network-name>|<network-id> connect to a user-defined network
+ * ns:<path> path to a network namespace to join
+ * slirp4netns use slirp4netns to create a user network stack.
+ This is the default for rootless containers
+ type: list
+ elements: str
+ aliases:
+ - net
+ - network_mode
+ no_hosts:
+ description:
+ - Do not create /etc/hosts for the container
+ Default is false.
+ type: bool
+ oom_kill_disable:
+ description:
+ - Whether to disable OOM Killer for the container or not.
+ Default is false.
+ type: bool
+ oom_score_adj:
+ description:
+ - Tune the host's OOM preferences for containers (accepts -1000 to 1000)
+ type: int
+ pid:
+ description:
+ - Set the PID mode for the container
+ type: str
+ aliases:
+ - pid_mode
+ pids_limit:
+ description:
+ - Tune the container's PIDs limit. Set -1 to have unlimited PIDs for the
+ container.
+ type: str
+ pod:
+ description:
+ - Run container in an existing pod.
+ If you want podman to make the pod for you, preference the pod name
+ with "new:"
+ type: str
+ privileged:
+ description:
+ - Give extended privileges to this container. The default is false.
+ type: bool
+ publish:
+ description:
+ - Publish a container's port, or range of ports, to the host.
+ Format - ip:hostPort:containerPort | ip::containerPort |
+ hostPort:containerPort | containerPort
+ In case of only containerPort is set, the hostPort will chosen
+ randomly by Podman.
+ type: list
+ elements: str
+ aliases:
+ - ports
+ - published
+ - published_ports
+ publish_all:
+ description:
+ - Publish all exposed ports to random ports on the host interfaces. The
+ default is false.
+ type: bool
+ read_only:
+ description:
+ - Mount the container's root filesystem as read only. Default is false
+ type: bool
+ read_only_tmpfs:
+ description:
+ - If container is running in --read-only mode, then mount a read-write
+ tmpfs on /run, /tmp, and /var/tmp. The default is true
+ type: bool
+ recreate:
+ description:
+ - Use with present and started states to force the re-creation of an
+ existing container.
+ type: bool
+ default: False
+ restart_policy:
+ description:
+ - Restart policy to follow when containers exit.
+ Restart policy will not take effect if a container is stopped via the
+ podman kill or podman stop commands. Valid values are
+ * no - Do not restart containers on exit
+ * on-failure[:max_retries] - Restart containers when they exit with a
+ non-0 exit code, retrying indefinitely
+ or until the optional max_retries count is hit
+ * always - Restart containers when they exit, regardless of status,
+ retrying indefinitely
+ type: str
+ rm:
+ description:
+ - Automatically remove the container when it exits. The default is false.
+ type: bool
+ aliases:
+ - remove
+ - auto_remove
+ rootfs:
+ description:
+ - If true, the first argument refers to an exploded container on the file
+ system. The default is false.
+ type: bool
+ security_opt:
+ description:
+ - Security Options. For example security_opt "seccomp=unconfined"
+ type: list
+ elements: str
+ shm_size:
+ description:
+ - Size of /dev/shm. The format is <number><unit>. number must be greater
+ than 0.
+ Unit is optional and can be b (bytes), k (kilobytes), m(megabytes), or
+ g (gigabytes).
+ If you omit the unit, the system uses bytes. If you omit the size
+ entirely, the system uses 64m
+ type: str
+ sig_proxy:
+ description:
+ - Proxy signals sent to the podman run command to the container process.
+ SIGCHLD, SIGSTOP, and SIGKILL are not proxied. The default is true.
+ type: bool
+ stop_signal:
+ description:
+ - Signal to stop a container. Default is SIGTERM.
+ type: int
+ stop_timeout:
+ description:
+ - Timeout (in seconds) to stop a container. Default is 10.
+ type: int
+ subgidname:
+ description:
+ - Run the container in a new user namespace using the map with 'name' in
+ the /etc/subgid file.
+ type: str
+ subuidname:
+ description:
+ - Run the container in a new user namespace using the map with 'name' in
+ the /etc/subuid file.
+ type: str
+ sysctl:
+ description:
+ - Configure namespaced kernel parameters at runtime
+ type: dict
+ systemd:
+ description:
+ - Run container in systemd mode. The default is true.
+ type: bool
+ tmpfs:
+ description:
+ - Create a tmpfs mount. For example tmpfs
+ "/tmp" "rw,size=787448k,mode=1777"
+ type: dict
+ tty:
+ description:
+ - Allocate a pseudo-TTY. The default is false.
+ type: bool
+ uidmap:
+ description:
+ - Run the container in a new user namespace using the supplied mapping.
+ type: list
+ elements: str
+ ulimit:
+ description:
+ - Ulimit options
+ type: list
+ aliases:
+ - ulimits
+ user:
+ description:
+ - Sets the username or UID used and optionally the groupname or GID for
+ the specified command.
+ type: str
+ userns:
+ description:
+ - Set the user namespace mode for the container.
+ It defaults to the PODMAN_USERNS environment variable.
+ An empty value means user namespaces are disabled.
+ type: str
+ aliases:
+ - userns_mode
+ uts:
+ description:
+ - Set the UTS mode for the container
+ type: str
+ volume:
+ description:
+ - Create a bind mount. If you specify, volume /HOST-DIR:/CONTAINER-DIR,
+ podman bind mounts /HOST-DIR in the host to /CONTAINER-DIR in the
+ podman container.
+ type: list
+ elements: str
+ aliases:
+ - volumes
+ volumes_from:
+ description:
+ - Mount volumes from the specified container(s).
+ type: list
+ elements: str
+ workdir:
+ description:
+ - Working directory inside the container.
+ The default working directory for running binaries within a container
+ is the root directory (/).
+ type: str
+ aliases:
+ - working_dir
+"""
+
+EXAMPLES = r"""
+- name: Run container
+ containers.podman.podman_container:
+ name: container
+ image: quay.io/bitnami/wildfly
+ state: started
+
+- name: Create a data container
+ containers.podman.podman_container:
+ name: mydata
+ image: busybox
+ volume:
+ - /tmp/data
+
+- name: Re-create a redis container
+ containers.podman.podman_container:
+ name: myredis
+ image: redis
+ command: redis-server --appendonly yes
+ state: present
+ recreate: yes
+ expose:
+ - 6379
+ volumes_from:
+ - mydata
+
+- name: Restart a container
+ containers.podman.podman_container:
+ name: myapplication
+ image: redis
+ state: started
+ restart: yes
+ etc_hosts:
+ other: "127.0.0.1"
+ restart_policy: "no"
+ device: "/dev/sda:/dev/xvda:rwm"
+ ports:
+ - "8080:9000"
+ - "127.0.0.1:8081:9001/udp"
+ env:
+ SECRET_KEY: "ssssh"
+ BOOLEAN_KEY: "yes"
+
+- name: Container present
+ containers.podman.podman_container:
+ name: mycontainer
+ state: present
+ image: ubuntu:14.04
+ command: "sleep 1d"
+
+- name: Stop a container
+ containers.podman.podman_container:
+ name: mycontainer
+ state: stopped
+
+- name: Start 4 load-balanced containers
+ containers.podman.podman_container:
+ name: "container{{ item }}"
+ recreate: yes
+ image: someuser/anotherappimage
+ command: sleep 1d
+ with_sequence: count=4
+
+- name: remove container
+ containers.podman.podman_container:
+ name: ohno
+ state: absent
+
+- name: Writing output
+ containers.podman.podman_container:
+ name: myservice
+ image: busybox
+ log_options: path=/var/log/container/mycontainer.json
+ log_driver: k8s-file
+"""
+
+RETURN = r"""
+container:
+ description:
+ - Facts representing the current state of the container. Matches the
+ podman inspection output.
+ - Note that facts are part of the registered vars since Ansible 2.8. For
+ compatibility reasons, the facts
+ are also accessible directly as C(podman_container). Note that the
+ returned fact will be removed in Ansible 2.12.
+ - Empty if C(state) is I(absent).
+ returned: always
+ type: dict
+ sample: '{
+ "AppArmorProfile": "",
+ "Args": [
+ "sh"
+ ],
+ "BoundingCaps": [
+ "CAP_CHOWN",
+ ...
+ ],
+ "Config": {
+ "Annotations": {
+ "io.kubernetes.cri-o.ContainerType": "sandbox",
+ "io.kubernetes.cri-o.TTY": "false"
+ },
+ "AttachStderr": false,
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "Cmd": [
+ "sh"
+ ],
+ "Domainname": "",
+ "Entrypoint": "",
+ "Env": [
+ "PATH=/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=xterm",
+ "HOSTNAME=",
+ "container=podman"
+ ],
+ "Hostname": "",
+ "Image": "docker.io/library/busybox:latest",
+ "Labels": null,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "StopSignal": 15,
+ "Tty": false,
+ "User": {
+ "gid": 0,
+ "uid": 0
+ },
+ "Volumes": null,
+ "WorkingDir": "/"
+ },
+ "ConmonPidFile": "...",
+ "Created": "2019-06-17T19:13:09.873858307+03:00",
+ "Dependencies": [],
+ "Driver": "overlay",
+ "EffectiveCaps": [
+ "CAP_CHOWN",
+ ...
+ ],
+ "ExecIDs": [],
+ "ExitCommand": [
+ "/usr/bin/podman",
+ "--root",
+ ...
+ ],
+ "GraphDriver": {
+ ...
+ },
+ "HostConfig": {
+ ...
+ },
+ "HostnamePath": "...",
+ "HostsPath": "...",
+ "ID": "...",
+ "Image": "...",
+ "ImageName": "docker.io/library/busybox:latest",
+ "IsInfra": false,
+ "LogPath": "/tmp/container/mycontainer.json",
+ "MountLabel": "system_u:object_r:container_file_t:s0:c282,c782",
+ "Mounts": [
+ ...
+ ],
+ "Name": "myservice",
+ "Namespace": "",
+ "NetworkSettings": {
+ "Bridge": "",
+ ...
+ },
+ "Path": "sh",
+ "ProcessLabel": "system_u:system_r:container_t:s0:c282,c782",
+ "ResolvConfPath": "...",
+ "RestartCount": 0,
+ "Rootfs": "",
+ "State": {
+ "Dead": false,
+ "Error": "",
+ "ExitCode": 0,
+ "FinishedAt": "2019-06-17T19:13:10.157518963+03:00",
+ "Healthcheck": {
+ "FailingStreak": 0,
+ "Log": null,
+ "Status": ""
+ },
+ "OOMKilled": false,
+ "OciVersion": "1.0.1-dev",
+ "Paused": false,
+ "Pid": 4083,
+ "Restarting": false,
+ "Running": false,
+ "StartedAt": "2019-06-17T19:13:10.152479729+03:00",
+ "Status": "exited"
+ },
+ "StaticDir": "..."
+ ...
+ }'
+"""
+
+from ansible.module_utils.basic import AnsibleModule # noqa: F402
+from ..module_utils.podman.podman_container_lib import PodmanManager # noqa: F402
+from ..module_utils.podman.podman_container_lib import ARGUMENTS_SPEC_CONTAINER # noqa: F402
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=ARGUMENTS_SPEC_CONTAINER,
+ mutually_exclusive=(
+ ['no_hosts', 'etc_hosts'],
+ ),
+ supports_check_mode=True,
+ )
+
+ # work on input vars
+ if module.params['state'] in ['started', 'present'] and \
+ not module.params['image']:
+ module.fail_json(msg="State '%s' required image to be configured!" %
+ module.params['state'])
+
+ results = PodmanManager(module, module.params).execute()
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container_info.py
new file mode 100644
index 00000000..d3ec55c8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_container_info.py
@@ -0,0 +1,405 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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_info
+author:
+ - Sagi Shnaidman (@sshnaidm)
+ - Emilien Macchi (@EmilienM)
+short_description: Gather facts about containers using podman
+notes:
+ - Podman may require elevated privileges in order to run properly.
+description:
+ - Gather facts about containers using C(podman)
+requirements:
+ - "Podman installed on host"
+options:
+ name:
+ description:
+ - List of container names to gather facts about. If no name is given
+ return facts about all containers.
+ type: list
+ elements: str
+ 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: Gather facts for all containers
+ containers.podman.podman_container_info:
+
+- name: Gather facts on a specific container
+ containers.podman.podman_container_info:
+ name: web1
+
+- name: Gather facts on several containers
+ containers.podman.podman_container_info:
+ name:
+ - redis
+ - web1
+"""
+
+RETURN = r"""
+containers:
+ description: Facts from all or specificed containers
+ returned: always
+ type: list
+ elements: dict
+ sample: [
+ {
+ "Id": "c5c39f9b80a6ea2ad665aa9946435934e478a0c5322da835f3883872f",
+ "Created": "2019-10-01T12:51:00.233106443Z",
+ "Path": "dumb-init",
+ "Args": [
+ "--single-child",
+ "--",
+ "kolla_start"
+ ],
+ "State": {
+ "OciVersion": "1.0.1-dev",
+ "Status": "configured",
+ "Running": false,
+ "Paused": false,
+ "Restarting": false,
+ "OOMKilled": false,
+ "Dead": false,
+ "Pid": 0,
+ "ExitCode": 0,
+ "Error": "",
+ "StartedAt": "0001-01-01T00:00:00Z",
+ "FinishedAt": "0001-01-01T00:00:00Z",
+ "Healthcheck": {
+ "Status": "",
+ "FailingStreak": 0,
+ "Log": null
+ }
+ },
+ "Image": "0e267acda67d0ebd643e900d820a91b961d859743039e620191ca1",
+ "ImageName": "docker.io/tripleomaster/centos-haproxy:latest",
+ "Rootfs": "",
+ "Pod": "",
+ "ResolvConfPath": "",
+ "HostnamePath": "",
+ "HostsPath": "",
+ "OCIRuntime": "runc",
+ "Name": "haproxy",
+ "RestartCount": 0,
+ "Driver": "overlay",
+ "MountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c78,c866",
+ "ProcessLabel": "system_u:system_r:svirt_lxc_net_t:s0:c785,c866",
+ "AppArmorProfile": "",
+ "EffectiveCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FSETID",
+ "CAP_FOWNER",
+ "CAP_MKNOD",
+ "CAP_NET_RAW",
+ "CAP_SETGID",
+ "CAP_SETUID",
+ "CAP_SETFCAP",
+ "CAP_SETPCAP",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SYS_CHROOT",
+ "CAP_KILL",
+ "CAP_AUDIT_WRITE"
+ ],
+ "BoundingCaps": [
+ "CAP_CHOWN",
+ "CAP_DAC_OVERRIDE",
+ "CAP_FSETID",
+ "CAP_FOWNER",
+ "CAP_MKNOD",
+ "CAP_NET_RAW",
+ "CAP_SETGID",
+ "CAP_SETUID",
+ "CAP_SETFCAP",
+ "CAP_SETPCAP",
+ "CAP_NET_BIND_SERVICE",
+ "CAP_SYS_CHROOT",
+ "CAP_KILL",
+ "CAP_AUDIT_WRITE"
+ ],
+ "ExecIDs": [],
+ "GraphDriver": {
+ "Name": "overlay"
+ },
+ "Mounts": [],
+ "Dependencies": [],
+ "NetworkSettings": {
+ "Bridge": "",
+ "SandboxID": "",
+ "HairpinMode": false,
+ "LinkLocalIPv6Address": "",
+ "LinkLocalIPv6PrefixLen": 0,
+ "Ports": [],
+ "SandboxKey": "",
+ "SecondaryIPAddresses": null,
+ "SecondaryIPv6Addresses": null,
+ "EndpointID": "",
+ "Gateway": "",
+ "GlobalIPv6Address": "",
+ "GlobalIPv6PrefixLen": 0,
+ "IPAddress": "",
+ "IPPrefixLen": 0,
+ "IPv6Gateway": "",
+ "MacAddress": ""
+ },
+ "ExitCommand": [
+ "/usr/bin/podman",
+ "--root",
+ "/var/lib/containers/storage",
+ "--runroot",
+ "/var/run/containers/storage",
+ "--log-level",
+ "error",
+ "--cgroup-manager",
+ "systemd",
+ "--tmpdir",
+ "/var/run/libpod",
+ "--runtime",
+ "runc",
+ "--storage-driver",
+ "overlay",
+ "--events-backend",
+ "journald",
+ "container",
+ "cleanup",
+ "c9e813703f9b80a6ea2ad665aa9946435934e478a0c5322da835f3883872f"
+ ],
+ "Namespace": "",
+ "IsInfra": false,
+ "Config": {
+ "Hostname": "c5c39e813703",
+ "Domainname": "",
+ "User": "",
+ "AttachStdin": false,
+ "AttachStdout": false,
+ "AttachStderr": false,
+ "Tty": false,
+ "OpenStdin": false,
+ "StdinOnce": false,
+ "Env": [
+ "PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=xterm",
+ "HOSTNAME=",
+ "container=oci",
+ "KOLLA_INSTALL_METATYPE=rdo",
+ "KOLLA_BASE_DISTRO=centos",
+ "KOLLA_INSTALL_TYPE=binary",
+ "KOLLA_DISTRO_PYTHON_VERSION=2.7",
+ "KOLLA_BASE_ARCH=x86_64"
+ ],
+ "Cmd": [
+ "kolla_start"
+ ],
+ "Image": "docker.io/tripleomaster/centos-haproxy:latest",
+ "Volumes": null,
+ "WorkingDir": "/",
+ "Entrypoint": "dumb-init --single-child --",
+ "OnBuild": null,
+ "Labels": {
+ "build-date": "20190919",
+ "kolla_version": "8.1.0",
+ "name": "haproxy",
+ "org.label-schema.build-date": "20190801",
+ "org.label-schema.license": "GPLv2",
+ "org.label-schema.name": "CentOS Base Image",
+ "org.label-schema.schema-version": "1.0",
+ "org.label-schema.vendor": "CentOS"
+ },
+ "Annotations": {
+ "io.kubernetes.cri-o.ContainerType": "sandbox",
+ "io.kubernetes.cri-o.TTY": "false",
+ "io.podman.annotations.autoremove": "FALSE",
+ "io.podman.annotations.init": "FALSE",
+ "io.podman.annotations.privileged": "FALSE",
+ "io.podman.annotations.publish-all": "FALSE"
+ },
+ "StopSignal": 15
+ },
+ "HostConfig": {
+ "Binds": [],
+ "ContainerIDFile": "",
+ "LogConfig": {
+ "Type": "k8s-file",
+ "Config": null
+ },
+ "NetworkMode": "default",
+ "PortBindings": {},
+ "RestartPolicy": {
+ "Name": "",
+ "MaximumRetryCount": 0
+ },
+ "AutoRemove": false,
+ "VolumeDriver": "",
+ "VolumesFrom": null,
+ "CapAdd": [],
+ "CapDrop": [],
+ "Dns": [],
+ "DnsOptions": [],
+ "DnsSearch": [],
+ "ExtraHosts": [],
+ "GroupAdd": [],
+ "IpcMode": "",
+ "Cgroup": "",
+ "Links": null,
+ "OomScoreAdj": 0,
+ "PidMode": "",
+ "Privileged": false,
+ "PublishAllPorts": false,
+ "ReadonlyRootfs": false,
+ "SecurityOpt": [],
+ "Tmpfs": {},
+ "UTSMode": "",
+ "UsernsMode": "",
+ "ShmSize": 65536000,
+ "Runtime": "oci",
+ "ConsoleSize": [
+ 0,
+ 0
+ ],
+ "Isolation": "",
+ "CpuShares": 0,
+ "Memory": 0,
+ "NanoCpus": 0,
+ "CgroupParent": "",
+ "BlkioWeight": 0,
+ "BlkioWeightDevice": null,
+ "BlkioDeviceReadBps": null,
+ "BlkioDeviceWriteBps": null,
+ "BlkioDeviceReadIOps": null,
+ "BlkioDeviceWriteIOps": null,
+ "CpuPeriod": 0,
+ "CpuQuota": 0,
+ "CpuRealtimePeriod": 0,
+ "CpuRealtimeRuntime": 0,
+ "CpusetCpus": "",
+ "CpusetMems": "",
+ "Devices": [],
+ "DiskQuota": 0,
+ "KernelMemory": 0,
+ "MemoryReservation": 0,
+ "MemorySwap": 0,
+ "MemorySwappiness": -1,
+ "OomKillDisable": false,
+ "PidsLimit": 0,
+ "Ulimits": [
+ {
+ "Name": "RLIMIT_NOFILE",
+ "Soft": 1048576,
+ "Hard": 1048576
+ },
+ {
+ "Name": "RLIMIT_NPROC",
+ "Soft": 1048576,
+ "Hard": 1048576
+ }
+ ],
+ "CpuCount": 0,
+ "CpuPercent": 0,
+ "IOMaximumIOps": 0,
+ "IOMaximumBandwidth": 0
+ }
+ }
+ ]
+"""
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+def get_containers_facts(module, executable, name):
+ """Collect containers facts for all containers or for specified in 'name'.
+
+ Arguments:
+ module {AnsibleModule} -- instance of AnsibleModule
+ executable {string} -- binary to execute when inspecting containers
+ name {list} -- list of names or None in case of all containers
+
+ Returns:
+ list of containers info, stdout, stderr
+ """
+ if not name:
+ all_names = [executable, 'container', 'ls', '-q', '-a']
+ rc, out, err = module.run_command(all_names)
+ if rc != 0:
+ module.fail_json(msg="Unable to get list of containers: %s" % err)
+ name = out.split()
+ if not name:
+ return [], out, err
+ command = [executable, 'container', 'inspect']
+ command.extend(name)
+ rc, out, err = module.run_command(command)
+ if rc == 0:
+ json_out = json.loads(out) if out else None
+ if json_out is None:
+ return [], out, err
+ return json_out, out, err
+ if rc != 0 and 'no such ' in err:
+ if len(name) < 2:
+ return [], out, err
+ return cycle_over(module, executable, name)
+ module.fail_json(msg="Unable to gather info for %s: %s" % (",".join(name), err))
+
+
+def cycle_over(module, executable, name):
+ """Inspect each container in a cycle in case some of them don't exist.
+
+ Arguments:
+ module {AnsibleModule} -- instance of AnsibleModule
+ executable {string} -- binary to execute when inspecting containers
+ name {list} -- list of containers names to inspect
+
+ Returns:
+ list of containers info, stdout as empty, stderr
+ """
+ inspection = []
+ stderrs = []
+ for container in name:
+ command = [executable, 'container', 'inspect', container]
+ rc, out, err = module.run_command(command)
+ if rc != 0 and 'no such ' not in err:
+ module.fail_json(msg="Unable to gather info for %s: %s" % (container, err))
+ if rc == 0 and out:
+ json_out = json.loads(out)
+ if json_out:
+ inspection += json_out
+ stderrs.append(err)
+ return inspection, "", "\n".join(stderrs)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec={
+ 'executable': {'type': 'str', 'default': 'podman'},
+ 'name': {'type': 'list', 'elements': 'str'},
+ },
+ supports_check_mode=True,
+ )
+
+ name = module.params['name']
+ executable = module.get_bin_path(module.params['executable'], required=True)
+ # pylint: disable=unused-variable
+ inspect_results, out, err = get_containers_facts(module, executable, name)
+
+ results = {
+ "changed": False,
+ "containers": inspect_results,
+ "stderr": err
+ }
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_containers.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_containers.py
new file mode 100644
index 00000000..75ebb057
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_containers.py
@@ -0,0 +1,162 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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 = '''
+---
+module: podman_containers
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.4.0'
+short_description: Manage podman containers in a batch
+description:
+ - Manage groups of podman containers
+requirements:
+ - "podman"
+options:
+ containers:
+ description:
+ - List of dictionaries with data for running containers for podman_container module.
+ required: True
+ type: list
+ elements: dict
+ debug:
+ description:
+ - Return additional information which can be helpful for investigations.
+ type: bool
+ default: False
+'''
+
+EXAMPLES = '''
+- name: Run three containers at once
+ podman_containers:
+ containers:
+ - name: alpine
+ image: alpine
+ command: sleep 1d
+ - name: web
+ image: nginx
+ - name: test
+ image: python:3-alpine
+ command: python -V
+'''
+
+from copy import deepcopy # noqa: F402
+
+from ansible.module_utils.basic import AnsibleModule # noqa: F402
+from ..module_utils.podman.podman_container_lib import PodmanManager # noqa: F402
+from ..module_utils.podman.podman_container_lib import ARGUMENTS_SPEC_CONTAINER # noqa: F402
+
+
+def init_options():
+ default = {}
+ opts = ARGUMENTS_SPEC_CONTAINER
+ for k, v in opts.items():
+ if 'default' in v:
+ default[k] = v['default']
+ else:
+ default[k] = None
+ return default
+
+
+def update_options(opts_dict, container):
+ aliases = {}
+ for k, v in ARGUMENTS_SPEC_CONTAINER.items():
+ if 'aliases' in v:
+ for alias in v['aliases']:
+ aliases[alias] = k
+ for k in list(container):
+ if k in aliases:
+ key = aliases[k]
+ opts_dict[key] = container[k]
+ container.pop(k)
+ opts_dict.update(container)
+ return opts_dict
+
+
+def combine(results):
+ changed = any([i.get('changed', False) for i in results])
+ failed = any([i.get('failed', False) for i in results])
+ actions = []
+ podman_actions = []
+ containers = []
+ podman_version = ''
+ diffs = {}
+ stderr = ''
+ stdout = ''
+ for i in results:
+ if 'actions' in i and i['actions']:
+ actions += i['actions']
+ if 'podman_actions' in i and i['podman_actions']:
+ podman_actions += i['podman_actions']
+ if 'container' in i and i['container']:
+ containers.append(i['container'])
+ if 'podman_version' in i:
+ podman_version = i['podman_version']
+ if 'diff' in i:
+ diffs[i['container']['Name']] = i['diff']
+ if 'stderr' in i:
+ stderr += i['stderr']
+ if 'stdout' in i:
+ stdout += i['stdout']
+
+ total = {
+ 'changed': changed,
+ 'failed': failed,
+ 'actions': actions,
+ 'podman_actions': podman_actions,
+ 'containers': containers,
+ 'stdout': stdout,
+ 'stderr': stderr,
+ }
+ if podman_version:
+ total['podman_version'] = podman_version
+ if diffs:
+ before = after = ''
+ for k, v in diffs.items():
+ before += "".join([str(k), ": ", str(v['before']), "\n"])
+ after += "".join([str(k), ": ", str(v['after']), "\n"])
+ total['diff'] = {
+ 'before': before,
+ 'after': after
+ }
+ return total
+
+
+def check_input_strict(container):
+ if container['state'] in ['started', 'present'] and not container['image']:
+ return "State '%s' required image to be configured!" % container['state']
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ containers=dict(type='list', elements='dict', required=True),
+ debug=dict(type='bool', default=False),
+ ),
+ supports_check_mode=True,
+ )
+ # work on input vars
+
+ results = []
+ default_options_templ = init_options()
+ for container in module.params['containers']:
+ options_dict = deepcopy(default_options_templ)
+ options_dict = update_options(options_dict, container)
+ options_dict['debug'] = module.params['debug'] or options_dict['debug']
+ test_input = check_input_strict(options_dict)
+ if test_input:
+ module.fail_json(
+ msg="Failed to run container %s because: %s" % (options_dict['name'], test_input))
+ res = PodmanManager(module, options_dict).execute()
+ results.append(res)
+ total_results = combine(results)
+ module.exit_json(**total_results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image.py
new file mode 100644
index 00000000..186f0498
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image.py
@@ -0,0 +1,774 @@
+#!/usr/bin/python
+# Copyright (c) 2018 Ansible Project
+# 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_image
+ author:
+ - Sam Doran (@samdoran)
+ short_description: Pull images for use by podman
+ notes: []
+ description:
+ - Build, pull, or push images using Podman.
+ options:
+ name:
+ description:
+ - Name of the image to pull, push, or delete. It may contain a tag using the format C(image:tag).
+ required: True
+ type: str
+ 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
+ ca_cert_dir:
+ description:
+ - Path to directory containing TLS certificates and keys to use.
+ type: 'path'
+ tag:
+ description:
+ - Tag of the image to pull, push, or delete.
+ default: "latest"
+ type: str
+ pull:
+ description: Whether or not to pull the image.
+ default: True
+ type: bool
+ push:
+ description: Whether or not to push an image.
+ default: False
+ type: bool
+ path:
+ description: Path to directory containing the build file.
+ type: str
+ force:
+ description:
+ - Whether or not to force push or pull an image.
+ - When building, force the build even if the image already exists.
+ type: bool
+ default: False
+ state:
+ description:
+ - Whether an image should be present, absent, or built.
+ default: "present"
+ type: str
+ choices:
+ - present
+ - absent
+ - build
+ validate_certs:
+ description:
+ - Require HTTPS and validate certificates when pulling or pushing. Also used during build if a pull or push is necessary.
+ default: True
+ type: bool
+ aliases:
+ - tlsverify
+ - tls_verify
+ password:
+ description:
+ - Password to use when authenticating to remote registries.
+ type: str
+ username:
+ description:
+ - username to use when authenticating to remote registries.
+ type: str
+ auth_file:
+ description:
+ - Path to file containing authorization credentials to the remote registry.
+ aliases:
+ - authfile
+ type: path
+ build:
+ description: Arguments that control image build.
+ type: dict
+ aliases:
+ - build_args
+ - buildargs
+ suboptions:
+ volume:
+ description:
+ - Specify multiple volume / mount options to mount one or more mounts to a container.
+ type: list
+ elements: str
+ annotation:
+ description:
+ - Dictionary of key=value pairs to add to the image. Only works with OCI images. Ignored for Docker containers.
+ type: dict
+ force_rm:
+ description:
+ - Always remove intermediate containers after a build, even if the build is unsuccessful.
+ type: bool
+ default: False
+ format:
+ description:
+ - Format of the built image.
+ type: str
+ choices:
+ - docker
+ - oci
+ default: "oci"
+ cache:
+ description:
+ - Whether or not to use cached layers when building an image
+ type: bool
+ default: True
+ rm:
+ description: Remove intermediate containers after a successful build
+ type: bool
+ default: True
+ extra_args:
+ description:
+ - Extra args to pass to build, if executed. Does not idempotently check for new build args.
+ type: str
+ push_args:
+ description: Arguments that control pushing images.
+ type: dict
+ suboptions:
+ compress:
+ description:
+ - Compress tarball image layers when pushing to a directory using the 'dir' transport.
+ type: bool
+ format:
+ description:
+ - Manifest type to use when pushing an image using the 'dir' transport (default is manifest type of source).
+ type: str
+ choices:
+ - oci
+ - v2s1
+ - v2s2
+ remove_signatures:
+ description: Discard any pre-existing signatures in the image
+ type: bool
+ sign_by:
+ description:
+ - Path to a key file to use to sign the image.
+ type: str
+ dest:
+ description: Path or URL where image will be pushed.
+ type: str
+ aliases:
+ - destination
+ transport:
+ description:
+ - Transport to use when pushing in image. If no transport is set, will attempt to push to a remote registry.
+ type: str
+ choices:
+ - dir
+ - docker-archive
+ - docker-daemon
+ - oci-archive
+ - ostree
+'''
+
+EXAMPLES = r"""
+- name: Pull an image
+ container.podman.podman_image:
+ name: quay.io/bitnami/wildfly
+
+- name: Remove an image
+ container.podman.podman_image:
+ name: quay.io/bitnami/wildfly
+ state: absent
+
+- name: Pull a specific version of an image
+ container.podman.podman_image:
+ name: redis
+ tag: 4
+
+- name: Build a basic OCI image
+ container.podman.podman_image:
+ name: nginx
+ path: /path/to/build/dir
+
+- name: Build a basic OCI image with advanced parameters
+ container.podman.podman_image:
+ name: nginx
+ path: /path/to/build/dir
+ build:
+ cache: no
+ force_rm: yes
+ format: oci
+ annotation:
+ app: nginx
+ function: proxy
+ info: Load balancer for my cool app
+
+- name: Build a Docker formatted image
+ container.podman.podman_image:
+ name: nginx
+ path: /path/to/build/dir
+ build:
+ format: docker
+
+- name: Build and push an image using existing credentials
+ container.podman.podman_image:
+ name: nginx
+ path: /path/to/build/dir
+ push: yes
+ push_args:
+ dest: quay.io/acme
+
+- name: Build and push an image using an auth file
+ container.podman.podman_image:
+ name: nginx
+ push: yes
+ auth_file: /etc/containers/auth.json
+ push_args:
+ dest: quay.io/acme
+
+- name: Build and push an image using username and password
+ container.podman.podman_image:
+ name: nginx
+ push: yes
+ username: bugs
+ password: "{{ vault_registry_password }}"
+ push_args:
+ dest: quay.io/acme
+
+- name: Build and push an image to multiple registries
+ container.podman.podman_image:
+ name: "{{ item }}"
+ path: /path/to/build/dir
+ push: yes
+ auth_file: /etc/containers/auth.json
+ loop:
+ - quay.io/acme/nginx
+ - docker.io/acme/nginx
+
+- name: Build and push an image to multiple registries with separate parameters
+ container.podman.podman_image:
+ name: "{{ item.name }}"
+ tag: "{{ item.tag }}"
+ path: /path/to/build/dir
+ push: yes
+ auth_file: /etc/containers/auth.json
+ push_args:
+ dest: "{{ item.dest }}"
+ loop:
+ - name: nginx
+ tag: 4
+ dest: docker.io/acme
+
+ - name: nginx
+ tag: 3
+ dest: docker.io/acme
+"""
+
+RETURN = r"""
+ image:
+ description:
+ - Image inspection results for the image that was pulled, pushed, or built.
+ returned: success
+ type: dict
+ sample: [
+ {
+ "Annotations": {},
+ "Architecture": "amd64",
+ "Author": "",
+ "Comment": "from Bitnami with love",
+ "ContainerConfig": {
+ "Cmd": [
+ "/run.sh"
+ ],
+ "Entrypoint": [
+ "/app-entrypoint.sh"
+ ],
+ "Env": [
+ "PATH=/opt/bitnami/java/bin:/opt/bitnami/wildfly/bin:/opt/bitnami/nami/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "IMAGE_OS=debian-9",
+ "NAMI_VERSION=1.0.0-1",
+ "GPG_KEY_SERVERS_LIST=ha.pool.sks-keyservers.net",
+ "TINI_VERSION=v0.13.2",
+ "TINI_GPG_KEY=595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7",
+ "GOSU_VERSION=1.10",
+ "GOSU_GPG_KEY=B42F6819007F00F88E364FD4036A9C25BF357DD4",
+ "BITNAMI_IMAGE_VERSION=16.0.0-debian-9-r27",
+ "BITNAMI_PKG_CHMOD=-R g+rwX",
+ "BITNAMI_PKG_EXTRA_DIRS=/home/wildfly",
+ "HOME=/",
+ "BITNAMI_APP_NAME=wildfly",
+ "NAMI_PREFIX=/.nami",
+ "WILDFLY_HOME=/home/wildfly",
+ "WILDFLY_JAVA_HOME=",
+ "WILDFLY_JAVA_OPTS=",
+ "WILDFLY_MANAGEMENT_HTTP_PORT_NUMBER=9990",
+ "WILDFLY_PASSWORD=bitnami",
+ "WILDFLY_PUBLIC_CONSOLE=true",
+ "WILDFLY_SERVER_AJP_PORT_NUMBER=8009",
+ "WILDFLY_SERVER_HTTP_PORT_NUMBER=8080",
+ "WILDFLY_SERVER_INTERFACE=0.0.0.0",
+ "WILDFLY_USERNAME=user",
+ "WILDFLY_WILDFLY_HOME=/home/wildfly",
+ "WILDFLY_WILDFLY_OPTS=-Dwildfly.as.deployment.ondemand=false"
+ ],
+ "ExposedPorts": {
+ "8080/tcp": {},
+ "9990/tcp": {}
+ },
+ "Labels": {
+ "maintainer": "Bitnami <containers@bitnami.com>"
+ },
+ "User": "1001"
+ },
+ "Created": "2019-04-10T05:48:03.553887623Z",
+ "Digest": "sha256:5a8ab28e314c2222de3feaf6dac94a0436a37fc08979d2722c99d2bef2619a9b",
+ "GraphDriver": {
+ "Data": {
+ "LowerDir": "/var/lib/containers/storage/overlay/142c1beadf1bb09fbd929465ec98c9dca3256638220450efb4214727d0d0680e/diff:/var/lib/containers/s",
+ "MergedDir": "/var/lib/containers/storage/overlay/9aa10191f5bddb59e28508e721fdeb43505e5b395845fa99723ed787878dbfea/merged",
+ "UpperDir": "/var/lib/containers/storage/overlay/9aa10191f5bddb59e28508e721fdeb43505e5b395845fa99723ed787878dbfea/diff",
+ "WorkDir": "/var/lib/containers/storage/overlay/9aa10191f5bddb59e28508e721fdeb43505e5b395845fa99723ed787878dbfea/work"
+ },
+ "Name": "overlay"
+ },
+ "History": [
+ {
+ "comment": "from Bitnami with love",
+ "created": "2019-04-09T22:27:40.659377677Z"
+ },
+ {
+ "created": "2019-04-09T22:38:53.86336555Z",
+ "created_by": "/bin/sh -c #(nop) LABEL maintainer=Bitnami <containers@bitnami.com>",
+ "empty_layer": true
+ },
+ {
+ "created": "2019-04-09T22:38:54.022778765Z",
+ "created_by": "/bin/sh -c #(nop) ENV IMAGE_OS=debian-9",
+ "empty_layer": true
+ },
+ ],
+ "Id": "ace34da54e4af2145e1ad277005adb235a214e4dfe1114c2db9ab460b840f785",
+ "Labels": {
+ "maintainer": "Bitnami <containers@bitnami.com>"
+ },
+ "ManifestType": "application/vnd.docker.distribution.manifest.v1+prettyjws",
+ "Os": "linux",
+ "Parent": "",
+ "RepoDigests": [
+ "quay.io/bitnami/wildfly@sha256:5a8ab28e314c2222de3feaf6dac94a0436a37fc08979d2722c99d2bef2619a9b"
+ ],
+ "RepoTags": [
+ "quay.io/bitnami/wildfly:latest"
+ ],
+ "RootFS": {
+ "Layers": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "Type": "layers"
+ },
+ "Size": 466180019,
+ "User": "1001",
+ "Version": "18.09.3",
+ "VirtualSize": 466180019
+ }
+ ]
+"""
+
+import json
+import re
+import shlex
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.containers.podman.plugins.module_utils.podman.common import run_podman_command
+
+
+class PodmanImageManager(object):
+
+ def __init__(self, module, results):
+
+ super(PodmanImageManager, self).__init__()
+
+ self.module = module
+ self.results = results
+ self.name = self.module.params.get('name')
+ self.executable = self.module.get_bin_path(module.params.get('executable'), required=True)
+ self.tag = self.module.params.get('tag')
+ self.pull = self.module.params.get('pull')
+ self.push = self.module.params.get('push')
+ self.path = self.module.params.get('path')
+ self.force = self.module.params.get('force')
+ self.state = self.module.params.get('state')
+ self.validate_certs = self.module.params.get('validate_certs')
+ self.auth_file = self.module.params.get('auth_file')
+ self.username = self.module.params.get('username')
+ self.password = self.module.params.get('password')
+ self.ca_cert_dir = self.module.params.get('ca_cert_dir')
+ self.build = self.module.params.get('build')
+ self.push_args = self.module.params.get('push_args')
+
+ repo, repo_tag = parse_repository_tag(self.name)
+ if repo_tag:
+ self.name = repo
+ self.tag = repo_tag
+
+ self.image_name = '{name}:{tag}'.format(name=self.name, tag=self.tag)
+
+ if self.state in ['present', 'build']:
+ self.present()
+
+ if self.state in ['absent']:
+ self.absent()
+
+ def _run(self, args, expected_rc=0, ignore_errors=False):
+ return run_podman_command(
+ module=self.module,
+ executable=self.executable,
+ args=args,
+ expected_rc=expected_rc,
+ ignore_errors=ignore_errors)
+
+ def _get_id_from_output(self, lines, startswith=None, contains=None, split_on=' ', maxsplit=1):
+ layer_ids = []
+ for line in lines.splitlines():
+ if startswith and line.startswith(startswith) or contains and contains in line:
+ splitline = line.rsplit(split_on, maxsplit)
+ layer_ids.append(splitline[1])
+
+ # Podman 1.4 changed the output to only include the layer id when run in quiet mode
+ if not layer_ids:
+ layer_ids = lines.splitlines()
+
+ return(layer_ids[-1])
+
+ def present(self):
+ image = self.find_image()
+
+ if image:
+ digest_before = image[0].get('Digest', image[0].get('digest'))
+ else:
+ digest_before = None
+
+ if not image or self.force:
+ if self.path:
+ # Build the image
+ self.results['actions'].append('Built image {image_name} from {path}'.format(image_name=self.image_name, path=self.path))
+ if not self.module.check_mode:
+ image = self.results['image'] = self.build_image()
+ else:
+ # Pull the image
+ self.results['actions'].append('Pulled image {image_name}'.format(image_name=self.image_name))
+ if not self.module.check_mode:
+ image = self.results['image'] = self.pull_image()
+
+ if not image:
+ image = self.find_image()
+ digest_after = image[0].get('Digest', image[0].get('digest'))
+ self.results['changed'] = digest_before != digest_after
+
+ if self.push:
+ # Push the image
+ if '/' in self.image_name:
+ push_format_string = 'Pushed image {image_name}'
+ else:
+ push_format_string = 'Pushed image {image_name} to {dest}'
+ self.results['actions'].append(push_format_string.format(image_name=self.image_name, dest=self.push_args['dest']))
+ self.results['changed'] = True
+ if not self.module.check_mode:
+ self.results['image'] = self.push_image()
+
+ def absent(self):
+ image = self.find_image()
+
+ if image:
+ self.results['actions'].append('Removed image {name}'.format(name=self.name))
+ self.results['changed'] = True
+ self.results['image']['state'] = 'Deleted'
+ if not self.module.check_mode:
+ self.remove_image()
+
+ def find_image(self, image_name=None):
+ if image_name is None:
+ image_name = self.image_name
+ args = ['image', 'ls', image_name, '--format', 'json']
+ rc, images, err = self._run(args, ignore_errors=True)
+ if len(images) > 0:
+ return json.loads(images)
+ else:
+ return None
+
+ def inspect_image(self, image_name=None):
+ if image_name is None:
+ image_name = self.image_name
+ args = ['inspect', image_name, '--format', 'json']
+ rc, image_data, err = self._run(args)
+ if len(image_data) > 0:
+ return json.loads(image_data)
+ else:
+ return None
+
+ def pull_image(self, image_name=None):
+ if image_name is None:
+ image_name = self.image_name
+
+ args = ['pull', image_name, '-q']
+
+ if self.auth_file:
+ args.extend(['--authfile', self.auth_file])
+
+ if self.username and self.password:
+ cred_string = '{user}:{password}'.format(user=self.username, password=self.password)
+ args.extend(['--creds', cred_string])
+
+ if self.validate_certs is not None:
+ if self.validate_certs:
+ args.append('--tls-verify')
+ else:
+ args.append('--tls-verify=false')
+
+ if self.ca_cert_dir:
+ args.extend(['--cert-dir', self.ca_cert_dir])
+
+ rc, out, err = self._run(args, ignore_errors=True)
+ if rc != 0:
+ self.module.fail_json(msg='Failed to pull image {image_name}'.format(image_name=image_name))
+ return self.inspect_image(out.strip())
+
+ def build_image(self):
+ args = ['build', '-q']
+ args.extend(['-t', self.image_name])
+
+ if self.validate_certs is not None:
+ if self.validate_certs:
+ args.append('--tls-verify')
+ else:
+ args.append('--tls-verify=false')
+
+ annotation = self.build.get('annotation')
+ if annotation:
+ for k, v in annotation.items():
+ args.extend(['--annotation', '{k}={v}'.format(k=k, v=v)])
+
+ if self.ca_cert_dir:
+ args.extend(['--cert-dir', self.ca_cert_dir])
+
+ if self.build.get('force_rm'):
+ args.append('--force-rm')
+
+ image_format = self.build.get('format')
+ if image_format:
+ args.extend(['--format', image_format])
+
+ if not self.build.get('cache'):
+ args.append('--no-cache')
+
+ if self.build.get('rm'):
+ args.append('--rm')
+
+ volume = self.build.get('volume')
+ if volume:
+ for v in volume:
+ args.extend(['--volume', v])
+
+ if self.auth_file:
+ args.extend(['--authfile', self.auth_file])
+
+ if self.username and self.password:
+ cred_string = '{user}:{password}'.format(user=self.username, password=self.password)
+ args.extend(['--creds', cred_string])
+
+ extra_args = self.build.get('extra_args')
+ if extra_args:
+ args.extend([arg for arg in shlex.split(extra_args)])
+
+ args.append(self.path)
+
+ rc, out, err = self._run(args, ignore_errors=True)
+ if rc != 0:
+ self.module.fail_json(msg="Failed to build image {image}: {out} {err}".format(image=self.image_name, out=out, err=err))
+
+ last_id = self._get_id_from_output(out, startswith='-->')
+ return self.inspect_image(last_id)
+
+ def push_image(self):
+ args = ['push']
+
+ if self.validate_certs is not None:
+ if self.validate_certs:
+ args.append('--tls-verify')
+ else:
+ args.append('--tls-verify=false')
+
+ if self.ca_cert_dir:
+ args.extend(['--cert-dir', self.ca_cert_dir])
+
+ if self.username and self.password:
+ cred_string = '{user}:{password}'.format(user=self.username, password=self.password)
+ args.extend(['--creds', cred_string])
+
+ if self.auth_file:
+ args.extend(['--authfile', self.auth_file])
+
+ if self.push_args.get('compress'):
+ args.append('--compress')
+
+ push_format = self.push_args.get('format')
+ if push_format:
+ args.extend(['--format', push_format])
+
+ if self.push_args.get('remove_signatures'):
+ args.append('--remove-signatures')
+
+ sign_by_key = self.push_args.get('sign_by')
+ if sign_by_key:
+ args.extend(['--sign-by', sign_by_key])
+
+ args.append(self.image_name)
+
+ # Build the destination argument
+ dest = self.push_args.get('dest')
+ dest_format_string = '{dest}/{image_name}'
+ regexp = re.compile(r'/{name}(:{tag})?'.format(name=self.name, tag=self.tag))
+ if not dest:
+ if '/' not in self.name:
+ self.module.fail_json(msg="'push_args['dest']' is required when pushing images that do not have the remote registry in the image name")
+
+ # If the push destination contains the image name and/or the tag
+ # remove it and warn since it's not needed.
+ elif regexp.search(dest):
+ dest = regexp.sub('', dest)
+ self.module.warn("Image name and tag are automatically added to push_args['dest']. Destination changed to {dest}".format(dest=dest))
+
+ if dest and dest.endswith('/'):
+ dest = dest[:-1]
+
+ transport = self.push_args.get('transport')
+ if transport:
+ if not dest:
+ self.module.fail_json("'push_args['transport'] requires 'push_args['dest'] but it was not provided.")
+ if transport == 'docker':
+ dest_format_string = '{transport}://{dest}'
+ elif transport == 'ostree':
+ dest_format_string = '{transport}:{name}@{dest}'
+ else:
+ dest_format_string = '{transport}:{dest}'
+
+ dest_string = dest_format_string.format(transport=transport, name=self.name, dest=dest, image_name=self.image_name,)
+
+ # Only append the destination argument if the image name is not a URL
+ if '/' not in self.name:
+ args.append(dest_string)
+
+ rc, out, err = self._run(args, ignore_errors=True)
+ if rc != 0:
+ self.module.fail_json(msg="Failed to push image {image_name}: {err}".format(image_name=self.image_name, err=err))
+ last_id = self._get_id_from_output(
+ out + err, contains=':', split_on=':')
+
+ return self.inspect_image(last_id)
+
+ def remove_image(self, image_name=None):
+ if image_name is None:
+ image_name = self.image_name
+
+ args = ['rmi', image_name]
+ if self.force:
+ args.append('--force')
+ rc, out, err = self._run(args, ignore_errors=True)
+ if rc != 0:
+ self.module.fail_json(msg='Failed to remove image {image_name}. {err}'.format(image_name=image_name, err=err))
+ return out
+
+
+def parse_repository_tag(repo_name):
+ parts = repo_name.rsplit('@', 1)
+ if len(parts) == 2:
+ return tuple(parts)
+ parts = repo_name.rsplit(':', 1)
+ if len(parts) == 2 and '/' not in parts[1]:
+ return tuple(parts)
+ return repo_name, None
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ name=dict(type='str', required=True),
+ tag=dict(type='str', default='latest'),
+ pull=dict(type='bool', default=True),
+ push=dict(type='bool', default=False),
+ path=dict(type='str'),
+ force=dict(type='bool', default=False),
+ state=dict(type='str', default='present', choices=['absent', 'present', 'build']),
+ validate_certs=dict(type='bool', default=True, aliases=['tlsverify', 'tls_verify']),
+ executable=dict(type='str', default='podman'),
+ auth_file=dict(type='path', aliases=['authfile']),
+ username=dict(type='str'),
+ password=dict(type='str', no_log=True),
+ ca_cert_dir=dict(type='path'),
+ build=dict(
+ type='dict',
+ aliases=['build_args', 'buildargs'],
+ default={},
+ options=dict(
+ annotation=dict(type='dict'),
+ force_rm=dict(type='bool', default=False),
+ format=dict(
+ type='str',
+ choices=['oci', 'docker'],
+ default='oci'
+ ),
+ cache=dict(type='bool', default=True),
+ rm=dict(type='bool', default=True),
+ volume=dict(type='list', elements='str'),
+ extra_args=dict(type='str'),
+ ),
+ ),
+ push_args=dict(
+ type='dict',
+ default={},
+ options=dict(
+ compress=dict(type='bool'),
+ format=dict(type='str', choices=['oci', 'v2s1', 'v2s2']),
+ remove_signatures=dict(type='bool'),
+ sign_by=dict(type='str'),
+ dest=dict(type='str', aliases=['destination'],),
+ transport=dict(
+ type='str',
+ choices=[
+ 'dir',
+ 'docker-archive',
+ 'docker-daemon',
+ 'oci-archive',
+ 'ostree',
+ ]
+ ),
+ ),
+ ),
+ ),
+ supports_check_mode=True,
+ required_together=(
+ ['username', 'password'],
+ ),
+ mutually_exclusive=(
+ ['authfile', 'username'],
+ ['authfile', 'password'],
+ ),
+ )
+
+ results = dict(
+ changed=False,
+ actions=[],
+ image={},
+ )
+
+ PodmanImageManager(module, results)
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image_info.py
new file mode 100644
index 00000000..4712c56a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_image_info.py
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+# Copyright (c) 2019 Ansible Project
+# 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_image_info
+author:
+ - Sam Doran (@samdoran)
+short_description: Gather info about images using podman
+notes:
+ - Podman may required elevated privileges in order to run properly.
+description:
+ - Gather info about images using C(podman)
+options:
+ 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
+ name:
+ description:
+ - List of tags or UID to gather info about. If no name is given return info about all images.
+ type: list
+ elements: str
+
+'''
+
+EXAMPLES = r"""
+- name: Gather info for all images
+ containers.podman.podman_image_info:
+
+- name: Gather info on a specific image
+ containers.podman.podman_image_info:
+ name: nginx
+
+- name: Gather info on several images
+ containers.podman.podman_image_info:
+ name:
+ - redis
+ - quay.io/bitnami/wildfly
+"""
+
+RETURN = r"""
+images:
+ description: info from all or specified images
+ returned: always
+ type: dict
+ sample: [
+ {
+ "Annotations": {},
+ "Architecture": "amd64",
+ "Author": "",
+ "Comment": "from Bitnami with love",
+ "ContainerConfig": {
+ "Cmd": [
+ "nami",
+ "start",
+ "--foreground",
+ "wildfly"
+ ],
+ "Entrypoint": [
+ "/app-entrypoint.sh"
+ ],
+ "Env": [
+ "PATH=/opt/bitnami/java/bin:/opt/bitnami/wildfly/bin:/opt/bitnami/nami/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "IMAGE_OS=debian-9",
+ "NAMI_VERSION=0.0.9-0",
+ "GPG_KEY_SERVERS_LIST=ha.pool.sks-keyservers.net \
+hkp://p80.pool.sks-keyservers.net:80 keyserver.ubuntu.com hkp://keyserver.ubuntu.com:80 pgp.mit.edu",
+ "TINI_VERSION=v0.13.2",
+ "TINI_GPG_KEY=595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7",
+ "GOSU_VERSION=1.10",
+ "GOSU_GPG_KEY=B42F6819007F00F88E364FD4036A9C25BF357DD4",
+ "BITNAMI_IMAGE_VERSION=14.0.1-debian-9-r12",
+ "BITNAMI_APP_NAME=wildfly",
+ "WILDFLY_JAVA_HOME=",
+ "WILDFLY_JAVA_OPTS=",
+ "WILDFLY_MANAGEMENT_HTTP_PORT_NUMBER=9990",
+ "WILDFLY_PASSWORD=bitnami",
+ "WILDFLY_PUBLIC_CONSOLE=true",
+ "WILDFLY_SERVER_AJP_PORT_NUMBER=8009",
+ "WILDFLY_SERVER_HTTP_PORT_NUMBER=8080",
+ "WILDFLY_SERVER_INTERFACE=0.0.0.0",
+ "WILDFLY_USERNAME=user",
+ "WILDFLY_WILDFLY_HOME=/home/wildfly",
+ "WILDFLY_WILDFLY_OPTS=-Dwildfly.as.deployment.ondemand=false"
+ ],
+ "ExposedPorts": {
+ "8080/tcp": {},
+ "9990/tcp": {}
+ },
+ "Labels": {
+ "maintainer": "Bitnami <containers@bitnami.com>"
+ }
+ },
+ "Created": "2018-09-25T04:07:45.934395523Z",
+ "Digest": "sha256:5c7d8e2dd66dcf4a152a4032a1d3c5a33458c67e1c1335edd8d18d738892356b",
+ "GraphDriver": {
+ "Data": {
+ "LowerDir": "/var/lib/containers/storage/overlay/a9dbf5616cc16919a8ac0dfc60aff87a72b5be52994c4649fcc91a089a12931\
+f/diff:/var/lib/containers/storage/overlay/67129bd46022122a7d8b7acb490092af6c7ce244ce4fbd7d9e2d2b7f5979e090/diff:/var/lib/containers/storage/overlay/7c51242c\
+4c5db5c74afda76d7fdbeab6965d8b21804bb3fc597dee09c770b0ca/diff:/var/lib/containers/storage/overlay/f97315dc58a9c002ba0cabccb9933d4b0d2113733d204188c88d72f75569b57b/diff:/var/lib/containers/storage/overlay/1dbde2dd497ddde2b467727125b900958a051a72561e58d29abe3d660dcaa9a7/diff:/var/lib/containers/storage/overlay/4aad9d80f30c3f0608f58173558b7554d84dee4dc4479672926eca29f75e6e33/diff:/var/lib/containers/storage/overlay/6751fc9b6868254870c062d75a511543fc8cfda2ce6262f4945f107449219632/diff:/var/lib/containers/storage/overlay/a27034d79081347421dd24d7e9e776c18271cd9a6e51053cb39af4d3d9c400e8/diff:/var/lib/containers/storage/overlay/537cf0045ed9cd7989f7944e7393019c81b16c1799a2198d8348cd182665397f/diff:/var/lib/containers/storage/overlay/27578615c5ae352af4e8449862d61aaf5c11b105a7d5905af55bd01b0c656d6e/diff:/var/lib/containers/storage/overlay/566542742840fe3034b3596f7cb9e62a6274c95a69f368f9e713746f8712c0b6/diff",
+ "MergedDir": "/var/lib/containers/storage/overlay/72bb96d6\
+c53ad57a0b1e44cab226a6251598accbead40b23fac89c19ad8c25ca/merged",
+ "UpperDir": "/var/lib/containers/storage/overlay/72bb96d6c53ad57a0b1e44cab226a6251598accbead40b23fac89c19ad8c25ca/diff",
+ "WorkDir": "/var/lib/containers/storage/overlay/72bb96d6c53ad57a0b1e44cab226a6251598accbead40b23fac89c19ad8c25ca/work"
+ },
+ "Name": "overlay"
+ },
+ "Id": "bcacbdf7a119c0fa934661ca8af839e625ce6540d9ceb6827cdd389f823d49e0",
+ "Labels": {
+ "maintainer": "Bitnami <containers@bitnami.com>"
+ },
+ "ManifestType": "application/vnd.docker.distribution.manifest.v1+prettyjws",
+ "Os": "linux",
+ "Parent": "",
+ "RepoDigests": [
+ "quay.io/bitnami/wildfly@sha256:5c7d8e2dd66dcf4a152a4032a1d3c5a33458c67e1c1335edd8d18d738892356b"
+ ],
+ "RepoTags": [
+ "quay.io/bitnami/wildfly:latest"
+ ],
+ "RootFS": {
+ "Layers": [
+ "sha256:75391df2c87e076b0c2f72d20c95c57dc8be7ee684cc07273416cce622b43367",
+ "sha256:7dd303f041039bfe8f0833092673ac35f93137d10e0fbc4302021ea65ad57731",
+ "sha256:720d9edf0cd2a9bb56b88b80be9070dbfaad359514c70094c65066963fed485d",
+ "sha256:6a567ecbf97725501a634fcb486271999aa4591b633b4ae9932a46b40f5aaf47",
+ "sha256:59e9a6db8f178f3da868614564faabb2820cdfb69be32e63a4405d6f7772f68c",
+ "sha256:310a82ccb092cd650215ab375da8943d235a263af9a029b8ac26a281446c04db",
+ "sha256:36cb91cf4513543a8f0953fed785747ea18b675bc2677f3839889cfca0aac79e"
+ ],
+ "Type": "layers"
+ },
+ "Size": 569919342,
+ "User": "",
+ "Version": "17.06.0-ce",
+ "VirtualSize": 569919342
+ }
+ ]
+"""
+
+import json
+
+from ansible.module_utils.basic import AnsibleModule
+
+
+def image_exists(module, executable, name):
+ command = [executable, 'image', 'exists', name]
+ rc, out, err = module.run_command(command)
+ if rc == 1:
+ return False
+ elif 'Command "exists" not found' in err:
+ # The 'exists' test is available in podman >= 0.12.1
+ command = [executable, 'image', 'ls', '-q', name]
+ rc2, out2, err2 = module.run_command(command)
+ if rc2 != 0:
+ return False
+ return True
+
+
+def filter_invalid_names(module, executable, name):
+ valid_names = []
+ names = name
+ if not isinstance(name, list):
+ names = [name]
+
+ for name in names:
+ if image_exists(module, executable, name):
+ valid_names.append(name)
+
+ return valid_names
+
+
+def get_image_info(module, executable, name):
+ names = name
+ if not isinstance(name, list):
+ names = [name]
+
+ if len(names) > 0:
+ command = [executable, 'image', 'inspect']
+ command.extend(names)
+ rc, out, err = module.run_command(command)
+
+ if rc != 0:
+ module.fail_json(msg="Unable to gather info for '{0}': {1}".format(', '.join(names), err))
+ return out
+
+ else:
+ return json.dumps([])
+
+
+def get_all_image_info(module, executable):
+ command = [executable, 'image', 'ls', '-q']
+ rc, out, err = module.run_command(command)
+ name = out.strip().split('\n')
+ out = get_image_info(module, executable, name)
+
+ return out
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ executable=dict(type='str', default='podman'),
+ name=dict(type='list', elements='str')
+ ),
+ supports_check_mode=True,
+ )
+
+ executable = module.params['executable']
+ name = module.params.get('name')
+ executable = module.get_bin_path(executable, required=True)
+
+ if name:
+ valid_names = filter_invalid_names(module, executable, name)
+ results = json.loads(get_image_info(module, executable, valid_names))
+ else:
+ results = json.loads(get_all_image_info(module, executable))
+
+ results = dict(
+ changed=False,
+ images=results
+ )
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_login_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_login_info.py
new file mode 100644
index 00000000..0ff72e43
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/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/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_logout.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_logout.py
new file mode 100644
index 00000000..35627e8e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_logout.py
@@ -0,0 +1,154 @@
+#!/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_logout
+author:
+ - "Clemens Lange (@clelange)"
+short_description: Log out of a container registry using podman
+notes: []
+description:
+ - Log out of a container registry server using the podman logout command
+ by deleting the cached credentials stored in the `auth.json` file.
+ If the registry is not specified, the first registry under
+ `[registries.search]` from `registries.conf `will be used. The path of
+ the authentication file can be overridden by the user by setting the
+ `authfile` flag. The default path used is
+ `${XDG_RUNTIME_DIR}/containers/auth.json`.
+ All the cached credentials can be removed by setting the `all` flag.
+ Warning - podman will use credentials in `${HOME}/.docker/config.json`
+ to authenticate in case they are not found in the default `authfile`.
+ However, the logout command will only removed credentials in the
+ `authfile` specified.
+requirements:
+ - "Podman installed on host"
+options:
+ registry:
+ description:
+ - Registry server. If the registry is not specified,
+ the first registry under `[registries.search]` from
+ `registries.conf` will be used.
+ type: str
+ authfile:
+ description:
+ - Path of the authentication file. Default is
+ ``${XDG_RUNTIME_DIR}/containers/auth.json``
+ 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
+ all:
+ description:
+ - Remove the cached credentials for all registries in the auth file.
+ type: bool
+ ignore_docker_credentials:
+ description:
+ - Credentials created using other tools such as `docker login` are not
+ removed unless the corresponding `authfile` is explicitly specified.
+ Since podman also uses existing credentials in these files by default
+ (for docker e.g. `${HOME}/.docker/config.json`), module execution will
+ fail if a docker login exists for the registry specified in any
+ `authfile` is used by podman. This can be ignored by setting
+ `ignore_docker_credentials` to `yes` - the credentials will be kept and
+ `changed` will be false.
+ This option cannot be used together with `all` since in this case
+ podman will not check for existing `authfiles` created by other tools.
+ type: bool
+ 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: Log out of default registry
+ podman_logout:
+
+- name: Log out of quay.io
+ podman_logout:
+ registry: quay.io
+
+- name: Log out of all registries in auth file
+ podman_logout:
+ all: yes
+
+- name: Log out of all registries in specified auth file
+ podman_logout:
+ authfile: $HOME/.docker/config.json
+ all: yes
+"""
+# noqa: F402
+
+import json # noqa: F402
+from ansible.module_utils.basic import AnsibleModule
+
+
+def logout(module, executable, registry, authfile, all_registries, ignore_docker_credentials):
+ command = [executable, 'logout']
+ changed = False
+ if authfile:
+ command.extend(['--authfile', authfile])
+ if registry:
+ command.append(registry)
+ if all_registries:
+ command.append("--all")
+ rc, out, err = module.run_command(command)
+ if rc != 0:
+ if 'Error: Not logged into' not in err:
+ module.fail_json(msg="Unable to gather info for %s: %s" % (registry, err))
+ else:
+ # If the command is successful, we managed to log out
+ # Mind: This also applied if --all flag is used, while in this case
+ # there is no check whether one has been logged into any registry
+ changed = True
+ if 'Existing credentials were established via' in out:
+ # The command will return successfully but not log out the user if the
+ # credentials were initially created using docker. Catch this behaviour:
+ if not ignore_docker_credentials:
+ module.fail_json(msg="Unable to log out of %s: %s" % (registry, out))
+ else:
+ changed = False
+ return changed, out, err
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ executable=dict(type='str', default='podman'),
+ registry=dict(type='str'),
+ authfile=dict(type='path'),
+ all=dict(type='bool'),
+ ignore_docker_credentials=dict(type='bool'),
+ ),
+ supports_check_mode=True,
+ mutually_exclusive=(
+ ['registry', 'all'],
+ ['ignore_docker_credentials', 'all'],
+ ),
+ )
+
+ registry = module.params['registry']
+ authfile = module.params['authfile']
+ all_registries = module.params['all']
+ ignore_docker_credentials = module.params['ignore_docker_credentials']
+ executable = module.get_bin_path(module.params['executable'], required=True)
+
+ changed, out, err = logout(module, executable, registry, authfile,
+ all_registries, ignore_docker_credentials)
+
+ results = {
+ "changed": changed,
+ "stdout": out,
+ "stderr": err,
+ }
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network.py
new file mode 100644
index 00000000..590b4690
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network.py
@@ -0,0 +1,614 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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_network
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.0.0'
+short_description: Manage podman networks
+notes: []
+description:
+ - Manage podman networks with podman network command.
+requirements:
+ - podman
+options:
+ name:
+ description:
+ - Name of the network
+ type: str
+ required: True
+ 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
+ disable_dns:
+ description:
+ - disable dns plugin (default "false")
+ type: bool
+ driver:
+ description:
+ - Driver to manage the network (default "bridge")
+ type: str
+ gateway:
+ description:
+ - IPv4 or IPv6 gateway for the subnet
+ type: str
+ internal:
+ description:
+ - Restrict external access from this network (default "false")
+ type: bool
+ ip_range:
+ description:
+ - Allocate container IP from range
+ type: str
+ ipv6:
+ description:
+ - Enable IPv6 (Dual Stack) networking. You must pass a IPv6 subnet.
+ The subnet option must be used with the ipv6 option.
+ type: bool
+ subnet:
+ description:
+ - Subnet in CIDR format
+ type: str
+ macvlan:
+ description:
+ - Create a Macvlan connection based on this device
+ type: str
+ opt:
+ description:
+ - Add network options. Currently 'vlan' and 'mtu' are supported.
+ type: dict
+ suboptions:
+ mtu:
+ description:
+ - MTU size for bridge network interface.
+ type: int
+ required: false
+ vlan:
+ description:
+ - VLAN tag for bridge which enables vlan_filtering.
+ type: int
+ required: false
+ debug:
+ description:
+ - Return additional information which can be helpful for investigations.
+ type: bool
+ default: False
+ state:
+ description:
+ - State of network, default 'present'
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+ recreate:
+ description:
+ - Recreate network even if exists.
+ type: bool
+ default: false
+"""
+
+EXAMPLES = r"""
+- name: Create a podman network
+ containers.podman.podman_network:
+ name: podman_network
+ become: true
+
+- name: Create internal podman network
+ containers.podman.podman_network:
+ name: podman_internal
+ internal: true
+ ip_range: 192.168.22.128/25
+ subnet: 192.168.22.0/24
+ gateway: 192.168.22.1
+ become: true
+"""
+
+RETURN = r"""
+network:
+ description: Facts from created or updated networks
+ returned: always
+ type: list
+ sample: [
+ {
+ "cniVersion": "0.4.0",
+ "name": "podman",
+ "plugins": [
+ {
+ "bridge": "cni-podman0",
+ "ipMasq": true,
+ "ipam": {
+ "ranges": [
+ [
+ {
+ "gateway": "10.88.0.1",
+ "subnet": "10.88.0.0/16"
+ }
+ ]
+ ],
+ "routes": [
+ {
+ "dst": "0.0.0.0/0"
+ }
+ ],
+ "type": "host-local"
+ },
+ "isGateway": true,
+ "type": "bridge"
+ },
+ {
+ "capabilities": {
+ "portMappings": true
+ },
+ "type": "portmap"
+ },
+ {
+ "backend": "iptables",
+ "type": "firewall"
+ }
+ ]
+ }
+ ]
+"""
+
+import json # noqa: F402
+from distutils.version import LooseVersion # noqa: F402
+import os # noqa: F402
+
+from ansible.module_utils.basic import AnsibleModule # noqa: F402
+from ansible.module_utils._text import to_bytes, to_native # noqa: F402
+
+from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
+
+
+class PodmanNetworkModuleParams:
+ """Creates list of arguments for podman CLI command.
+
+ Arguments:
+ action {str} -- action type from 'create', 'delete'
+ params {dict} -- dictionary of module parameters
+
+ """
+
+ def __init__(self, action, params, podman_version, module):
+ self.params = params
+ self.action = action
+ self.podman_version = podman_version
+ self.module = module
+
+ def construct_command_from_params(self):
+ """Create a podman command from given module parameters.
+
+ Returns:
+ list -- list of byte strings for Popen command
+ """
+ if self.action in ['delete']:
+ return self._simple_action()
+ if self.action in ['create']:
+ return self._create_action()
+
+ def _simple_action(self):
+ if self.action == 'delete':
+ cmd = ['rm', '-f', self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def _create_action(self):
+ cmd = [self.action, self.params['name']]
+ all_param_methods = [func for func in dir(self)
+ if callable(getattr(self, func))
+ and func.startswith("addparam")]
+ params_set = (i for i in self.params if self.params[i] is not None)
+ for param in params_set:
+ func_name = "_".join(["addparam", param])
+ if func_name in all_param_methods:
+ cmd = getattr(self, func_name)(cmd)
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def check_version(self, param, minv=None, maxv=None):
+ if minv and LooseVersion(minv) > LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported from podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+ if maxv and LooseVersion(maxv) < LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported till podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+
+ def addparam_gateway(self, c):
+ return c + ['--gateway', self.params['gateway']]
+
+ def addparam_driver(self, c):
+ return c + ['--driver', self.params['driver']]
+
+ def addparam_subnet(self, c):
+ return c + ['--subnet', self.params['subnet']]
+
+ def addparam_ip_range(self, c):
+ return c + ['--ip-range', self.params['ip_range']]
+
+ def addparam_ipv6(self, c):
+ return c + ['--ipv6']
+
+ def addparam_macvlan(self, c):
+ return c + ['--macvlan', self.params['macvlan']]
+
+ def addparam_internal(self, c):
+ return c + ['--internal=%s' % self.params['internal']]
+
+ def addparam_opt(self, c):
+ for opt in self.params['opt'].items():
+ c += ['--opt',
+ b"=".join([to_bytes(k, errors='surrogate_or_strict')
+ for k in opt])]
+ return c
+
+ def addparam_disable_dns(self, c):
+ return c + ['--disable-dns=%s' % self.params['disable_dns']]
+
+
+class PodmanNetworkDefaults:
+ def __init__(self, module, podman_version):
+ self.module = module
+ self.version = podman_version
+ self.defaults = {
+ 'driver': 'bridge',
+ 'disable_dns': False,
+ 'internal': False,
+ }
+
+ def default_dict(self):
+ # make here any changes to self.defaults related to podman version
+ return self.defaults
+
+
+class PodmanNetworkDiff:
+ def __init__(self, module, info, podman_version):
+ self.module = module
+ self.version = podman_version
+ self.default_dict = None
+ self.info = lower_keys(info)
+ self.params = self.defaultize()
+ self.diff = {'before': {}, 'after': {}}
+ self.non_idempotent = {}
+
+ def defaultize(self):
+ params_with_defaults = {}
+ self.default_dict = PodmanNetworkDefaults(
+ self.module, self.version).default_dict()
+ for p in self.module.params:
+ if self.module.params[p] is None and p in self.default_dict:
+ params_with_defaults[p] = self.default_dict[p]
+ else:
+ params_with_defaults[p] = self.module.params[p]
+ return params_with_defaults
+
+ def _diff_update_and_compare(self, param_name, before, after):
+ if before != after:
+ self.diff['before'].update({param_name: before})
+ self.diff['after'].update({param_name: after})
+ return True
+ return False
+
+ def diffparam_disable_dns(self):
+ dns_installed = False
+ for f in [
+ '/usr/libexec/cni/dnsname',
+ '/usr/lib/cni/dnsname',
+ '/opt/cni/bin/dnsname',
+ '/opt/bridge/bin/dnsname'
+ ]:
+ if os.path.exists(f):
+ dns_installed = True
+ before = not bool(
+ [k for k in self.info['plugins'] if 'domainname' in k])
+ after = self.params['disable_dns']
+ # If dnsname plugin is not installed, default is disable_dns=True
+ if not dns_installed and self.module.params['disable_dns'] is None:
+ after = True
+ return self._diff_update_and_compare('disable_dns', before, after)
+
+ def diffparam_driver(self):
+ # Currently only bridge is supported
+ before = after = 'bridge'
+ return self._diff_update_and_compare('driver', before, after)
+
+ def diffparam_gateway(self):
+ try:
+ before = self.info['plugins'][0]['ipam']['ranges'][0][0]['gateway']
+ except (IndexError, KeyError):
+ before = ''
+ after = before
+ if self.params['gateway'] is not None:
+ after = self.params['gateway']
+ return self._diff_update_and_compare('gateway', before, after)
+
+ def diffparam_internal(self):
+ try:
+ before = not self.info['plugins'][0]['isgateway']
+ except (IndexError, KeyError):
+ before = False
+ after = self.params['internal']
+ return self._diff_update_and_compare('internal', before, after)
+
+ def diffparam_ip_range(self):
+ # TODO(sshnaidm): implement IP to CIDR convert and vice versa
+ before = after = ''
+ return self._diff_update_and_compare('ip_range', before, after)
+
+ def diffparam_subnet(self):
+ try:
+ before = self.info['plugins'][0]['ipam']['ranges'][0][0]['subnet']
+ except (IndexError, KeyError):
+ before = ''
+ after = before
+ if self.params['subnet'] is not None:
+ after = self.params['subnet']
+ return self._diff_update_and_compare('subnet', before, after)
+
+ def diffparam_macvlan(self):
+ before = after = ''
+ return self._diff_update_and_compare('macvlan', before, after)
+
+ def diffparam_opt(self):
+ vlan_before = self.info['plugins'][0].get('vlan')
+ vlan_after = self.params['opt'].get('vlan') if self.params['opt'] else None
+ if vlan_before or vlan_after:
+ before, after = {'vlan': vlan_before}, {'vlan': vlan_after}
+ else:
+ before, after = {}, {}
+ mtu_before = self.info['plugins'][0].get('mtu')
+ mtu_after = self.params['opt'].get('mtu') if self.params['opt'] else None
+ if mtu_before or mtu_after:
+ before.update({'mtu': mtu_before})
+ after.update({'mtu': mtu_after})
+ return self._diff_update_and_compare('opt', before, after)
+
+ def is_different(self):
+ diff_func_list = [func for func in dir(self)
+ if callable(getattr(self, func)) and func.startswith(
+ "diffparam")]
+ fail_fast = not bool(self.module._diff)
+ different = False
+ for func_name in diff_func_list:
+ dff_func = getattr(self, func_name)
+ if dff_func():
+ if fail_fast:
+ return True
+ different = True
+ # Check non idempotent parameters
+ for p in self.non_idempotent:
+ if self.module.params[p] is not None and self.module.params[p] not in [{}, [], '']:
+ different = True
+ return different
+
+
+class PodmanNetwork:
+ """Perform network tasks.
+
+ Manages podman network, inspects it and checks its current state
+ """
+
+ def __init__(self, module, name):
+ """Initialize PodmanNetwork class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ name {str} -- name of network
+ """
+
+ super(PodmanNetwork, self).__init__()
+ self.module = module
+ self.name = name
+ self.stdout, self.stderr = '', ''
+ self.info = self.get_info()
+ self.version = self._get_podman_version()
+ self.diff = {}
+ self.actions = []
+
+ @property
+ def exists(self):
+ """Check if network exists."""
+ return bool(self.info != {})
+
+ @property
+ def different(self):
+ """Check if network is different."""
+ diffcheck = PodmanNetworkDiff(
+ self.module,
+ self.info,
+ self.version)
+ is_different = diffcheck.is_different()
+ diffs = diffcheck.diff
+ if self.module._diff and is_different and diffs['before'] and diffs['after']:
+ self.diff['before'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['before'].items())]) + "\n"
+ self.diff['after'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['after'].items())]) + "\n"
+ return is_different
+
+ def get_info(self):
+ """Inspect network and gather info about it."""
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'network', b'inspect', self.name])
+ return json.loads(out)[0] if rc == 0 else {}
+
+ def _get_podman_version(self):
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'--version'])
+ if rc != 0 or not out or "version" not in out:
+ self.module.fail_json(msg="%s run failed!" %
+ self.module.params['executable'])
+ return out.split("version")[1].strip()
+
+ def _perform_action(self, action):
+ """Perform action with network.
+
+ Arguments:
+ action {str} -- action to perform - create, stop, delete
+ """
+ b_command = PodmanNetworkModuleParams(action,
+ self.module.params,
+ self.version,
+ self.module,
+ ).construct_command_from_params()
+ full_cmd = " ".join([self.module.params['executable'], 'network']
+ + [to_native(i) for i in b_command])
+ self.module.log("PODMAN-NETWORK-DEBUG: %s" % full_cmd)
+ self.actions.append(full_cmd)
+ if not self.module.check_mode:
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'network'] + b_command,
+ expand_user_and_vars=False)
+ self.stdout = out
+ self.stderr = err
+ if rc != 0:
+ self.module.fail_json(
+ msg="Can't %s network %s" % (action, self.name),
+ stdout=out, stderr=err)
+
+ def delete(self):
+ """Delete the network."""
+ self._perform_action('delete')
+
+ def create(self):
+ """Create the network."""
+ self._perform_action('create')
+
+ def recreate(self):
+ """Recreate the network."""
+ self.delete()
+ self.create()
+
+
+class PodmanNetworkManager:
+ """Module manager class.
+
+ Defines according to parameters what actions should be applied to network
+ """
+
+ def __init__(self, module):
+ """Initialize PodmanManager class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ """
+
+ super(PodmanNetworkManager, self).__init__()
+
+ self.module = module
+ self.results = {
+ 'changed': False,
+ 'actions': [],
+ 'network': {},
+ }
+ self.name = self.module.params['name']
+ self.executable = \
+ self.module.get_bin_path(self.module.params['executable'],
+ required=True)
+ self.state = self.module.params['state']
+ self.recreate = self.module.params['recreate']
+ self.network = PodmanNetwork(self.module, self.name)
+
+ def update_network_result(self, changed=True):
+ """Inspect the current network, update results with last info, exit.
+
+ Keyword Arguments:
+ changed {bool} -- whether any action was performed
+ (default: {True})
+ """
+ facts = self.network.get_info() if changed else self.network.info
+ out, err = self.network.stdout, self.network.stderr
+ self.results.update({'changed': changed, 'network': facts,
+ 'podman_actions': self.network.actions},
+ stdout=out, stderr=err)
+ if self.network.diff:
+ self.results.update({'diff': self.network.diff})
+ if self.module.params['debug']:
+ self.results.update({'podman_version': self.network.version})
+ self.module.exit_json(**self.results)
+
+ def execute(self):
+ """Execute the desired action according to map of actions & states."""
+ states_map = {
+ 'present': self.make_present,
+ 'absent': self.make_absent,
+ }
+ process_action = states_map[self.state]
+ process_action()
+ self.module.fail_json(msg="Unexpected logic error happened, "
+ "please contact maintainers ASAP!")
+
+ def make_present(self):
+ """Run actions if desired state is 'started'."""
+ if not self.network.exists:
+ self.network.create()
+ self.results['actions'].append('created %s' % self.network.name)
+ self.update_network_result()
+ elif self.recreate or self.network.different:
+ self.network.recreate()
+ self.results['actions'].append('recreated %s' %
+ self.network.name)
+ self.update_network_result()
+ else:
+ self.update_network_result(changed=False)
+
+ def make_absent(self):
+ """Run actions if desired state is 'absent'."""
+ if not self.network.exists:
+ self.results.update({'changed': False})
+ elif self.network.exists:
+ self.network.delete()
+ self.results['actions'].append('deleted %s' % self.network.name)
+ self.results.update({'changed': True})
+ self.results.update({'network': {},
+ 'podman_actions': self.network.actions})
+ self.module.exit_json(**self.results)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ state=dict(type='str', default="present",
+ choices=['present', 'absent']),
+ name=dict(type='str', required=True),
+ disable_dns=dict(type='bool', required=False),
+ driver=dict(type='str', required=False),
+ gateway=dict(type='str', required=False),
+ internal=dict(type='bool', required=False),
+ ip_range=dict(type='str', required=False),
+ ipv6=dict(type='bool', required=False),
+ subnet=dict(type='str', required=False),
+ macvlan=dict(type='str', required=False),
+ opt=dict(type='dict', required=False,
+ options=dict(
+ mtu=dict(type='int', required=False),
+ vlan=dict(type='int', required=False))),
+ executable=dict(type='str', required=False, default='podman'),
+ debug=dict(type='bool', default=False),
+ recreate=dict(type='bool', default=False),
+ ),
+ required_by=dict( # for IP range and GW to set 'subnet' is required
+ ip_range=('subnet'),
+ gateway=('subnet'),
+ ))
+
+ PodmanNetworkManager(module).execute()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network_info.py
new file mode 100644
index 00000000..a9e18cd4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_network_info.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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_network_info
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.0.0'
+short_description: Gather info about podman networks
+notes: []
+description:
+ - Gather info about podman networks with podman inspect command.
+requirements:
+ - "Podman installed on host"
+options:
+ name:
+ description:
+ - Name of the network
+ type: str
+ 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: Gather info about all present networks
+ containers.podman.podman_network_info:
+
+- name: Gather info about specific network
+ containers.podman.podman_network_info:
+ name: podman
+"""
+
+RETURN = r"""
+networks:
+ description: Facts from all or specified networks
+ returned: always
+ type: list
+ sample: [
+ {
+ "cniVersion": "0.4.0",
+ "name": "podman",
+ "plugins": [
+ {
+ "bridge": "cni-podman0",
+ "ipMasq": true,
+ "ipam": {
+ "ranges": [
+ [
+ {
+ "gateway": "10.88.0.1",
+ "subnet": "10.88.0.0/16"
+ }
+ ]
+ ],
+ "routes": [
+ {
+ "dst": "0.0.0.0/0"
+ }
+ ],
+ "type": "host-local"
+ },
+ "isGateway": true,
+ "type": "bridge"
+ },
+ {
+ "capabilities": {
+ "portMappings": true
+ },
+ "type": "portmap"
+ },
+ {
+ "backend": "iptables",
+ "type": "firewall"
+ }
+ ]
+ }
+ ]
+"""
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+def get_network_info(module, executable, name):
+ command = [executable, 'network', 'inspect']
+ if not name:
+ all_names = [executable, 'network', 'ls', '-q']
+ rc, out, err = module.run_command(all_names)
+ if rc != 0:
+ module.fail_json(msg="Unable to get list of networks: %s" % err)
+ name = out.split()
+ if not name:
+ return [], out, err
+ command += name
+ else:
+ command.append(name)
+ rc, out, err = module.run_command(command)
+ if rc != 0 or 'unable to find network configuration' in err:
+ module.fail_json(msg="Unable to gather info for %s: %s" % (name, err))
+ if not out or json.loads(out) is None:
+ return [], out, err
+ return json.loads(out), out, err
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ executable=dict(type='str', default='podman'),
+ name=dict(type='str')
+ ),
+ supports_check_mode=True,
+ )
+
+ name = module.params['name']
+ executable = module.get_bin_path(module.params['executable'], required=True)
+
+ inspect_results, out, err = get_network_info(module, executable, name)
+
+ results = {
+ "changed": False,
+ "networks": inspect_results,
+ "stderr": err
+ }
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod.py
new file mode 100644
index 00000000..01dbc627
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod.py
@@ -0,0 +1,232 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# flake8: noqa: E501
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = '''
+---
+module: podman_pod
+short_description: Manage Podman pods
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.0.0'
+description:
+ - Manage podman pods.
+options:
+ state:
+ description:
+ - This variable is set for state
+ type: str
+ default: created
+ choices:
+ - created
+ - killed
+ - restarted
+ - absent
+ - started
+ - stopped
+ - paused
+ - unpaused
+ recreate:
+ description:
+ - Use with present and started states to force the re-creation of an
+ existing pod.
+ type: bool
+ default: False
+ add_host:
+ description:
+ - Add a host to the /etc/hosts file shared between all containers in the pod.
+ type: list
+ elements: str
+ required: false
+ cgroup_parent:
+ description:
+ - Path to cgroups under which the cgroup for the pod will be created. If the path
+ is not absolute, he path is considered to be relative to the cgroups path of the
+ init process. Cgroups will be created if they do not already exist.
+ type: str
+ required: false
+ dns:
+ description:
+ - Set custom DNS servers in the /etc/resolv.conf file that will be shared between
+ all containers in the pod. A special option, "none" is allowed which disables
+ creation of /etc/resolv.conf for the pod.
+ type: list
+ elements: str
+ required: false
+ dns_opt:
+ description:
+ - Set custom DNS options in the /etc/resolv.conf file that will be shared between
+ all containers in the pod.
+ type: list
+ elements: str
+ required: false
+ dns_search:
+ description:
+ - Set custom DNS search domains in the /etc/resolv.conf file that will be shared
+ between all containers in the pod.
+ type: list
+ elements: str
+ required: false
+ hostname:
+ description:
+ - Set a hostname to the pod
+ type: str
+ required: false
+ infra:
+ description:
+ - Create an infra container and associate it with the pod. An infra container is
+ a lightweight container used to coordinate the shared kernel namespace of a pod.
+ Default is true.
+ type: bool
+ required: false
+ infra_conmon_pidfile:
+ description:
+ - Write the pid of the infra container's conmon process to a file. As conmon runs
+ in a separate process than Podman, this is necessary when using systemd to manage
+ Podman containers and pods.
+ type: str
+ required: false
+ infra_command:
+ description:
+ - The command that will be run to start the infra container. Default is "/pause".
+ type: str
+ required: false
+ infra_image:
+ description:
+ - The image that will be created for the infra container. Default is "k8s.gcr.io/pause:3.1".
+ type: str
+ required: false
+ ip:
+ description:
+ - Set a static IP for the pod's shared network.
+ type: str
+ required: false
+ label:
+ description:
+ - Add metadata to a pod, pass dictionary of label keys and values.
+ type: dict
+ required: false
+ label_file:
+ description:
+ - Read in a line delimited file of labels.
+ type: str
+ required: false
+ mac_address:
+ description:
+ - Set a static MAC address for the pod's shared network.
+ type: str
+ required: false
+ name:
+ description:
+ - Assign a name to the pod.
+ type: str
+ required: true
+ network:
+ description:
+ - Set network mode for the pod. Supported values are bridge (the default), host
+ (do not create a network namespace, all containers in the pod will use the host's
+ network), or a comma-separated list of the names of CNI networks the pod should
+ join.
+ type: str
+ required: false
+ no_hosts:
+ description:
+ - Disable creation of /etc/hosts for the pod.
+ type: bool
+ required: false
+ pod_id_file:
+ description:
+ - Write the pod ID to the file.
+ type: str
+ required: false
+ publish:
+ description:
+ - Publish a port or range of ports from the pod to the host.
+ type: list
+ elements: str
+ required: false
+ aliases:
+ - ports
+ share:
+ description:
+ - A comma delimited list of kernel namespaces to share. If none or "" is specified,
+ no namespaces will be shared. The namespaces to choose from are ipc, net, pid,
+ user, uts.
+ type: str
+ required: false
+ 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
+ debug:
+ description:
+ - Return additional information which can be helpful for investigations.
+ type: bool
+ default: False
+
+requirements:
+ - "podman"
+
+'''
+
+RETURN = '''
+pod:
+ description: Pod inspection results for the given pod
+ built.
+ returned: always
+ type: dict
+ sample:
+ Config:
+ cgroupParent: /libpod_parent
+ created: '2020-06-14T15:16:12.230818767+03:00'
+ hostname: newpod
+ id: a5a5c6cdf8c72272fc5c33f787e8d7501e2fa0c1e92b2b602860defdafeeec58
+ infraConfig:
+ infraPortBindings: null
+ makeInfraContainer: true
+ labels: {}
+ lockID: 515
+ name: newpod
+ sharesCgroup: true
+ sharesIpc: true
+ sharesNet: true
+ sharesUts: true
+ Containers:
+ - id: dc70a947c7ae15198ec38b3c817587584085dee3919cbeb9969e3ab77ba10fd2
+ state: configured
+ State:
+ cgroupPath: /libpod_parent/a5a5c6cdf8c72272fc5c33f787e8d7501e2fa0c1e92b2b602860defdafeeec58
+ infraContainerID: dc70a947c7ae15198ec38b3c817587584085dee3919cbeb9969e3ab77ba10fd2
+ status: Created
+
+'''
+
+EXAMPLES = '''
+# What modules does for example
+- podman_pod:
+ name: pod1
+ state: started
+ ports:
+ - 4444:5555
+'''
+from ansible.module_utils.basic import AnsibleModule # noqa: F402
+from ..module_utils.podman.podman_pod_lib import PodmanPodManager # noqa: F402
+from ..module_utils.podman.podman_pod_lib import ARGUMENTS_SPEC_POD # noqa: F402
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=ARGUMENTS_SPEC_POD
+ )
+ results = PodmanPodManager(module, module.params).execute()
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod_info.py
new file mode 100644
index 00000000..c02e503c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_pod_info.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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_pod_info
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.0.0'
+short_description: Gather info about podman pods
+notes: []
+description:
+ - Gather info about podman pods with podman inspect command.
+requirements:
+ - "Podman installed on host"
+options:
+ name:
+ description:
+ - Name of the pod
+ type: str
+ 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: Gather info about all present pods
+ containers.podman.podman_pod_info:
+
+- name: Gather info about specific pods
+ containers.podman.podman_pod_info:
+ name: special_pod
+"""
+
+RETURN = r"""
+pods:
+ description: Facts from all or specified pods
+ returned: always
+ type: list
+ sample: [
+ {
+ "Config": {
+ "id": "d9cb6dbb0....",
+ "name": "pod1",
+ "hostname": "pod1host",
+ "labels": {
+ },
+ "cgroupParent": "/libpod_parent",
+ "sharesCgroup": true,
+ "sharesIpc": true,
+ "sharesNet": true,
+ "sharesUts": true,
+ "infraConfig": {
+ "makeInfraContainer": true,
+ "infraPortBindings": [
+ {
+ "hostPort": 7777,
+ "containerPort": 7111,
+ "protocol": "tcp",
+ "hostIP": ""
+ }
+ ]
+ },
+ "created": "2020-07-13T20:29:12.572282186+03:00",
+ "lockID": 682
+ },
+ "State": {
+ "cgroupPath": "/libpod_parent/d9cb6dbb0....",
+ "infraContainerID": "ad46737bf....",
+ "status": "Created"
+ },
+ "Containers": [
+ {
+ "id": "ad46737bf....",
+ "state": "configured"
+ }
+ ]
+ }
+ ]
+"""
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+def get_pod_info(module, executable, name):
+ command = [executable, 'pod', 'inspect']
+ pods = [name]
+ result = []
+ errs = []
+ rcs = []
+ if not name:
+ all_names = [executable, 'pod', 'ls', '-q']
+ rc, out, err = module.run_command(all_names)
+ if rc != 0:
+ module.fail_json(msg="Unable to get list of pods: %s" % err)
+ name = out.split()
+ if not name:
+ return [], out, err
+ pods = name
+ for pod in pods:
+ rc, out, err = module.run_command(command + [pod])
+ errs.append(err.strip())
+ rcs += [rc]
+ if not out or json.loads(out) is None:
+ continue
+ result.append(json.loads(out))
+ return result, errs, rcs
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ executable=dict(type='str', default='podman'),
+ name=dict(type='str')
+ ),
+ supports_check_mode=True,
+ )
+
+ name = module.params['name']
+ executable = module.get_bin_path(module.params['executable'], required=True)
+
+ inspect_results, errs, rcs = get_pod_info(module, executable, name)
+
+ if len(rcs) > 1 and 0 not in rcs:
+ module.fail_json(msg="Failed to inspect pods", stderr="\n".join(errs))
+
+ results = {
+ "changed": False,
+ "pods": inspect_results,
+ "stderr": "\n".join(errs),
+ }
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume.py
new file mode 100644
index 00000000..d74e39d3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume.py
@@ -0,0 +1,477 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# flake8: noqa: E501
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+DOCUMENTATION = '''
+---
+module: podman_volume
+short_description: Manage Podman volumes
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+version_added: '1.1.0'
+description:
+ - Manage Podman volumes
+options:
+ state:
+ description:
+ - State of volume, default 'present'
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+ recreate:
+ description:
+ - Recreate volume even if exists.
+ type: bool
+ default: false
+ name:
+ description:
+ - Name of volume.
+ type: str
+ required: true
+ label:
+ description:
+ - Add metadata to a pod volume (e.g., label com.example.key=value).
+ type: dict
+ required: false
+ driver:
+ description:
+ - Specify volume driver name (default local).
+ type: str
+ required: false
+ options:
+ description:
+ - Set driver specific options. For example 'device=tpmfs', 'type=tmpfs'.
+ type: list
+ elements: str
+ required: false
+ 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
+ debug:
+ description:
+ - Return additional information which can be helpful for investigations.
+ type: bool
+ default: False
+
+requirements:
+ - "podman"
+
+'''
+
+RETURN = '''
+volume:
+ description: Volume inspection results if exists.
+ returned: always
+ type: dict
+ sample:
+ CreatedAt: '2020-06-05T16:38:55.277628769+03:00'
+ Driver: local
+ Labels:
+ key.com: value
+ key.org: value2
+ Mountpoint: /home/user/.local/share/containers/storage/volumes/test/_data
+ Name: test
+ Options: {}
+ Scope: local
+
+'''
+
+EXAMPLES = '''
+# What modules does for example
+- podman_volume:
+ state: present
+ name: volume1
+ label:
+ key: value
+ key2: value2
+ options:
+ - "device=/dev/loop1"
+ - "type=ext4"
+'''
+# noqa: F402
+import json # noqa: F402
+from distutils.version import LooseVersion # noqa: F402
+
+from ansible.module_utils.basic import AnsibleModule # noqa: F402
+from ansible.module_utils._text import to_bytes, to_native # noqa: F402
+
+from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
+
+
+class PodmanVolumeModuleParams:
+ """Creates list of arguments for podman CLI command.
+
+ Arguments:
+ action {str} -- action type from 'create', 'delete'
+ params {dict} -- dictionary of module parameters
+
+ """
+
+ def __init__(self, action, params, podman_version, module):
+ self.params = params
+ self.action = action
+ self.podman_version = podman_version
+ self.module = module
+
+ def construct_command_from_params(self):
+ """Create a podman command from given module parameters.
+
+ Returns:
+ list -- list of byte strings for Popen command
+ """
+ if self.action in ['delete']:
+ return self._simple_action()
+ if self.action in ['create']:
+ return self._create_action()
+
+ def _simple_action(self):
+ if self.action == 'delete':
+ cmd = ['rm', '-f', self.params['name']]
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def _create_action(self):
+ cmd = [self.action, self.params['name']]
+ all_param_methods = [func for func in dir(self)
+ if callable(getattr(self, func))
+ and func.startswith("addparam")]
+ params_set = (i for i in self.params if self.params[i] is not None)
+ for param in params_set:
+ func_name = "_".join(["addparam", param])
+ if func_name in all_param_methods:
+ cmd = getattr(self, func_name)(cmd)
+ return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
+
+ def check_version(self, param, minv=None, maxv=None):
+ if minv and LooseVersion(minv) > LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported from podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+ if maxv and LooseVersion(maxv) < LooseVersion(
+ self.podman_version):
+ self.module.fail_json(msg="Parameter %s is supported till podman "
+ "version %s only! Current version is %s" % (
+ param, minv, self.podman_version))
+
+ def addparam_label(self, c):
+ for label in self.params['label'].items():
+ c += ['--label', b'='.join(
+ [to_bytes(l, errors='surrogate_or_strict') for l in label])]
+ return c
+
+ def addparam_driver(self, c):
+ return c + ['--driver', self.params['driver']]
+
+ def addparam_options(self, c):
+ for opt in self.params['options']:
+ c += ['--opt', opt]
+ return c
+
+
+class PodmanVolumeDefaults:
+ def __init__(self, module, podman_version):
+ self.module = module
+ self.version = podman_version
+ self.defaults = {
+ 'driver': 'local',
+ 'label': {},
+ 'options': {}
+ }
+
+ def default_dict(self):
+ # make here any changes to self.defaults related to podman version
+ return self.defaults
+
+
+class PodmanVolumeDiff:
+ def __init__(self, module, info, podman_version):
+ self.module = module
+ self.version = podman_version
+ self.default_dict = None
+ self.info = lower_keys(info)
+ self.params = self.defaultize()
+ self.diff = {'before': {}, 'after': {}}
+ self.non_idempotent = {}
+
+ def defaultize(self):
+ params_with_defaults = {}
+ self.default_dict = PodmanVolumeDefaults(
+ self.module, self.version).default_dict()
+ for p in self.module.params:
+ if self.module.params[p] is None and p in self.default_dict:
+ params_with_defaults[p] = self.default_dict[p]
+ else:
+ params_with_defaults[p] = self.module.params[p]
+ return params_with_defaults
+
+ def _diff_update_and_compare(self, param_name, before, after):
+ if before != after:
+ self.diff['before'].update({param_name: before})
+ self.diff['after'].update({param_name: after})
+ return True
+ return False
+
+ def diffparam_label(self):
+ before = self.info['labels'] if 'labels' in self.info else {}
+ after = self.params['label']
+ return self._diff_update_and_compare('label', before, after)
+
+ def diffparam_driver(self):
+ before = self.info['driver']
+ after = self.params['driver']
+ return self._diff_update_and_compare('driver', before, after)
+
+ def diffparam_options(self):
+ before = self.info['options'] if 'options' in self.info else {}
+ before = ["=".join((k, v)) for k, v in before.items()]
+ after = self.params['options']
+ # Gor UID, GID
+ ids = []
+ if self.info['uid']:
+ before += ['uid=%s' % str(self.info['uid'])]
+ if self.info['gid']:
+ before += ['gid=%s' % str(self.info['gid'])]
+ if self.params['options']:
+ for opt in self.params['options']:
+ if 'uid=' in opt or 'gid=' in opt:
+ ids += opt.split("o=")[1].split(",")
+ after = [i for i in after if 'gid' not in i and 'uid' not in i]
+ after += ids
+ before, after = sorted(list(set(before))), sorted(list(set(after)))
+ return self._diff_update_and_compare('options', before, after)
+
+ def is_different(self):
+ diff_func_list = [func for func in dir(self)
+ if callable(getattr(self, func)) and func.startswith(
+ "diffparam")]
+ fail_fast = not bool(self.module._diff)
+ different = False
+ for func_name in diff_func_list:
+ dff_func = getattr(self, func_name)
+ if dff_func():
+ if fail_fast:
+ return True
+ else:
+ different = True
+ # Check non idempotent parameters
+ for p in self.non_idempotent:
+ if self.module.params[p] is not None and self.module.params[p] not in [{}, [], '']:
+ different = True
+ return different
+
+
+class PodmanVolume:
+ """Perform volume tasks.
+
+ Manages podman volume, inspects it and checks its current state
+ """
+
+ def __init__(self, module, name):
+ """Initialize PodmanVolume class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ name {str} -- name of volume
+ """
+
+ super(PodmanVolume, self).__init__()
+ self.module = module
+ self.name = name
+ self.stdout, self.stderr = '', ''
+ self.info = self.get_info()
+ self.version = self._get_podman_version()
+ self.diff = {}
+ self.actions = []
+
+ @property
+ def exists(self):
+ """Check if volume exists."""
+ return bool(self.info != {})
+
+ @property
+ def different(self):
+ """Check if volume is different."""
+ diffcheck = PodmanVolumeDiff(
+ self.module,
+ self.info,
+ self.version)
+ is_different = diffcheck.is_different()
+ diffs = diffcheck.diff
+ if self.module._diff and is_different and diffs['before'] and diffs['after']:
+ self.diff['before'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['before'].items())]) + "\n"
+ self.diff['after'] = "\n".join(
+ ["%s - %s" % (k, v) for k, v in sorted(
+ diffs['after'].items())]) + "\n"
+ return is_different
+
+ def get_info(self):
+ """Inspect volume and gather info about it."""
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'volume', b'inspect', self.name])
+ return json.loads(out)[0] if rc == 0 else {}
+
+ def _get_podman_version(self):
+ # pylint: disable=unused-variable
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'--version'])
+ if rc != 0 or not out or "version" not in out:
+ self.module.fail_json(msg="%s run failed!" %
+ self.module.params['executable'])
+ return out.split("version")[1].strip()
+
+ def _perform_action(self, action):
+ """Perform action with volume.
+
+ Arguments:
+ action {str} -- action to perform - create, stop, delete
+ """
+ b_command = PodmanVolumeModuleParams(action,
+ self.module.params,
+ self.version,
+ self.module,
+ ).construct_command_from_params()
+ full_cmd = " ".join([self.module.params['executable'], 'volume']
+ + [to_native(i) for i in b_command])
+ self.module.log("PODMAN-VOLUME-DEBUG: %s" % full_cmd)
+ self.actions.append(full_cmd)
+ if not self.module.check_mode:
+ rc, out, err = self.module.run_command(
+ [self.module.params['executable'], b'volume'] + b_command,
+ expand_user_and_vars=False)
+ self.stdout = out
+ self.stderr = err
+ if rc != 0:
+ self.module.fail_json(
+ msg="Can't %s volume %s" % (action, self.name),
+ stdout=out, stderr=err)
+
+ def delete(self):
+ """Delete the volume."""
+ self._perform_action('delete')
+
+ def create(self):
+ """Create the volume."""
+ self._perform_action('create')
+
+ def recreate(self):
+ """Recreate the volume."""
+ self.delete()
+ self.create()
+
+
+class PodmanVolumeManager:
+ """Module manager class.
+
+ Defines according to parameters what actions should be applied to volume
+ """
+
+ def __init__(self, module):
+ """Initialize PodmanManager class.
+
+ Arguments:
+ module {obj} -- ansible module object
+ """
+
+ super(PodmanVolumeManager, self).__init__()
+
+ self.module = module
+ self.results = {
+ 'changed': False,
+ 'actions': [],
+ 'volume': {},
+ }
+ self.name = self.module.params['name']
+ self.executable = \
+ self.module.get_bin_path(self.module.params['executable'],
+ required=True)
+ self.state = self.module.params['state']
+ self.recreate = self.module.params['recreate']
+ self.volume = PodmanVolume(self.module, self.name)
+
+ def update_volume_result(self, changed=True):
+ """Inspect the current volume, update results with last info, exit.
+
+ Keyword Arguments:
+ changed {bool} -- whether any action was performed
+ (default: {True})
+ """
+ facts = self.volume.get_info() if changed else self.volume.info
+ out, err = self.volume.stdout, self.volume.stderr
+ self.results.update({'changed': changed, 'volume': facts,
+ 'podman_actions': self.volume.actions},
+ stdout=out, stderr=err)
+ if self.volume.diff:
+ self.results.update({'diff': self.volume.diff})
+ if self.module.params['debug']:
+ self.results.update({'podman_version': self.volume.version})
+ self.module.exit_json(**self.results)
+
+ def execute(self):
+ """Execute the desired action according to map of actions & states."""
+ states_map = {
+ 'present': self.make_present,
+ 'absent': self.make_absent,
+ }
+ process_action = states_map[self.state]
+ process_action()
+ self.module.fail_json(msg="Unexpected logic error happened, "
+ "please contact maintainers ASAP!")
+
+ def make_present(self):
+ """Run actions if desired state is 'started'."""
+ if not self.volume.exists:
+ self.volume.create()
+ self.results['actions'].append('created %s' % self.volume.name)
+ self.update_volume_result()
+ elif self.recreate or self.volume.different:
+ self.volume.recreate()
+ self.results['actions'].append('recreated %s' %
+ self.volume.name)
+ self.update_volume_result()
+ else:
+ self.update_volume_result(changed=False)
+
+ def make_absent(self):
+ """Run actions if desired state is 'absent'."""
+ if not self.volume.exists:
+ self.results.update({'changed': False})
+ elif self.volume.exists:
+ self.volume.delete()
+ self.results['actions'].append('deleted %s' % self.volume.name)
+ self.results.update({'changed': True})
+ self.results.update({'volume': {},
+ 'podman_actions': self.volume.actions})
+ self.module.exit_json(**self.results)
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ state=dict(type='str', default="present",
+ choices=['present', 'absent']),
+ name=dict(type='str', required=True),
+ label=dict(type='dict', required=False),
+ driver=dict(type='str', required=False),
+ options=dict(type='list', elements='str', required=False),
+ recreate=dict(type='bool', default=False),
+ executable=dict(type='str', required=False, default='podman'),
+ debug=dict(type='bool', default=False),
+ ))
+
+ PodmanVolumeManager(module).execute()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume_info.py b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume_info.py
new file mode 100644
index 00000000..97b43b3c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/plugins/modules/podman_volume_info.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+# Copyright (c) 2020 Red Hat
+# 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_volume_info
+author:
+ - "Sagi Shnaidman (@sshnaidm)"
+short_description: Gather info about podman volumes
+notes: []
+description:
+ - Gather info about podman volumes with podman inspect command.
+requirements:
+ - "Podman installed on host"
+options:
+ name:
+ description:
+ - Name of the volume
+ type: str
+ 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: Gather info about all present volumes
+ podman_volume_info:
+
+- name: Gather info about specific volume
+ podman_volume_info:
+ name: specific_volume
+"""
+
+RETURN = r"""
+volumes:
+ description: Facts from all or specified volumes
+ returned: always
+ type: list
+ sample: [
+ {
+ "name": "testvolume",
+ "labels": {},
+ "mountPoint": "/home/ansible/.local/share/testvolume/_data",
+ "driver": "local",
+ "options": {},
+ "scope": "local"
+ }
+ ]
+"""
+
+import json
+from ansible.module_utils.basic import AnsibleModule
+
+
+def get_volume_info(module, executable, name):
+ command = [executable, 'volume', 'inspect']
+ if name:
+ command.append(name)
+ else:
+ command.append("--all")
+ rc, out, err = module.run_command(command)
+ if rc != 0 or 'no such volume' in err:
+ module.fail_json(msg="Unable to gather info for %s: %s" % (name or 'all volumes', err))
+ if not out or json.loads(out) is None:
+ return [], out, err
+ return json.loads(out), out, err
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ executable=dict(type='str', default='podman'),
+ name=dict(type='str')
+ ),
+ supports_check_mode=True,
+ )
+
+ name = module.params['name']
+ executable = module.get_bin_path(module.params['executable'], required=True)
+
+ inspect_results, out, err = get_volume_info(module, executable, name)
+
+ results = {
+ "changed": False,
+ "volumes": inspect_results,
+ "stderr": err
+ }
+
+ module.exit_json(**results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/collections-debian-merged/ansible_collections/containers/podman/setup.cfg b/collections-debian-merged/ansible_collections/containers/podman/setup.cfg
new file mode 100644
index 00000000..def4acc9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/setup.cfg
@@ -0,0 +1,38 @@
+[metadata]
+name = ansible-podman-collections.containers
+summary = Ansible collections for Podman
+description-file =
+ README.md
+
+author = Sagi Shnaidman (@sshnaidm)
+author-email = einarum@gmail.com
+home-page = https://github.com/containers/ansible-podman-collections/
+classifier =
+ License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
+ Development Status :: 5 - Production/Stable
+ Intended Audience :: Developers
+ Intended Audience :: System Administrators
+ Intended Audience :: Information Technology
+ Topic :: System :: Systems Administration
+ Topic :: Utilities
+
+[global]
+setup-hooks =
+ pbr.hooks.setup_hook
+
+[files]
+data_files =
+ share/ansible/collections/ansible_collections/containers/podman/ = README.md
+ share/ansible/collections/ansible_collections/containers/podman/roles/ = roles/*
+ share/ansible/collections/ansible_collections/containers/podman/plugins/ = plugins/*
+ share/ansible/collections/ansible_collections/containers/podman/playbooks/ = playbooks/*
+ share/ansible/collections/ansible_collections/containers/podman/scripts/ = scripts/*
+ share/ansible/collections/ansible_collections/containers/podman/docs/ = docs/*
+ share/ansible/collections/ansible_collections/containers/podman/meta/ = meta/*
+
+[wheel]
+universal = 1
+
+[pbr]
+skip_authors = True
+skip_changelog = True
diff --git a/collections-debian-merged/ansible_collections/containers/podman/setup.py b/collections-debian-merged/ansible_collections/containers/podman/setup.py
new file mode 100644
index 00000000..d6d2ea1b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/setup.py
@@ -0,0 +1,8 @@
+# Copyright Red Hat, Inc. All Rights Reserved.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+import setuptools
+
+setuptools.setup(
+ setup_requires=['pbr'],
+ pbr=True)
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/.gitignore b/collections-debian-merged/ansible_collections/containers/podman/tests/.gitignore
new file mode 100644
index 00000000..ea1472ec
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/.gitignore
@@ -0,0 +1 @@
+output/
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/__init__.py b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/__init__.py
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml
new file mode 100644
index 00000000..21699422
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection/test_connection.yml
@@ -0,0 +1,43 @@
+- hosts: "{{ target_hosts }}"
+ gather_facts: no
+ serial: 1
+ tasks:
+
+ ### raw with unicode arg and output
+
+ - name: raw with unicode arg and output
+ raw: echo 汉语
+ register: command
+ - name: check output of raw with unicode arg and output
+ assert:
+ that:
+ - "'汉语' in command.stdout"
+ - command is changed # as of 2.2, raw should default to changed: true for consistency w/ shell/command/script modules
+
+ ### copy local file with unicode filename and content
+
+ - name: create local file with unicode filename and content
+ local_action: lineinfile dest={{ local_tmp }}-汉语/汉语.txt create=true line=汉语
+ - name: remove remote file with unicode filename and content
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语/汉语.txt state=absent"
+ - name: create remote directory with unicode name
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=directory"
+ - name: copy local file with unicode filename and content
+ action: "{{ action_prefix }}copy src={{ local_tmp }}-汉语/汉语.txt dest={{ remote_tmp }}-汉语/汉语.txt"
+
+ ### fetch remote file with unicode filename and content
+
+ - name: remove local file with unicode filename and content
+ local_action: file path={{ local_tmp }}-汉语/汉语.txt state=absent
+ - name: fetch remote file with unicode filename and content
+ fetch: src={{ remote_tmp }}-汉语/汉语.txt dest={{ local_tmp }}-汉语/汉语.txt fail_on_missing=true validate_checksum=true flat=true
+
+ ### remove local and remote temp files
+
+ - name: remove local temp file
+ local_action: file path={{ local_tmp }}-汉语 state=absent
+ - name: remove remote temp file
+ action: "{{ action_prefix }}file path={{ remote_tmp }}-汉语 state=absent"
+
+ ### test wait_for_connection plugin
+ - wait_for_connection:
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh
new file mode 100755
index 00000000..8da6526b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/runme.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+set -o pipefail
+set -eux
+
+function run_ansible {
+ ${SUDO:-} ${ANSIBLECMD:-ansible-playbook} ../connection/test_connection.yml -i "test_connection.inventory" \
+ -e target_hosts="buildah" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
+
+}
+
+# First run as root
+run_ansible "$@"
+
+# Create a normal user
+${SUDO:-} ansible all -i "test_connection.inventory" -m "user" -a 'name="testuser"'
+
+# Second run as normal user
+ANSIBLE_VERBOSITY=4 ANSIBLE_REMOTE_USER="testuser" run_ansible "$@" | tee check_log
+${SUDO:-} grep -q "Using buildah connection from collection" check_log
+${SUDO:-} rm -f check_log
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory
new file mode 100644
index 00000000..e6d090ee
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_buildah/test_connection.inventory
@@ -0,0 +1,12 @@
+[buildah]
+buildah-container ansible_ssh_pipelining=true
+[buildah:vars]
+# 1. install buildah
+# 2. create container:
+# $ sudo buildah from --name=buildah-container python:2
+# 3. run test:
+# $ ansible-test integration connection_buildah
+# 6. remove container
+# $ sudo buildah rm buildah-container
+ansible_host=buildah-container
+ansible_connection=containers.podman.buildah
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh
new file mode 100755
index 00000000..eda49cf5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/runme.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+set -o pipefail
+set -eux
+
+function run_ansible {
+ ${SUDO:-} ${ANSIBLECMD:-ansible-playbook} ../connection/test_connection.yml -i "test_connection.inventory" \
+ -e target_hosts="podman" \
+ -e action_prefix= \
+ -e local_tmp=/tmp/ansible-local \
+ -e remote_tmp=/tmp/ansible-remote \
+ "$@"
+
+}
+
+run_ansible "$@"
+LC_ALL=C LANG=C run_ansible "$@"
+ANSIBLE_VERBOSITY=4 ANSIBLE_REMOTE_TMP="/tmp" ANSIBLE_REMOTE_USER="1000" run_ansible "$@" | tee check_log
+${SUDO:-} grep -q "Using podman connection from collection" check_log
+${SUDO:-} rm -f check_log
+set +o pipefail
+ANSIBLE_PODMAN_EXECUTABLE=fakepodman run_ansible "$@" 2>&1 | grep "fakepodman command not found in PATH"
+set -o pipefail
+ANSIBLE_PODMAN_EXECUTABLE=fakepodman run_ansible "$@" && {
+ echo "Playbook with fakepodman should fail!"
+ exit 1
+}
+ANSIBLE_VERBOSITY=4 ANSIBLE_PODMAN_EXTRA_ARGS=" --log-level debug " run_ansible "$@" | grep "level=debug msg="
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory
new file mode 100644
index 00000000..c64c399f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/connection_podman/test_connection.inventory
@@ -0,0 +1,15 @@
+[podman]
+podman-container
+[podman:vars]
+# 1. install podman
+# 2. create container:
+# podman pull python:3-alpine
+# podman run -d --name podman-container python:3-alpine sleep 999999
+# 3. run test:
+# ./bin/ansible-test integration connection_podman
+# 6. remove container
+# podman stop podman-container
+# podman rm podman-container
+ansible_host=podman-container
+ansible_connection=containers.podman.podman
+ansible_python_interpreter=/usr/local/bin/python
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml
new file mode 100644
index 00000000..edd721c7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container/tasks/main.yml
@@ -0,0 +1,462 @@
+- name: Test podman_container
+ block:
+ - name: Delete all container leftovers from tests
+ containers.podman.podman_container:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "alpine:3.7"
+ - "container"
+ - "container2"
+
+ - name: Test no image with default action
+ containers.podman.podman_container:
+ name: container
+ ignore_errors: true
+ register: no_image
+
+ - name: Test no image with state 'started'
+ containers.podman.podman_container:
+ name: container
+ state: started
+ ignore_errors: true
+ register: no_image1
+
+ - name: Test no image with state 'present'
+ containers.podman.podman_container:
+ name: container
+ state: present
+ ignore_errors: true
+ register: no_image2
+
+ - name: Check no image
+ assert:
+ that:
+ - no_image is failed
+ - no_image1 is failed
+ - no_image2 is failed
+ - no_image.msg == "State 'started' required image to be configured!"
+ - no_image1.msg == "State 'started' required image to be configured!"
+ - no_image2.msg == "State 'present' required image to be configured!"
+ fail_msg: No image test failed!
+ success_msg: No image test passed!
+
+ - name: Ensure image doesn't exist
+ containers.podman.podman_image:
+ name: alpine:3.7
+ state: absent
+
+ - name: Check pulling image
+ containers.podman.podman_container:
+ name: container
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ register: image
+
+ - name: Check using already pulled image
+ containers.podman.podman_container:
+ name: container2
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ register: image2
+
+ - name: Check output is correct
+ assert:
+ that:
+ - image is changed
+ - image.container is defined
+ - image.container['State']['Running']
+ - "'pulled image alpine:3.7' in image.actions"
+ - "'started container' in image.actions"
+ - image2 is changed
+ - image2.container is defined
+ - image2.container['State']['Running']
+ - "'pulled image alpine:3.7' not in image2.actions"
+ - "'started container2' in image2.actions"
+ fail_msg: Pulling image test failed!
+ success_msg: Pulling image test passed!
+
+ - name: Check failed image pull
+ containers.podman.podman_container:
+ name: container
+ image: ineverneverneverexist
+ state: present
+ command: sleep 1d
+ register: imagefail
+ ignore_errors: true
+
+ - name: Check output is correct
+ assert:
+ that:
+ - imagefail is failed
+ - imagefail.msg == "Can't pull image ineverneverneverexist"
+
+
+ - name: Force container recreate
+ containers.podman.podman_container:
+ name: container
+ image: alpine
+ state: present
+ command: sleep 1d
+ recreate: true
+ register: recreated
+
+ - name: Check output is correct
+ assert:
+ that:
+ - recreated is changed
+ - recreated.container is defined
+ - recreated.container['State']['Running']
+ - "'recreated container' in recreated.actions"
+ fail_msg: Force recreate test failed!
+ success_msg: Force recreate test passed!
+
+ - name: Stop container
+ containers.podman.podman_container:
+ name: container
+ state: stopped
+ register: stopped
+
+ - name: Stop the same container again (idempotency)
+ containers.podman.podman_container:
+ name: container
+ state: stopped
+ register: stopped_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - stopped is changed
+ - stopped.container is defined
+ - not stopped.container['State']['Running']
+ - "'stopped container' in stopped.actions"
+ - stopped_again is not changed
+ - stopped_again.container is defined
+ - not stopped_again.container['State']['Running']
+ - stopped_again.actions == []
+ fail_msg: Stopping container test failed!
+ success_msg: Stopping container test passed!
+
+ - name: Delete stopped container
+ containers.podman.podman_container:
+ name: container
+ state: absent
+ register: deleted
+
+ - name: Delete again container (idempotency)
+ containers.podman.podman_container:
+ name: container
+ state: absent
+ register: deleted_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - deleted is changed
+ - deleted.container is defined
+ - deleted.container == {}
+ - "'deleted container' in deleted.actions"
+ - deleted_again is not changed
+ - deleted_again.container is defined
+ - deleted_again.container == {}
+ - deleted_again.actions == []
+ fail_msg: Deleting stopped container test failed!
+ success_msg: Deleting stopped container test passed!
+
+ - name: Create container, but don't run
+ containers.podman.podman_container:
+ name: container
+ image: alpine:3.7
+ state: stopped
+ command: sleep 1d
+ register: created
+
+ - name: Check output is correct
+ assert:
+ that:
+ - created is changed
+ - created.container is defined
+ - created.container != {}
+ - not created.container['State']['Running']
+ - "'created container' in created.actions"
+ fail_msg: "Creating stopped container test failed!"
+ success_msg: "Creating stopped container test passed!"
+
+ - name: Delete created container
+ containers.podman.podman_container:
+ name: container
+ state: absent
+
+ - name: Start container that was deleted
+ containers.podman.podman_container:
+ name: container
+ image: alpine:3.7
+ state: started
+ command: sleep 1d
+ register: started
+
+ - name: Check output is correct
+ assert:
+ that:
+ - started is changed
+ - started.container is defined
+ - started.container['State']['Running']
+ - "'pulled image alpine:3.7' not in started.actions"
+
+ - name: Delete started container
+ containers.podman.podman_container:
+ name: container
+ state: absent
+ register: deleted
+
+ - name: Delete again container (idempotency)
+ containers.podman.podman_container:
+ name: container
+ state: absent
+ register: deleted_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - deleted is changed
+ - deleted.container is defined
+ - deleted.container == {}
+ - "'deleted container' in deleted.actions"
+ - deleted_again is not changed
+ - deleted_again.container is defined
+ - deleted_again.container == {}
+ - deleted_again.actions == []
+ fail_msg: Deleting started container test failed!
+ success_msg: Deleting started container test passed!
+
+ - name: Recreate container with parameters
+ containers.podman.podman_container:
+ name: container
+ image: docker.io/alpine:3.7
+ state: started
+ command: sleep 1d
+ recreate: true
+ etc_hosts:
+ host1: 127.0.0.1
+ host2: 127.0.0.1
+ annotation:
+ this: "annotation_value"
+ dns:
+ - 1.1.1.1
+ - 8.8.4.4
+ dns_search: example.com
+ cap_add:
+ - SYS_TIME
+ - NET_ADMIN
+ publish:
+ - "9000:80"
+ - "9001:8000"
+ workdir: "/bin"
+ env:
+ FOO: bar=1
+ BAR: foo
+ TEST: 1
+ BOOL: false
+ label:
+ somelabel: labelvalue
+ otheralbe: othervalue
+ volumes:
+ - /tmp:/data
+ register: test
+
+ - name: Check output is correct
+ assert:
+ that:
+ - test is changed
+ - test.container is defined
+ - test.container != {}
+ - test.container['State']['Running']
+ # test capabilities
+ - "'CAP_SYS_TIME' in test.container['BoundingCaps']"
+ - "'CAP_NET_ADMIN' in test.container['BoundingCaps']"
+ # test annotations
+ - test.container['Config']['Annotations']['this'] is defined
+ - test.container['Config']['Annotations']['this'] == "annotation_value"
+ # test DNS
+ - >-
+ (test.container['HostConfig']['Dns'] is defined and
+ test.container['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or
+ (test.container['HostConfig']['DNS'] is defined and
+ test.container['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4'])
+ # test ports
+ - test.container['NetworkSettings']['Ports']|length == 2
+ # test working dir
+ - test.container['Config']['WorkingDir'] == "/bin"
+ # test dns search
+ - >-
+ (test.container['HostConfig']['DnsSearch'] is defined and
+ test.container['HostConfig']['DnsSearch'] == ['example.com']) or
+ (test.container['HostConfig']['DNSSearch'] is defined and
+ test.container['HostConfig']['DNSSearch'] == ['example.com'])
+ # test environment variables
+ - "'FOO=bar=1' in test.container['Config']['Env']"
+ - "'BAR=foo' in test.container['Config']['Env']"
+ - "'TEST=1' in test.container['Config']['Env']"
+ - "'BOOL=False' in test.container['Config']['Env']"
+ # test labels
+ - test.container['Config']['Labels'] | length == 2
+ - test.container['Config']['Labels']['somelabel'] == "labelvalue"
+ - test.container['Config']['Labels']['otheralbe'] == "othervalue"
+ # test mounts
+ - >-
+ (test.container['Mounts'][0]['Destination'] is defined and
+ '/data' in test.container['Mounts'] | map(attribute='Destination') | list) or
+ (test.container['Mounts'][0]['destination'] is defined and
+ '/data' in test.container['Mounts'] | map(attribute='destination') | list)
+ - >-
+ (test.container['Mounts'][0]['Source'] is defined and
+ '/tmp' in test.container['Mounts'] | map(attribute='Source') | list) or
+ (test.container['Mounts'][0]['source'] is defined and
+ '/tmp' in test.container['Mounts'] | map(attribute='source') | list)
+ fail_msg: Parameters container test failed!
+ success_msg: Parameters container test passed!
+
+ - name: Check basic idempotency of running container
+ containers.podman.podman_container:
+ name: testidem
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+
+ - name: Check basic idempotency of running container - run it again
+ containers.podman.podman_container:
+ name: testidem
+ image: alpine:latest
+ state: present
+ command: sleep 20m
+ register: idem
+
+ - name: Check that nothing was changed
+ assert:
+ that:
+ - not idem.changed
+
+ - name: Check force restart option - run again and force restart
+ containers.podman.podman_container:
+ name: testidem
+ image: alpine:latest
+ state: present
+ command: sleep 20m
+ force_restart: true
+ register: idem_r
+
+ - name: Check that task was changed
+ assert:
+ that:
+ - idem_r is changed
+
+ - name: Check removing force_restart option
+ containers.podman.podman_container:
+ name: testidem
+ image: alpine:latest
+ state: present
+ command: sleep 20m
+ register: idem_r1
+
+ - name: Check that task was not changed
+ assert:
+ that:
+ - idem_r1 is not changed
+
+ - name: Run changed container (with tty enabled)
+ containers.podman.podman_container:
+ name: testidem
+ image: alpine
+ state: present
+ command: sleep 20m
+ tty: true
+ register: idem1
+
+ - name: Check that container is recreated when changed
+ assert:
+ that:
+ - idem1 is changed
+
+ - name: Run changed container without specifying an option, use defaults
+ containers.podman.podman_container:
+ name: testidem
+ image: alpine
+ state: present
+ command: sleep 20m
+ register: idem2
+
+ - name: Check that container is recreated when changed to default value
+ assert:
+ that:
+ - idem2 is changed
+
+ - name: Remove container
+ containers.podman.podman_container:
+ name: testidem
+ state: absent
+ register: remove
+
+ - name: Check podman_actions
+ assert:
+ that:
+ - "'podman rm -f testidem' in remove.podman_actions"
+
+ # - name: Create a pod
+ # shell: podman pod create --name testidempod
+
+ - name: Check basic idempotency of pod container
+ containers.podman.podman_container:
+ name: testidem-pod
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ pod: "new:testidempod"
+
+ - name: Check basic idempotency of pod container - run it again
+ containers.podman.podman_container:
+ name: testidem-pod
+ image: alpine:latest
+ state: present
+ command: sleep 20m
+ pod: testidempod
+ register: idem3
+
+ - name: Check that nothing was changed in pod containers
+ assert:
+ that:
+ - not idem3.changed
+
+ - name: Run changed pod container (with tty enabled)
+ containers.podman.podman_container:
+ name: testidem-pod
+ image: alpine
+ state: present
+ command: sleep 20m
+ tty: true
+ pod: testidempod
+ register: idem4
+
+ - name: Check that container is recreated when changed
+ assert:
+ that:
+ - idem4 is changed
+
+ - name: Remove container
+ containers.podman.podman_container:
+ name: testidem-pod
+ state: absent
+
+ always:
+ - name: Delete all container leftovers from tests
+ containers.podman.podman_container:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "alpine:3.7"
+ - "container"
+ - "container2"
+
+ - name: Remove pod
+ shell: podman pod rm -f testidempod
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile
new file mode 100644
index 00000000..8d32e4a3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/Dockerfile
@@ -0,0 +1,32 @@
+FROM alpine
+
+LABEL "key"="amazing value"
+LABEL nobody=cares
+
+ARG build_arg
+
+ENV password root
+ENV username root
+
+WORKDIR /work
+
+RUN adduser -D user && \
+ adduser -D user2
+
+COPY start.sh /start
+
+RUN chmod a+rwx /start
+
+EXPOSE 80
+EXPOSE 8080/tcp
+VOLUME ["/data", "/data2"]
+USER user
+STOPSIGNAL SIGKILL
+
+# problem with OS w/o systemd
+# HEALTHCHECK --interval=5m --timeout=3s \
+# CMD date
+
+CMD ["1d"]
+ENTRYPOINT ["/start"]
+
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh
new file mode 100755
index 00000000..1217239e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/files/start.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+s=${1:-"3h"}
+sleep "$s"
+
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml
new file mode 100644
index 00000000..a9ecb039
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/build_test_container.yml
@@ -0,0 +1,30 @@
+---
+- name: Create directory for user build images
+ file:
+ path: /tmp/usr_img
+ state: directory
+
+- name: Copy files to container build directory
+ copy:
+ src: "{{ item }}"
+ dest: "/tmp/usr_img/{{ item }}"
+ mode: 777
+ loop:
+ - Dockerfile
+ - start.sh
+
+- name: Build test docker image for regular user
+ containers.podman.podman_image:
+ name: "{{ idem_image }}"
+ path: /tmp/usr_img
+ build:
+ format: docker
+ extra_args: --cgroup-manager=cgroupfs
+
+- name: Build test docker image for root user
+ containers.podman.podman_image:
+ name: "{{ idem_image }}"
+ path: /tmp/usr_img
+ build:
+ format: docker
+ become: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml
new file mode 100644
index 00000000..15a4d658
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_all.yml
@@ -0,0 +1,224 @@
+# Other settings
+- name: Remove leftovers from other tests
+ containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- name: Run container
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- name: Run container again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: Check info when running container again
+ assert:
+ that: test1 is not changed
+
+- name: Run container with environment vars
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ env:
+ mykey: "amazing value"
+ ENV1: "one=two=three"
+ command: 1h
+ register: test2
+
+- name: Check info with environment vars
+ assert:
+ that: test2 is changed
+
+- name: Run container with environment vars again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ env:
+ mykey: "amazing value"
+ ENV1: "one=two=three"
+ command: 1h
+ register: test3
+
+- name: Check info with environment vars again
+ assert:
+ that: test3 is not changed
+
+- name: Run container with changed environment vars
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ env:
+ mykey: "amazing value1"
+ ENV1: "one=two=three"
+ command: 1h
+ register: test4
+
+- name: Check info with changed environment vars
+ assert:
+ that: test4 is changed
+
+- name: Run container with log level
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_level: debug
+ command: 1h
+ register: test5
+
+- name: Check info with log level
+ assert:
+ that: test5 is changed
+
+- name: Run container with log level again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_level: debug
+ command: 1h
+ register: test6
+
+- name: Check info with log level again
+ assert:
+ that: test6 is not changed
+
+- name: Run container with changed log level
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_level: error
+ command: 1h
+ register: test7
+
+- name: Check info with changed log level
+ assert:
+ that: test7 is changed
+
+- name: Run container with default log level
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test8
+
+- name: Check info with default log level
+ assert:
+ that: test8 is not changed
+
+- name: Run container with log opt tag
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_opt:
+ tag: nonotag
+ log_driver: journald
+ command: 1h
+ register: test9
+
+- name: Check info with log opt tag
+ assert:
+ that: test9 is changed
+
+- name: Run container with log opt tag - again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_opt:
+ tag: nonotag
+ log_driver: journald
+ command: 1h
+ register: test10
+
+- name: Check info with log opt tag - again
+ assert:
+ that: test10 is not changed
+
+- name: Run container with default log opt tag
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ log_driver: journald
+ register: test11
+
+- name: Check info with default log opt tag
+ assert:
+ that: test11 is changed
+
+- name: Run container with log opt path
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_opt:
+ path: /tmp/container.log
+ log_driver: journald
+ command: 1h
+ register: test12
+
+- name: Check info with log opt path
+ assert:
+ that: test12 is changed
+
+- name: Run container with changed log opt path
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_opt:
+ path: /tmp/container2.log
+ log_driver: journald
+ command: 1h
+ register: test13
+
+- name: Check info with changed log opt path
+ assert:
+ that: test13 is changed
+
+- name: Run container with default log opt path
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_driver: journald
+ command: 1h
+ register: test14
+
+# We can't guess the default log path
+- name: Check info with default log opt path
+ assert:
+ that: test14 is not changed
+
+- name: Run container with all log-opts
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ log_driver: journald
+ log_opt:
+ path: /tmp/container3.log
+ max_size: 100mb
+ tag: sometag
+ command: 1h
+
+- name: Remove test container
+ containers.podman.podman_container:
+ name: idempotency
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml
new file mode 100644
index 00000000..b7627fc7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_labels.yml
@@ -0,0 +1,179 @@
+# Labels
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ label:
+ key: "amazing value"
+ nobody: "cares"
+ command: 1h
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ label:
+ haha: kukuku
+ llala: wiwiwiw
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ label:
+ haha: kukuku
+ llala: wiwiwiw
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ label:
+ test: notest
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ label:
+ key: "amazing value"
+ nobody: "cares"
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ label:
+ razraz: dva
+ command: sleep 1h
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml
new file mode 100644
index 00000000..5a21aac4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_networks.yml
@@ -0,0 +1,40 @@
+- name: Remove container netcontainer
+ containers.podman.podman_container:
+ name: netcontainer
+ state: absent
+
+- name: Run container with {{ item.first_net }}
+ containers.podman.podman_container:
+ name: netcontainer
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: "{{ item.first_net }}"
+
+- name: Run container again with {{ item.first_net }}
+ containers.podman.podman_container:
+ name: netcontainer
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: "{{ item.first_net }}"
+ register: info
+
+- name: Check info for 2 runs of {{ item.first_net }}
+ assert:
+ that:
+ - info is not changed
+
+- name: Run changed container with {{ item.next_net }}
+ containers.podman.podman_container:
+ name: netcontainer
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: "{{ item.next_net }}"
+ register: info1
+
+- name: Check info
+ assert:
+ that:
+ - info1 is changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml
new file mode 100644
index 00000000..aae118e1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_pods.yml
@@ -0,0 +1,75 @@
+- name: Remove testing pod
+ containers.podman.podman_pod:
+ name: testpod
+ state: absent
+
+- name: Remove test container
+ containers.podman.podman_container:
+ name: testpod_container1
+ state: absent
+
+- name: Create pod
+ containers.podman.podman_pod:
+ name: testpod
+ publish:
+ - "11111:11111"
+
+- name: Start test container
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: testpod_container1
+ pod: testpod
+ state: started
+ label:
+ key: value
+ env:
+ test: test2
+ volumes:
+ - /tmp:/data
+
+- name: Start test container again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: testpod_container1
+ pod: testpod
+ state: started
+ label:
+ key: value
+ env:
+ test: test2
+ volumes:
+ - /tmp:/data
+ register: info
+
+- name: Check starting container
+ assert:
+ that: info is not changed
+
+- name: Start test container changed
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: testpod_container1
+ pod: testpod
+ state: started
+ register: info1
+
+- name: Check starting container changed
+ assert:
+ that: info1 is changed
+
+- name: Start test container again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: testpod_container1
+ pod: testpod
+ state: started
+ register: info2
+
+- name: Check starting container again
+ assert:
+ that: info2 is not changed
+
+- name: Remove testing pod
+ containers.podman.podman_pod:
+ name: testpod
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml
new file mode 100644
index 00000000..9e029b80
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_ports.yml
@@ -0,0 +1,240 @@
+# Ports
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ ports:
+ - "4444:4444/tcp"
+ - "1212:5555"
+ - "8888:19191/udp"
+ - "1900:1900/udp"
+ - "127.0.0.1:7671:7676/udp"
+ - "127.0.0.1:12122:8876/udp"
+ - "127.0.0.1:13122:8871/tcp"
+ - "127.0.0.1:43423:8872"
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ ports:
+ - "4444:4444/tcp"
+ - "1212:5555"
+ - "8888:19191/udp"
+ - "1900:1900/udp"
+ - "127.0.0.1:7671:7676/udp"
+ - "127.0.0.1:12122:8876/udp"
+ - "127.0.0.1:13122:8871/tcp"
+ - "127.0.0.1:43423:8872"
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ publish_all: true
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ publish_all: true
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ ports:
+ - 10000:8080
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ ports:
+ - 10001:8080
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ ports:
+ - 10001:8080/tcp
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ ports:
+ - 10001:8080/tcp
+ publish_all: false
+ command: 1h
+ register: test9a
+
+- name: check test9a
+ assert:
+ that: test9a is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9b
+
+- name: check test9b
+ assert:
+ that: test9b is changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ publish_all: false
+ command: sleep 1h
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ publish_all: true
+ command: sleep 1h
+ register: test11a
+
+- name: check test11a
+ assert:
+ that: test11a is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ ports:
+ - 10000:8080
+ command: sleep 1h
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test14
+
+- name: check test14
+ assert:
+ that: test14 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml
new file mode 100644
index 00000000..c4b2ded5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_stopsignal.yml
@@ -0,0 +1,204 @@
+# Stop signal
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 9
+ command: 1h
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 10
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 10
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 15
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 9
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ stop_signal: 15
+ command: 1h
+ register: test9a
+
+- name: check test9a
+ assert:
+ that: test9a is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9b
+
+- name: check test9b
+ assert:
+ that: test9b is changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ stop_signal: 15
+ command: sleep 1h
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ stop_signal: 10
+ command: sleep 1h
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test14
+
+- name: check test14
+ assert:
+ that: test14 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml
new file mode 100644
index 00000000..ad1f103a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_users.yml
@@ -0,0 +1,169 @@
+# Users
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ user: user
+ command: 1h
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ user: user2
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ user: user2
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ user: user2
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ user: user
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ user: nobody
+ command: sleep 1h
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml
new file mode 100644
index 00000000..475e4494
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_volumes.yml
@@ -0,0 +1,234 @@
+# Volumes
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ volumes:
+ - /opt:/somedir
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ volumes:
+ - /opt/://somedir
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ volumes:
+ - /opt:/somedir
+ - /data
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ volumes:
+ - /data
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- name: Create volumes
+ shell: |
+ podman volume inspect local_volume1 || podman volume create local_volume1
+ podman volume inspect local_volume2 || podman volume create local_volume2
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ volumes:
+ - "/opt:/anotherdir"
+ - "local_volume1:/data"
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ volumes:
+ - "/opt//:/anotherdir"
+ - "local_volume1:/data/"
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ volumes:
+ - "/opt:/anotherdir"
+ - "local_volume2:/data"
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ volumes:
+ - "/opt:/anotherdir"
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is not changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test14
+
+- name: check test14
+ assert:
+ that: test14 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ volumes:
+ - /opt:/data
+ command: sleep 1h
+ register: test15
+
+- name: check test15
+ assert:
+ that: test15 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test16
+
+- name: check test16
+ assert:
+ that: test16 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test17
+
+- name: check test17
+ assert:
+ that: test17 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml
new file mode 100644
index 00000000..b6d0fa35
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/idem_workdir.yml
@@ -0,0 +1,204 @@
+# Workdir
+- containers.podman.podman_container:
+ name: idempotency
+ state: absent
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test1
+
+- name: check test1
+ assert:
+ that: test1 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /work
+ command: 1h
+ register: test2
+
+- name: check test2
+ assert:
+ that: test2 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test3
+
+- name: check test3
+ assert:
+ that: test3 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /app
+ command: 1h
+ register: test4
+
+- name: check test4
+ assert:
+ that: test4 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /app
+ command: 1h
+ register: test5
+
+- name: check test5
+ assert:
+ that: test5 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test6
+
+- name: check test6
+ assert:
+ that: test6 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /app
+ command: 1h
+ register: test7
+
+- name: check test7
+ assert:
+ that: test7 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /work
+ command: 1h
+ register: test8
+
+- name: check test8
+ assert:
+ that: test8 is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9
+
+- name: check test9
+ assert:
+ that: test9 is not changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ workdir: /
+ command: 1h
+ register: test9a
+
+- name: check test9a
+ assert:
+ that: test9a is changed
+
+- containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: idempotency
+ state: present
+ command: 1h
+ register: test9b
+
+- name: check test9b
+ assert:
+ that: test9b is changed
+
+- containers.podman.podman_container:
+ name: idempotency1
+ state: absent
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test10
+
+- name: check test10
+ assert:
+ that: test10 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ workdir: /
+ command: sleep 1h
+ register: test11
+
+- name: check test11
+ assert:
+ that: test11 is not changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ workdir: /app
+ command: sleep 1h
+ register: test12
+
+- name: check test12
+ assert:
+ that: test12 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test13
+
+- name: check test13
+ assert:
+ that: test13 is changed
+
+- containers.podman.podman_container:
+ image: alpine
+ name: idempotency1
+ state: present
+ command: sleep 1h
+ register: test14
+
+- name: check test14
+ assert:
+ that: test14 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml
new file mode 100644
index 00000000..b207f73b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/main.yml
@@ -0,0 +1,46 @@
+---
+- name: Prepare a container
+ include_tasks: build_test_container.yml
+
+- name: Test idempotency of users
+ include_tasks: idem_users.yml
+
+- name: Test idempotency of workdir
+ include_tasks: idem_workdir.yml
+
+- name: Test idempotency of labels
+ include_tasks: idem_labels.yml
+
+- name: Test idempotency of stop signal
+ include_tasks: idem_stopsignal.yml
+
+- name: Test idempotency of ports
+ include_tasks: idem_ports.yml
+
+- name: Test idempotency of volumes
+ include_tasks: idem_volumes.yml
+
+- name: Test idempotency of containers in pods
+ include_tasks: idem_pods.yml
+
+- name: Test idempotency of other settings
+ include_tasks: idem_all.yml
+
+- name: Test idempotency for root containers
+ include_tasks: root-podman.yml
+ vars:
+ ansible_python_interpreter: "/usr/bin/python"
+ args:
+ apply:
+ become: true
+
+- name: Test idempotency for root network containers
+ include_tasks: root-podman-network.yml
+ vars:
+ ansible_python_interpreter: "/usr/bin/python"
+ args:
+ apply:
+ become: true
+
+- name: Test idempotency for root network containers
+ include_tasks: rootless-podman-network.yml
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml
new file mode 100644
index 00000000..bdcbd157
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman-network.yml
@@ -0,0 +1,67 @@
+- name: Test podman rootful container with networks
+ block:
+
+ - name: Remove container
+ containers.podman.podman_container:
+ name: netcontainer
+ state: absent
+
+ - name: Create network testnet
+ command: podman network create testnet --subnet 10.92.92.0/24
+
+ - name: Create network anothernet
+ command: podman network create anothernet --subnet 10.72.72.0/24
+
+ - name: List current networks
+ command: podman network ls
+
+ - name: Set test data
+ set_fact:
+ testdata:
+ - first_net: host
+ next_net: bridge
+ - first_net: bridge
+ next_net: host
+ - first_net: none
+ next_net: host
+ - first_net: host
+ next_net: none
+ - first_net: anothernet
+ next_net: testnet
+ - first_net: testnet
+ next_net:
+ - testnet
+ - anothernet
+ - first_net:
+ - testnet
+ - anothernet
+ next_net: anothernet
+ - first_net:
+ - testnet
+ - anothernet
+ next_net: bridge
+ - first_net:
+ - testnet
+ - anothernet
+ next_net: host
+ - first_net: host
+ next_net: anothernet
+ - first_net: bridge
+ next_net:
+ - anothernet
+ - testnet
+
+ - include_tasks: idem_networks.yml
+ loop: "{{ testdata }}"
+
+ always:
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_container:
+ name: netcontainer
+ state: absent
+
+ - name: Delete all network leftovers from tests
+ shell: |
+ podman network rm -f anothernet
+ podman network rm -f testnet
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml
new file mode 100644
index 00000000..eccc4e89
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/root-podman.yml
@@ -0,0 +1,153 @@
+---
+# Ulimits testing
+- name: Make sure container doesn't exist
+ containers.podman.podman_container:
+ name: root-idempotency
+ state: absent
+
+- name: Run container as is
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+
+- name: Run container as is again
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ register: info_a
+
+- name: Check that it is not recreated
+ assert:
+ that:
+ - info_a is not changed
+
+- name: Run containers with ulimits
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ ulimit:
+ - 'nofile=55535:55535'
+ - 'memlock=-1:-1'
+ register: info
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info is changed
+
+- name: Run containers with ulimits - idempotency
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ ulimit:
+ - 'nofile=55535:55535'
+ - 'memlock=-1:-1'
+ register: info1
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info1 is not changed
+
+- name: Run containers with changed ulimits
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ ulimit:
+ - 'nofile=55535:65535'
+ - 'memlock=-1:-1'
+ register: info2
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info2 is changed
+
+- name: Run containers with changed ulimits - idempotency
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ ulimit:
+ - 'nofile=55535:65535'
+ - 'memlock=-1:-1'
+ register: info3
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info3 is not changed
+
+- name: Run default container
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+
+- name: Run containers with MAC address
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ mac_address: 44:55:66:77:88:99
+ register: info4
+
+- name: Check that it is not recreated
+ assert:
+ that:
+ - info4 is changed
+ - info4.container['NetworkSettings']['MacAddress'] == '44:55:66:77:88:99'
+
+- name: Run containers with MAC address again - idempotency
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ mac_address: 44:55:66:77:88:99
+ register: info5
+
+- name: Check that it is not recreated
+ assert:
+ that:
+ - info5 is not changed
+
+- name: Run containers with MAC address changed
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ mac_address: 44:55:66:77:88:33
+ register: info6
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info6 is changed
+
+- name: Run again default container
+ containers.podman.podman_container:
+ image: "{{ idem_image }}"
+ name: root-idempotency
+ state: present
+ command: 1h
+ register: info7
+
+- name: Check that it is recreated
+ assert:
+ that:
+ - info7 is not changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml
new file mode 100644
index 00000000..2178e522
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_idempotency/tasks/rootless-podman-network.yml
@@ -0,0 +1,103 @@
+- name: Test podman rootful container with networks
+ block:
+
+ - name: Remove container rootlessnet
+ containers.podman.podman_container:
+ name: rootlessnet
+ state: absent
+
+ - name: Run container with no specified networks
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+
+ - name: Run container again with no specified networks
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ register: info
+
+ - name: Check info for no specified networks
+ assert:
+ that:
+ - info is not changed
+
+ - name: Run container with network mode host
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: host
+ register: info1
+
+ - name: Check info with network mode host
+ assert:
+ that:
+ - info1 is changed
+
+ - name: Run container with network mode host again
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: host
+ register: info2
+
+ - name: Check info with network mode host again
+ assert:
+ that:
+ - info2 is not changed
+
+ - name: Run container without network at all
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: none
+ register: info3
+
+ - name: Check info without network at all
+ assert:
+ that:
+ - info3 is changed
+
+ - name: Run container without network at all again
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ network: none
+ register: info4
+
+ - name: Check info without network at all again
+ assert:
+ that:
+ - info4 is not changed
+
+ - name: Run container with default network mode
+ containers.podman.podman_container:
+ name: rootlessnet
+ image: "{{ idem_image }}"
+ command: 1h
+ state: present
+ register: info5
+
+ - name: Check info with default network mode
+ assert:
+ that:
+ - info5 is changed
+
+ always:
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_container:
+ name: rootlessnet
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml
new file mode 100644
index 00000000..7ad1e44c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_container_info/tasks/main.yml
@@ -0,0 +1,88 @@
+- name: Test podman_container_info
+ block:
+
+ - name: Generate random value for container name
+ set_fact:
+ container_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure container doesn't exist
+ command: podman container rm -f {{ container_name }}
+ ignore_errors: true
+
+ - name: Get missing container info
+ containers.podman.podman_container_info:
+ name: "{{ container_name }}"
+ register: nonexist
+
+ - name: Check results of missing container info
+ assert:
+ that:
+ - "'containers' in nonexist"
+ - nonexist is succeeded
+ - nonexist.containers == []
+
+ - name: Get missing multiple container info
+ containers.podman.podman_container_info:
+ name:
+ - "{{ container_name }}"
+ - neverexist
+ - whatever
+ register: nonexist2
+ ignore_errors: true
+
+ - name: Check results of missing multiple container info
+ assert:
+ that:
+ - "'containers' in nonexist2"
+ - nonexist2 is succeeded
+ - nonexist2.containers == []
+
+ - name: Make sure container exists
+ command: podman container run -d --name {{ container_name }} alpine sleep 15m
+
+ - name: Get existing container info
+ containers.podman.podman_container_info:
+ name: "{{ container_name }}"
+ register: existing_container
+
+ - name: Get mixed existing and non-existing container info
+ containers.podman.podman_container_info:
+ name:
+ - "{{ container_name }}"
+ - whatever
+ register: mixed_existing_container
+
+ - name: Get all containers info
+ containers.podman.podman_container_info:
+ register: all_containers
+
+ - name: Dump podman container inspect result
+ debug: var=existing_container
+
+ - name: Comparison with 'podman container inspect'
+ command: podman container inspect "{{ container_name }}"
+ register: podman_inspect
+
+ - name: Convert podman inspect output to JSON
+ set_fact:
+ podman_inspect_result: "{{ podman_inspect.stdout | from_json }}"
+
+ - name: Cleanup
+ command: podman container rm -f {{ container_name }}
+
+ - name: Make checks
+ assert:
+ that:
+ - "'containers' in existing_container"
+ - existing_container.containers
+ - "existing_container.containers == podman_inspect_result"
+ - all_containers.containers == existing_container.containers
+ - "'containers' in mixed_existing_container"
+ - mixed_existing_container.containers
+ - existing_container.containers == mixed_existing_container.containers
+
+ always:
+
+ - name: Cleanup
+ command: podman container rm -f {{ container_name }}
+ ignore_errors: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml
new file mode 100644
index 00000000..2703518c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_containers/tasks/main.yml
@@ -0,0 +1,642 @@
+- name: Test multiple podman_containers
+ block:
+ - name: Delete all containers leftovers from tests
+ containers.podman.podman_containers:
+ containers:
+ - name: "alpine:3.7"
+ state: absent
+ - name: "container"
+ state: absent
+ - name: "container1"
+ state: absent
+ - name: "container2"
+ state: absent
+ - name: "container3"
+ state: absent
+ - name: "container4"
+ state: absent
+ - name: "testidem"
+ state: absent
+ - name: "testidem1"
+ state: absent
+ - name: "testidem2"
+ state: absent
+ - name: "testidem3"
+ state: absent
+ - name: "testidem-pod"
+ state: absent
+ - name: "testidem-pod2"
+ state: absent
+
+ - name: Test no image with default action
+ containers.podman.podman_containers:
+ containers:
+ - name: "container"
+ - name: "container2"
+ - name: "container3"
+ image: alpine
+ ignore_errors: true
+ register: no_image
+
+ - name: Test no image with state 'started'
+ containers.podman.podman_containers:
+ containers:
+ - name: "container"
+ state: started
+ - name: "container2"
+ state: started
+ ignore_errors: true
+ register: no_image1
+
+ - name: Test no image with state 'present'
+ containers.podman.podman_containers:
+ containers:
+ - name: "container"
+ state: present
+ - name: "container2"
+ state: present
+ - name: "container3"
+ state: present
+ image: alpine
+ ignore_errors: true
+ register: no_image2
+
+ - name: Check no image
+ assert:
+ that:
+ - no_image is failed
+ - no_image1 is failed
+ - no_image2 is failed
+ - no_image.msg is search("State 'started' required image to be configured!")
+ - no_image1.msg is search ("State 'started' required image to be configured!")
+ - no_image2.msg is search("State 'present' required image to be configured!")
+ fail_msg: No-image test failed!
+ success_msg: No-image test passed!
+
+ - name: Ensure image doesn't exist
+ containers.podman.podman_image:
+ name: alpine:3.7
+ state: absent
+
+ - name: Check pulling image
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ - name: container1
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ register: image
+
+ - name: Check using already pulled image
+ containers.podman.podman_containers:
+ containers:
+ - name: container1
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ - name: container3
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ register: image2
+
+ - name: Check output is correct
+ assert:
+ that:
+ - image is changed
+ - image.containers[0] is defined
+ - image.containers[0]['State']['Running']
+ - image.containers[1] is defined
+ - image.containers[1]['State']['Running']
+ - "'pulled image alpine:3.7' in image.actions"
+ - "'started container' in image.actions"
+ - "'started container1' in image.actions"
+ - image2 is changed
+ - image2.containers is defined
+ - image2.containers[0]['State']['Running']
+ - image2.containers[1]['State']['Running']
+ - "'pulled image alpine:3.7' not in image2.actions"
+ - "'started container3' in image2.actions"
+ fail_msg: Pulling image test failed!
+ success_msg: Pulling image test passed!
+
+ - name: Check failed image pull
+ containers.podman.podman_containers:
+ containers:
+ - name: container1
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ - name: container
+ image: ineverneverneverexist
+ state: present
+ command: sleep 1d
+ register: imagefail
+ ignore_errors: true
+
+ - name: Check output is correct
+ assert:
+ that:
+ - imagefail is failed
+ - imagefail.msg == "Can't pull image ineverneverneverexist"
+
+ - name: Force containers recreate
+ containers.podman.podman_containers:
+ containers:
+ - name: container1
+ image: alpine:3.7
+ state: present
+ command: sleep 1d
+ - name: container
+ image: alpine
+ state: present
+ command: sleep 1d
+ recreate: true
+ register: recreated
+
+ - name: Check output is correct
+ assert:
+ that:
+ - recreated is changed
+ - recreated.containers is defined
+ - recreated.containers[1]['State']['Running']
+ - "'recreated container' in recreated.actions"
+ fail_msg: Force recreate test failed!
+ success_msg: Force recreate test passed!
+
+ - name: Stop containers
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: stopped
+ - name: container1
+ state: stopped
+ register: stopped
+
+ - name: Stop the same containers again (idempotency)
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: stopped
+ - name: container1
+ state: stopped
+ register: stopped_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - stopped is changed
+ - stopped.containers is defined
+ - not stopped.containers[0]['State']['Running']
+ - not stopped.containers[1]['State']['Running']
+ - "'stopped container' in stopped.actions"
+ - stopped_again is not changed
+ - stopped_again.containers is defined
+ - not stopped_again.containers[0]['State']['Running']
+ - not stopped_again.containers[1]['State']['Running']
+ - stopped_again.actions == []
+ fail_msg: Stopping container test failed!
+ success_msg: Stopping container test passed!
+
+ - name: Delete stopped containers
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: absent
+ - name: container1
+ state: absent
+ register: deleted
+
+ - name: Delete again containers (idempotency)
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: absent
+ - name: container1
+ state: absent
+ register: deleted_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - deleted is changed
+ - deleted.containers is defined
+ - deleted.containers == []
+ - "'deleted container' in deleted.actions"
+ - "'deleted container1' in deleted.actions"
+ - deleted_again is not changed
+ - deleted_again.containers is defined
+ - deleted_again.containers == []
+ - deleted_again.actions == []
+ fail_msg: Deleting stopped container test failed!
+ success_msg: Deleting stopped container test passed!
+
+ - name: Create containers, but don't run
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ image: alpine:3.7
+ state: stopped
+ command: sleep 1d
+ - name: container1
+ image: alpine:3.7
+ state: stopped
+ command: sleep 1d
+ register: created
+
+ - name: Create containers, but don't run again
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ image: alpine:3.7
+ state: stopped
+ command: sleep 1d
+ - name: container1
+ image: alpine:3.7
+ state: stopped
+ command: sleep 1d
+ register: created_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - created is changed
+ - created.containers is defined
+ - created.containers != []
+ - not created.containers[0]['State']['Running']
+ - not created.containers[1]['State']['Running']
+ - "'created container' in created.actions"
+ fail_msg: "Creating stopped container test failed!"
+ success_msg: "Creating stopped container test passed!"
+
+ - name: Delete created containers
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: absent
+ - name: container1
+ state: absent
+
+ - name: Start containers that were deleted
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ image: alpine:3.7
+ state: started
+ command: sleep 1d
+ - name: container1
+ image: alpine:3.7
+ state: started
+ command: sleep 1d
+ register: started
+
+ - name: Check output is correct
+ assert:
+ that:
+ - started.containers is defined
+ - started.containers[0]['State']['Running']
+ - started.containers[1]['State']['Running']
+ - "'started container' in started.actions"
+ - "'pulled image alpine:3.7' not in started.actions"
+
+ - name: Delete started container
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: absent
+ - name: container1
+ state: absent
+ register: deleted
+
+ - name: Delete again container (idempotency)
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ state: absent
+ - name: container1
+ state: absent
+ register: deleted_again
+
+ - name: Check output is correct
+ assert:
+ that:
+ - deleted is changed
+ - deleted.containers is defined
+ - deleted.containers == []
+ - "'deleted container' in deleted.actions"
+ - "'deleted container1' in deleted.actions"
+ - deleted_again is not changed
+ - deleted_again.containers is defined
+ - deleted_again.containers == []
+ - deleted_again.actions == []
+ fail_msg: Deleting started container test failed!
+ success_msg: Deleting started container test passed!
+
+ - name: Recreate container with parameters
+ containers.podman.podman_containers:
+ containers:
+ - name: container
+ image: docker.io/alpine:3.7
+ state: started
+ command: sleep 1d
+ recreate: true
+ etc_hosts:
+ host1: 127.0.0.1
+ host2: 127.0.0.1
+ annotation:
+ this: "annotation_value"
+ dns_servers:
+ - 1.1.1.1
+ - 8.8.4.4
+ dns_search_domains: example.com
+ capabilities:
+ - SYS_TIME
+ - NET_ADMIN
+ ports:
+ - "9000:80"
+ - "9001:8000"
+ workdir: "/bin"
+ env:
+ FOO: bar=1
+ BAR: foo
+ TEST: 1
+ BOOL: false
+ label:
+ somelabel: labelvalue
+ otheralbe: othervalue
+ volumes:
+ - /tmp:/data
+ - name: container1
+ image: docker.io/alpine:3.7
+ state: started
+ command: sleep 1d
+ recreate: true
+ etc_hosts:
+ host1: 127.0.0.1
+ host2: 127.0.0.1
+ annotation:
+ this: "annotation_value"
+ dns_servers:
+ - 1.1.1.1
+ - 8.8.4.4
+ dns_search_domains: example.com
+ capabilities:
+ - SYS_TIME
+ - NET_ADMIN
+ ports:
+ - "9002:80"
+ - "9003:8000"
+ workdir: "/bin"
+ env:
+ FOO: bar=1
+ BAR: foo
+ TEST: 1
+ BOOL: false
+ label:
+ somelabel: labelvalue
+ otheralbe: othervalue
+ volumes:
+ - /tmp:/data
+ register: test
+
+ - name: Check output is correct
+ assert:
+ that:
+ - test is changed
+ - test.containers is defined
+ - test.containers != []
+ - test.containers[0]['State']['Running']
+ # test capabilities
+ - "'CAP_SYS_TIME' in test.containers[0]['BoundingCaps']"
+ - "'CAP_NET_ADMIN' in test.containers[0]['BoundingCaps']"
+ # test annotations
+ - test.containers[0]['Config']['Annotations']['this'] is defined
+ - test.containers[0]['Config']['Annotations']['this'] == "annotation_value"
+ # test DNS
+ - >-
+ (test.containers[0]['HostConfig']['Dns'] is defined and
+ test.containers[0]['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or
+ (test.containers[0]['HostConfig']['DNS'] is defined and
+ test.containers[0]['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4'])
+ # test ports
+ - test.containers[0]['NetworkSettings']['Ports']|length == 2
+ # test working dir
+ - test.containers[0]['Config']['WorkingDir'] == "/bin"
+ # test dns search
+ - >-
+ (test.containers[0]['HostConfig']['DnsSearch'] is defined and
+ test.containers[0]['HostConfig']['DnsSearch'] == ['example.com']) or
+ (test.containers[0]['HostConfig']['DNSSearch'] is defined and
+ test.containers[0]['HostConfig']['DNSSearch'] == ['example.com'])
+ # test environment variables
+ - "'FOO=bar=1' in test.containers[0]['Config']['Env']"
+ - "'BAR=foo' in test.containers[0]['Config']['Env']"
+ - "'TEST=1' in test.containers[0]['Config']['Env']"
+ - "'BOOL=False' in test.containers[0]['Config']['Env']"
+ # test labels
+ - test.containers[0]['Config']['Labels'] | length == 2
+ - test.containers[0]['Config']['Labels']['somelabel'] == "labelvalue"
+ - test.containers[0]['Config']['Labels']['otheralbe'] == "othervalue"
+ # test mounts
+ - >-
+ (test.containers[0]['Mounts'][0]['Destination'] is defined and
+ '/data' in test.containers[0]['Mounts'] | map(attribute='Destination') | list) or
+ (test.containers[0]['Mounts'][0]['destination'] is defined and
+ '/data' in test.containers[0]['Mounts'] | map(attribute='destination') | list)
+ - >-
+ (test.containers[0]['Mounts'][0]['Source'] is defined and
+ '/tmp' in test.containers[0]['Mounts'] | map(attribute='Source') | list) or
+ (test.containers[0]['Mounts'][0]['source'] is defined and
+ '/tmp' in test.containers[0]['Mounts'] | map(attribute='source') | list)
+ fail_msg: Parameters container test failed!
+ success_msg: Parameters container test passed!
+
+ - name: Check basic idempotency of running container
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ - name: testidem2
+ image: docker.io/alpine
+ state: present
+ command: sleep 21m
+ - name: testidem3
+ image: docker.io/alpine
+ state: present
+ command: sleep 22m
+
+ - name: Check basic idempotency of running container - run it again
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ - name: testidem2
+ image: docker.io/alpine
+ state: present
+ command: sleep 21m
+ - name: testidem3
+ image: docker.io/alpine
+ state: present
+ command: sleep 22m
+ register: idem
+
+ - name: Check that nothing was changed
+ assert:
+ that:
+ - not idem.changed
+
+ - name: Run changed container (with tty enabled)
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ tty: true
+ - name: testidem2
+ image: docker.io/alpine
+ state: present
+ command: sleep 21m
+ - name: testidem3
+ image: docker.io/alpine
+ state: present
+ command: sleep 22m
+ register: idem1
+
+ - name: Check that container is recreated when changed
+ assert:
+ that:
+ - idem1 is changed
+
+ - name: Run changed container without specifying an option, use defaults
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ - name: testidem2
+ image: docker.io/alpine
+ state: present
+ command: sleep 21m
+ - name: testidem3
+ image: docker.io/alpine
+ state: present
+ command: sleep 22m
+ register: idem2
+
+ - name: Check that container is recreated when changed to default value
+ assert:
+ that:
+ - idem2 is changed
+
+ - name: Remove container
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem
+ state: absent
+ register: remove
+
+ - name: Check podman_actions
+ assert:
+ that:
+ - "'podman rm -f testidem' in remove.podman_actions"
+
+ - name: Create a pod
+ containers.podman.podman_pod:
+ name: testidempod
+
+ - name: Check basic idempotency of pod container
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem-pod
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ pod: "testidempod"
+ - name: testidem-pod2
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ pod: testidempod
+
+ - name: Check basic idempotency of pod container - run it again
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem-pod
+ image: alpine:latest
+ state: present
+ command: sleep 20m
+ pod: testidempod
+ - name: testidem-pod2
+ image: docker.io/alpine
+ state: present
+ command: sleep 20m
+ pod: testidempod
+ register: idem
+
+ - name: Check that nothing was changed in pod containers
+ assert:
+ that:
+ - not idem.changed
+
+ - name: Run changed pod container (with tty enabled)
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem-pod
+ image: alpine
+ state: present
+ command: sleep 20m
+ tty: true
+ pod: testidempod
+ - name: testidem-pod2
+ image: alpine
+ state: present
+ command: sleep 20m
+ pod: testidempod
+ register: idem1
+
+ - name: Check that container is recreated when changed
+ assert:
+ that:
+ - idem1 is changed
+
+ - name: Remove container
+ containers.podman.podman_containers:
+ containers:
+ - name: testidem-pod
+ state: absent
+ - name: testidem-pod2
+ state: absent
+
+ always:
+ - name: Delete all container leftovers from tests
+ containers.podman.podman_container:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "alpine:3.7"
+ - "container"
+ - "container1"
+ - "container2"
+ - "container3"
+ - "container4"
+ - "testidem"
+ - "testidem1"
+ - "testidem2"
+ - "testidem3"
+ - "testidem-pod"
+ - "testidem-pod2"
+
+ - name: Remove pod
+ containers.podman.podman_pod:
+ name: testidempod
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile
new file mode 100644
index 00000000..d4bd8edb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/files/Containerfile
@@ -0,0 +1,3 @@
+FROM quay.io/coreos/alpine-sh
+ENV VAR testing
+WORKDIR ${VAR}
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml
new file mode 100644
index 00000000..e0eb1961
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image/tasks/main.yml
@@ -0,0 +1,190 @@
+- name: Test podman_image
+ block:
+ - name: Pull image
+ containers.podman.podman_image:
+ name: quay.io/coreos/alpine-sh
+ register: pull1
+
+ - name: Pull image again
+ containers.podman.podman_image:
+ name: quay.io/coreos/alpine-sh
+ register: pull2
+
+ - name: Pull image from docker.io with short url
+ containers.podman.podman_image:
+ name: docker.io/alpine
+ register: pull3
+
+ - name: Pull image from docker.io with short url again
+ containers.podman.podman_image:
+ name: docker.io/alpine
+ register: pull4
+
+ - name: Pull image from docker.io with official/normalised url again
+ containers.podman.podman_image:
+ name: docker.io/library/alpine
+ register: pull5
+
+ - name: List images
+ command: podman image ls
+ register: images
+
+ - name: Ensure image were pulled properly
+ assert:
+ that:
+ - pull1 is changed
+ - pull2 is not changed
+ - pull3 is changed
+ - pull4 is changed
+ - pull5 is not changed
+ - "'alpine-sh' in images.stdout"
+ - "'library/alpine' in images.stdout"
+
+ - name: add another tag (repository url)
+ command:
+ argv:
+ - podman
+ - tag
+ - quay.io/coreos/alpine-sh
+ - quay.io/coreos/library/alpine-sh
+
+ - name: Remove image (tag)
+ containers.podman.podman_image:
+ name: quay.io/coreos/alpine-sh
+ state: absent
+ register: rmi1
+
+ - name: Remove image again
+ containers.podman.podman_image:
+ name: quay.io/coreos/alpine-sh
+ state: absent
+ register: rmi2
+
+ - name: Remove image using new repository url
+ containers.podman.podman_image:
+ name: quay.io/coreos/library/alpine-sh
+ state: absent
+ register: rmi3
+
+ - name: Try to remove docker.io image using short url
+ containers.podman.podman_image:
+ name: docker.io/alpine
+ state: absent
+ register: rmi4
+
+ - name: Remove docker.io image using normalised url
+ containers.podman.podman_image:
+ name: docker.io/library/alpine
+ state: absent
+ register: rmi5
+
+ - name: List images
+ command: podman image ls
+ register: images
+
+ - name: Ensure image were removed properly
+ assert:
+ that:
+ - rmi1 is changed
+ - rmi2 is not changed
+ - rmi3 is changed
+ - rmi4 is not changed
+ - rmi5 is changed
+ - "'alpine-sh' not in images.stdout"
+ - "'library/alpine' not in images.stdout"
+
+ - name: Pull a specific version of an image
+ containers.podman.podman_image:
+ name: quay.io/coreos/etcd
+ tag: v3.3.11
+ register: specific_image1
+
+ - name: Pull a specific version of an image again
+ containers.podman.podman_image:
+ name: quay.io/coreos/etcd
+ tag: v3.3.11
+ register: specific_image2
+
+ - name: List images
+ command: podman image ls
+ register: images
+
+ - name: Ensure specific image was pulled properly
+ assert:
+ that:
+ - specific_image1 is changed
+ - specific_image2 is not changed
+ - "'v3.3.11' in images.stdout"
+
+ - name: Create a build dir
+ file:
+ path: /var/tmp/build
+ state: directory
+
+ - name: Copy Containerfile
+ copy:
+ src: Containerfile
+ dest: /var/tmp/build/Dockerfile
+
+ - name: Build OCI image
+ containers.podman.podman_image:
+ name: testimage
+ path: /var/tmp/build
+ register: oci_build1
+
+ - name: Build OCI image again
+ containers.podman.podman_image:
+ name: testimage
+ path: /var/tmp/build
+ register: oci_build2
+
+ - name: Inspect build image
+ containers.podman.podman_image_info:
+ name: testimage
+ register: testimage_info
+
+ - name: Ensure OCI image was built properly
+ assert:
+ that:
+ - oci_build1 is changed
+ - oci_build2 is not changed
+ - "'localhost/testimage:latest' in testimage_info.images[0]['RepoTags'][0]"
+
+ - name: Build Docker image
+ containers.podman.podman_image:
+ name: dockerimage
+ path: /var/tmp/build
+ build:
+ format: docker
+ register: docker_build1
+
+ - name: Build Docker image again
+ containers.podman.podman_image:
+ name: dockerimage
+ path: /var/tmp/build
+ build:
+ format: docker
+ register: docker_build2
+
+ - name: Inspect build image
+ containers.podman.podman_image_info:
+ name: dockerimage
+ register: dockerimage_info
+
+ - name: Ensure Docker image was built properly
+ assert:
+ that:
+ - docker_build1 is changed
+ - docker_build2 is not changed
+ - "'localhost/dockerimage:latest' in dockerimage_info.images[0]['RepoTags'][0]"
+
+ always:
+ - name: Cleanup images
+ containers.podman.podman_image:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - quay.io/coreos/alpine-sh
+ - quay.io/coreos/etcd:v3.3.11
+ - localhost/testimage
+ - localhost/dockerimage
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml
new file mode 100644
index 00000000..c9bd0f83
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_image_info/tasks/main.yml
@@ -0,0 +1,50 @@
+- name: Test podman_image_info
+ block:
+ - name: Pull image
+ command: podman pull quay.io/coreos/etcd
+
+ - name: Get info on all images
+ containers.podman.podman_image_info:
+ register: all_image_result
+
+ - name: Pull another image
+ command: podman pull quay.io/coreos/dnsmasq
+
+ - name: Get info on specific image
+ containers.podman.podman_image_info:
+ name: dnsmasq
+ register: named_image_result
+
+ - name:
+ assert:
+ that:
+ - all_image_result.images | length > 0
+ - named_image_result.images | length == 1
+ - "'dnsmasq' in named_image_result.images[0]['RepoTags'][0]"
+
+ - name: Get info on single image that does not exist
+ containers.podman.podman_image_info:
+ name: nope
+ register: single_nonexistant
+
+ - name: Get info on multiple images that do not exist
+ containers.podman.podman_image_info:
+ name:
+ - nope
+ - reallynope
+ register: multiple_nonexistant
+
+ - name: Get info with one image that does not exist
+ containers.podman.podman_image_info:
+ name:
+ - dnsmasq
+ - nope
+ - etcd
+ register: mixed_nonexistant
+
+ - name: Ensure image info was returned when non-existant image info was requisted
+ assert:
+ that:
+ - single_nonexistant.images | length == 0
+ - multiple_nonexistant.images | length == 0
+ - mixed_nonexistant.images | length == 2
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_login_info/tasks/main.yml
new file mode 100644
index 00000000..020c8446
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/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"
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml
new file mode 100644
index 00000000..c2f7d47f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_logout/tasks/main.yml
@@ -0,0 +1,52 @@
+- name: Test podman_logout
+ block:
+
+ - name: Print podman version
+ command: podman version
+
+ - name: Logout from docker if it exists
+ command: docker logout
+ ignore_errors: true
+
+ - name: Log out with invalid executable
+ containers.podman.podman_logout:
+ executable: podman_invalid
+ register: invalid_executable
+ ignore_errors: yes
+
+ - name: Check invalid executable results
+ assert:
+ that:
+ - invalid_executable is failed
+
+ - name: Log out of non-existing registry
+ containers.podman.podman_logout:
+ register: non_existing_registry
+
+ - name: Check results
+ assert:
+ that:
+ - "'changed' in non_existing_registry"
+ - "non_existing_registry.changed == False"
+
+ - name: Log out with invalid authfile
+ containers.podman.podman_logout:
+ authfile: authfile_invalid.json
+ register: invalid_authfile
+ ignore_errors: yes
+
+ - name: Check invalid authfile results
+ assert:
+ that:
+ - invalid_authfile is failed
+
+ - name: Log out of all registries
+ containers.podman.podman_logout:
+ all: yes
+ register: all_registries
+
+ - name: Check results
+ assert:
+ that:
+ - "'changed' in all_registries"
+ - "all_registries.changed == True"
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml
new file mode 100644
index 00000000..488ad2b3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network/tasks/main.yml
@@ -0,0 +1,224 @@
+- name: Test podman_network
+ become: true
+ block:
+
+ - name: Print podman version
+ command: podman version
+
+ - name: Check if dnsname plugin is installed
+ block:
+
+ - name: Check if plugin is installed
+ stat:
+ path: "{{ item }}"
+ loop:
+ - /usr/libexec/cni/dnsname
+ - /usr/lib/cni/dnsname
+ - /opt/cni/bin/dnsname
+ - /opt/bridge/bin/dnsname
+ register: plugin_results
+
+ - name: Set plugin fact
+ set_fact:
+ dns_plugin: "{{ true in plugin_results.results|map(attribute='stat.exists') }}"
+
+ - name: Generate random value for network name
+ set_fact:
+ network_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure network doesn't exist
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: absent
+
+ - name: Get missing network info
+ containers.podman.podman_network_info:
+ name: "{{ network_name }}"
+ register: info
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - info is failed
+
+ - name: Create network
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ register: net
+
+ - name: Get existing network info
+ containers.podman.podman_network_info:
+ name: "{{ network_name }}"
+ register: info1
+
+ - name: Check info
+ assert:
+ that:
+ - info1 | length > 1
+ - info1.networks.0.name == network_name
+ - net is changed
+
+ - name: Create network again
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ register: info2
+
+ - name: Check info
+ assert:
+ that:
+ - info2 is not changed
+
+ - name: Create network with disable DNS
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ disable_dns: true
+ register: info3
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ info3 is changed and dns_plugin|bool or
+ info3 is not changed and not dns_plugin|bool
+
+ - name: Create network with disable DNS again
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ disable_dns: true
+ register: info4
+
+ - name: Check info
+ assert:
+ that:
+ - info4 is not changed
+
+ - name: Create network w/o disable DNS
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ register: info5
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ info5 is changed and dns_plugin|bool or
+ info5 is not changed and not dns_plugin|bool
+
+ - name: Create network with custom gateway
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ gateway: 10.100.100.100
+ subnet: 10.100.100.0/24
+ register: info6
+
+ - name: Check info
+ assert:
+ that:
+ - info6 is changed
+
+ - name: Create network with custom gateway again
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ gateway: 10.100.100.100
+ subnet: 10.100.100.0/24
+ register: info7
+
+ - name: Check info
+ assert:
+ that:
+ - info7 is not changed
+
+ - name: Create internal network
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ internal: true
+ register: info9
+
+ - name: Check info
+ assert:
+ that:
+ - info9 is changed
+
+ - name: Create internal network again
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ internal: true
+ register: info10
+
+ - name: Check info
+ assert:
+ that:
+ - info10 is not changed
+
+ - name: Create a regular external network
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ register: info11
+
+ - name: Check info
+ assert:
+ that:
+ - info11 is changed
+
+ - name: Create network with subnet
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ subnet: 10.200.200.0/24
+ register: info12
+
+ - name: Check info
+ assert:
+ that:
+ - info12 is changed
+
+ - name: Create network with subnet again
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ subnet: 10.200.200.0/24
+ register: info13
+
+ - name: Check info
+ assert:
+ that:
+ - info13 is not changed
+
+ - name: Create network with ipv6 subnet
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: present
+ subnet: 2001:cafe::/64
+ ipv6: true
+
+ - name: Make sure network doesn't exist
+ containers.podman.podman_network:
+ name: "{{ network_name }}"
+ state: absent
+
+ - name: Get existing network info
+ containers.podman.podman_network_info:
+ name: "{{ network_name }}"
+ register: info100
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - info100 is failed
+
+ always:
+
+ - name: Cleanup
+ command: podman network rm -f {{ network_name }}
+ ignore_errors: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml
new file mode 100644
index 00000000..81bcaa30
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_network_info/tasks/main.yml
@@ -0,0 +1,60 @@
+- name: Test podman_network_info
+ become: true
+ block:
+
+ - name: Print podman version
+ command: podman version
+
+ - name: Generate random value for network name
+ set_fact:
+ network_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure network doesn't exist
+ command: podman network rm {{ network_name }}
+ ignore_errors: true
+
+ - name: Get missing network info
+ containers.podman.podman_network_info:
+ name: "{{ network_name }}"
+ register: nonexist
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - "'networks' not in nonexist"
+ - nonexist is failed
+
+ - name: Make sure network exists
+ command: podman network create {{ network_name }}
+
+ - name: Get existing network info
+ containers.podman.podman_network_info:
+ name: "{{ network_name }}"
+ register: existing_network
+
+ - name: Dump podman network inspect result
+ debug: var=existing_network
+
+ - name: Comparison with 'podman network inspect'
+ command: podman network inspect "{{ network_name }}"
+ register: podman_inspect
+
+ - name: Convert podman inspect output to JSON
+ set_fact:
+ podman_inspect_result: "{{ podman_inspect.stdout | from_json }}"
+
+ - name: Cleanup
+ command: podman network rm {{ network_name }}
+
+ - name: Make checks
+ assert:
+ that:
+ - "'networks' in existing_network"
+ - existing_network.networks
+ - "existing_network.networks == podman_inspect_result"
+ always:
+
+ - name: Cleanup
+ command: podman network rm {{ network_name }}
+ ignore_errors: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml
new file mode 100644
index 00000000..2ede24bd
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/main.yml
@@ -0,0 +1,613 @@
+- name: Test podman pod
+ block:
+
+ - name: Discover podman version
+ shell: podman version | grep "^Version:" | awk {'print $2'}
+ register: podman_v
+
+ - name: Set podman version to 1
+ set_fact:
+ podman_version: 1
+ when: podman_v.stdout is version('2.0.0', 'lt')
+
+ - name: Set podman version to 2
+ set_fact:
+ podman_version: 2
+ when: podman_v.stdout is version('2.0.0', '>=')
+
+ - name: Discover cgroups version
+ shell: podman info | grep cgroupVersion | awk {'print $2'}
+ register: cgroups
+
+ - name: Set cgroups version
+ set_fact:
+ cgroups_version: "{{ cgroups.stdout }}"
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_pod:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "pod1"
+ - "pod2"
+
+ - name: Create pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: created
+ register: pod1_info
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod1_info.pod['State']['status'] is defined and
+ pod1_info.pod['State']['status'] == 'Created') or
+ (pod1_info.pod['State']['status'] is not defined and
+ pod1_info.pod['State'] == 'Created')
+
+ - name: Start pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod2_info
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod2_info.pod['State']['status'] is defined and
+ pod2_info.pod['State']['status'] == 'Running') or
+ (pod2_info.pod['State']['status'] is not defined and
+ pod2_info.pod['State'] == 'Running')
+
+ - name: Pause pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: paused
+ register: pod3_info
+ when: cgroups_version == 'v2'
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod3_info.pod['State']['status'] is defined and
+ pod3_info.pod['State']['status'] == 'Paused') or
+ (pod3_info.pod['State']['status'] is not defined and
+ pod3_info.pod['State'] == 'Paused')
+ when: cgroups_version == 'v2'
+
+ - name: Unpause pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: unpaused
+ register: pod4_info
+ when: cgroups_version == 'v2'
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod4_info.pod['State']['status'] is defined and
+ pod4_info.pod['State']['status'] == 'Running') or
+ (pod4_info.pod['State']['status'] is not defined and
+ pod4_info.pod['State'] == 'Running')
+ when: cgroups_version == 'v2'
+
+ - name: Stop pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: stopped
+ register: pod5_info
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod5_info.pod['State']['status'] is defined and
+ pod5_info.pod['State']['status'] != 'Running') or
+ (pod5_info.pod['State']['status'] is not defined and
+ pod5_info.pod['State'] != 'Running')
+
+ - name: Kill pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: killed
+ register: pod6_info
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod6_info.pod['State']['status'] is defined and
+ pod6_info.pod['State']['status'] == 'Exited') or
+ (pod6_info.pod['State']['status'] is not defined and
+ pod6_info.pod['State'] == 'Exited')
+
+ - name: Start pod
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod7_info
+
+ - name: Check info
+ assert:
+ that:
+ - >-
+ (pod7_info.pod['State']['status'] is defined and
+ pod7_info.pod['State']['status'] == 'Running') or
+ (pod7_info.pod['State']['status'] is not defined and
+ pod7_info.pod['State'] == 'Running')
+
+ - name: Start pod again for idempotency
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod8_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod8_info is not changed
+
+ - name: Start pod with ports
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ ports:
+ - "4444:4444/tcp"
+ - "1212:5555"
+ - "8888:19191/udp"
+ - "1900:1900/udp"
+ - "127.0.0.1:7671:7676/udp"
+ - "127.0.0.1:12122:8876/udp"
+ - "127.0.0.1:13122:8871/tcp"
+ - "127.0.0.1:43423:8872"
+ register: pod9_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod9_info is changed
+
+ - name: Start pod with ports for idempotency
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ ports:
+ - "4444:4444/tcp"
+ - "1212:5555"
+ - "8888:19191/udp"
+ - "1900:1900/udp"
+ - "127.0.0.1:7671:7676/udp"
+ - "127.0.0.1:12122:8876/udp"
+ - "127.0.0.1:13122:8871/tcp"
+ - "127.0.0.1:43423:8872"
+ register: pod10_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod10_info is not changed
+
+ - name: Start pod again for idempotency
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod11_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod11_info is changed
+
+ - name: Start pod with share
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ share: uts
+ register: pod12_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod12_info is changed
+
+ - name: Start pod with share for idempotency
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ share: uts
+ register: pod13_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod13_info is not changed
+
+ - name: Start pod without shares
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ share: ""
+ register: pod14_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod14_info is changed
+
+ - name: Start pod with default shares
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod15_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod15_info is changed
+
+ - name: Start pod with labels
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ label:
+ key: cval
+ otherkey: kddkdk
+ somekey: someval
+ register: pod16_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod16_info is changed
+
+ - name: Start pod with labels again for idempotency
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ label:
+ key: cval
+ otherkey: kddkdk
+ somekey: someval
+ register: pod17_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod17_info is not changed
+
+ - name: Start pod with different labels
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ label:
+ key: cval
+ otherkey: 23434dfsd
+ somekey: someval
+ register: pod18_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod18_info is changed
+
+ - name: Start pod without labels
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod19_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod19_info is changed
+
+ - name: Start pod with dns and hosts settings
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.1"
+ dns:
+ - 1.1.1.1
+ dns_opt:
+ - "option timeout:3"
+ dns_search:
+ - "redhat.com"
+ - "ibm.com"
+ hostname: happypod
+ register: pod20_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod20_info is changed
+
+ - name: Start pod with dns and hosts settings again
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.1"
+ dns:
+ - 1.1.1.1
+ dns_opt:
+ - "option timeout:3"
+ dns_search:
+ - "redhat.com"
+ - "ibm.com"
+ hostname: happypod
+ register: pod21_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod21_info is not changed
+
+ - name: Start pod with changed dns
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.1"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:3"
+ dns_search:
+ - "redhat.com"
+ - "ibm.com"
+ hostname: happypod
+ register: pod22_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod22_info is changed
+
+ - name: Start pod with changed add host
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:3"
+ dns_search:
+ - "redhat.com"
+ - "ibm.com"
+ hostname: happypod
+ register: pod23_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod23_info is changed
+
+ - name: Start pod with changed dns option
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:2"
+ dns_search:
+ - "redhat.com"
+ - "ibm.com"
+ hostname: happypod
+ register: pod24_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod24_info is changed
+
+ - name: Start pod with changed dns search
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:2"
+ dns_search:
+ - "redhat.com"
+ hostname: happypod
+ register: pod25_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod25_info is changed
+
+ - name: Start pod with changed hostname
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:2"
+ dns_search:
+ - "redhat.com"
+ hostname: bestpod
+ register: pod26_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod26_info is changed
+
+ - name: Start pod with removed dns search
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ dns_opt:
+ - "option timeout:2"
+ hostname: bestpod
+ register: pod27_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod27_info is changed
+
+ - name: Start pod with removed dns option
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ dns:
+ - 1.1.1.1
+ - 2.2.2.2
+ hostname: bestpod
+ register: pod28_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod28_info is changed
+
+ - name: Start pod with removed dns
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ add_host:
+ - "google:8.8.8.8"
+ - "site1:127.0.0.2"
+ hostname: bestpod
+ register: pod29_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod29_info is changed
+
+ - name: Start pod with removed add host
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ hostname: bestpod
+ register: pod30_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod30_info is changed
+
+ - name: Start pod without infra
+ containers.podman.podman_pod:
+ name: pod1
+ state: created
+ infra: false
+ register: pod31_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod31_info is changed
+
+ - name: Start pod without infra again
+ containers.podman.podman_pod:
+ name: pod1
+ state: created
+ infra: false
+ register: pod32_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod32_info is not changed
+
+ - name: Start pod with infra
+ containers.podman.podman_pod:
+ name: pod1
+ state: started
+ register: pod33_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod33_info is changed
+
+ - name: Start pod with different infra image
+ containers.podman.podman_pod:
+ name: pod1
+ state: created
+ infra_image: alpine:3.9
+ register: pod34_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod34_info is changed
+
+ - name: Start pod with different infra image again
+ containers.podman.podman_pod:
+ name: pod1
+ state: created
+ infra_image: alpine:3.9
+ register: pod35_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod35_info is not changed
+
+ always:
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_pod:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "pod1"
+ - "pod2"
+
+- name: Test idempotency for root pods
+ include_tasks: root-pod.yml
+ vars:
+ ansible_python_interpreter: "/usr/bin/python"
+ args:
+ apply:
+ become: true
+
+- name: Test idempotency for root pods and networks
+ include_tasks: net-pod.yml
+ vars:
+ ansible_python_interpreter: "/usr/bin/python"
+ args:
+ apply:
+ become: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml
new file mode 100644
index 00000000..b1b15def
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/net-pod.yml
@@ -0,0 +1,48 @@
+- name: Test podman rootful pod
+ block:
+
+ - name: Remove pods
+ containers.podman.podman_pod:
+ name: "rootnetpod"
+ state: absent
+
+ - name: Create network testnet
+ command: podman network create testnet --subnet 10.91.91.0/24
+
+ - name: Create network anothernet
+ command: podman network create anothernet --subnet 10.71.71.0/24
+
+ - name: List current networks
+ command: podman network ls
+
+ - name: Set test data
+ set_fact:
+ testdata:
+ - first_net: host
+ next_net: bridge
+ - first_net: bridge
+ next_net: host
+ - first_net: anothernet
+ next_net: testnet
+ - first_net: testnet
+ next_net: testnet,anothernet
+ - first_net: testnet,anothernet
+ next_net: anothernet
+ - first_net: testnet,anothernet
+ next_net: bridge
+ - first_net: testnet,anothernet
+ next_net: host
+ - first_net: host
+ next_net: anothernet
+ - first_net: bridge
+ next_net: anothernet,testnet
+
+ - include_tasks: network-tests.yml
+ loop: "{{ testdata }}"
+
+ always:
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_pod:
+ name: "rootnetpod"
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml
new file mode 100644
index 00000000..8df7016b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/network-tests.yml
@@ -0,0 +1,39 @@
+---
+- name: Remove pod nettest
+ become: true
+ containers.podman.podman_pod:
+ name: nettest
+ state: absent
+
+- name: Run pod with {{ item.first_net }}
+ become: true
+ containers.podman.podman_pod:
+ name: nettest
+ state: started
+ network: "{{ item.first_net }}"
+
+- name: Run pod again with {{ item.first_net }}
+ become: true
+ containers.podman.podman_pod:
+ name: nettest
+ state: started
+ network: "{{ item.first_net }}"
+ register: info
+
+- name: Check info that not changed
+ assert:
+ that:
+ - info is not changed
+
+- name: Run pod changed from {{ item.first_net }} to {{ item.next_net }}
+ become: true
+ containers.podman.podman_pod:
+ name: nettest
+ state: started
+ network: "{{ item.next_net }}"
+ register: info1
+
+- name: Check info
+ assert:
+ that:
+ - info1 is changed
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml
new file mode 100644
index 00000000..d0027417
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod/tasks/root-pod.yml
@@ -0,0 +1,120 @@
+- name: Test podman rootful pod
+ block:
+
+ - name: Discover cgroups version
+ shell: podman info | grep cgroupVersion | awk {'print $2'}
+ register: cgroups
+
+ - name: Set cgroups version
+ set_fact:
+ cgroups_version: "{{ cgroups.stdout }}"
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: absent
+
+ - name: Create and start pod
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+
+ - name: Create and start pod
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ register: pod1_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod1_info is not changed
+
+ - name: Add DNS to pod
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ dns:
+ - 1.1.1.1
+ register: pod2_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod2_info is changed
+
+ - name: Remove DNS from pod
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ register: pod3_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod3_info is changed
+
+ - name: Create network newnet
+ command: podman network create newnet --subnet 10.90.90.0/24
+
+ - name: Create network net2
+ command: podman network create net2 --subnet 10.70.70.0/24
+
+ - name: Start pod with networks
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ network: net2,newnet
+ register: pod4_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod4_info is changed
+
+ - name: Start pod with networks again
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ network: newnet,net2
+ register: pod5_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod5_info is not changed
+
+ - name: Start pod with one network
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ network: net2
+ register: pod6_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod6_info is changed
+
+ - name: Start pod without networks
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: started
+ register: pod7_info
+
+ - name: Check info
+ assert:
+ that:
+ - pod7_info is changed
+
+ always:
+
+ - name: Delete all pods leftovers from tests
+ containers.podman.podman_pod:
+ name: "rootpod"
+ state: absent
+
+ - name: Delete all existing pods
+ shell: |
+ podman pod rm -fa;
+ ignore_errors: true
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml
new file mode 100644
index 00000000..ccf20bf2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_pod_info/tasks/main.yml
@@ -0,0 +1,103 @@
+- name: Test podman_pod_info
+ block:
+
+ - name: Print podman version
+ command: podman info --debug
+
+ - name: Discover podman version
+ shell: podman version | grep "^Version:" | awk {'print $2'}
+ register: podman_version
+
+ - name: Generate random value for pod name
+ set_fact:
+ pod_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure pod doesn't exist
+ containers.podman.podman_pod:
+ name: "{{ pod_name }}"
+ state: absent
+
+ - name: Get missing pod info
+ containers.podman.podman_pod_info:
+ name: "{{ pod_name }}"
+ register: nonexist
+
+ - name: Check info for missing pod
+ assert:
+ that:
+ - nonexist.pods == []
+
+ - name: Get all missing pods info
+ containers.podman.podman_pod_info:
+ register: nonexist2
+
+ - name: Check info for missing pod
+ assert:
+ that:
+ - nonexist2.pods == []
+
+ - name: Create test pod
+ containers.podman.podman_pod:
+ name: "{{ pod_name }}"
+
+ - name: Get all pods info
+ containers.podman.podman_pod_info:
+ register: info
+
+ - name: Check info for pod
+ assert:
+ that:
+ - info.pods | length == 1
+ - >-
+ (info.pods[0]['Config']['name'] is defined and
+ info.pods[0]['Config']['name'] == pod_name) or
+ (info.pods[0]['Name'] is defined and
+ info.pods[0]['Name'] == pod_name)
+
+ - name: Get specific pod info
+ containers.podman.podman_pod_info:
+ name: "{{ pod_name }}"
+ register: info2
+
+ - name: Check info for pod
+ assert:
+ that:
+ - info2.pods | length == 1
+ - >-
+ (info2.pods[0]['Config']['name'] is defined and
+ info2.pods[0]['Config']['name'] == pod_name) or
+ (info2.pods[0]['Name'] is defined and
+ info2.pods[0]['Name'] == pod_name)
+
+ - name: Create another test pod
+ containers.podman.podman_pod:
+ name: "{{ pod_name }}_1"
+
+ - name: Get specific another pod info
+ containers.podman.podman_pod_info:
+ name: "{{ pod_name }}"
+ register: info3
+
+ - name: Check info for missing pod
+ assert:
+ that:
+ - info3.pods | length == 1
+
+ - name: Get pods info
+ containers.podman.podman_pod_info:
+ register: info4
+
+ - name: Check info for pods
+ assert:
+ that:
+ - info4.pods | length == 2
+
+ always:
+
+ - name: Make sure pod doesn't exist
+ containers.podman.podman_pod:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "{{ pod_name }}"
+ - "{{ pod_name }}_1"
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml
new file mode 100644
index 00000000..669b34c5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume/tasks/main.yml
@@ -0,0 +1,267 @@
+- name: Test podman_volume
+ block:
+
+ - name: Print podman version
+ command: podman version
+
+ - name: Generate random value for volume name
+ set_fact:
+ volume_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure volume doesn't exist
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
+
+ - name: Get missing volume info
+ containers.podman.podman_volume_info:
+ name: "{{ volume_name }}"
+ register: info
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - info is failed
+
+ - name: Create volume
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ register: vol
+
+ - name: Get existing volume info
+ containers.podman.podman_volume_info:
+ name: "{{ volume_name }}"
+ register: info1
+
+ - name: Check info
+ assert:
+ that:
+ - info1 | length > 1
+ - info1.volumes.0.Name == volume_name
+ - vol is changed
+
+ - name: Create volume again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info2
+
+ - name: Check info
+ assert:
+ that:
+ - info2 is not changed
+
+ - name: Create volume with labels
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ label:
+ key: val
+ nokey: noval
+ register: info3
+
+ - name: Check info
+ assert:
+ that:
+ - info3 is changed
+
+ - name: Create volume with labels again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ label:
+ key: val
+ nokey: noval
+ register: info4
+
+ - name: Check info
+ assert:
+ that:
+ - info4 is not changed
+
+ - name: Create volume w/o labels
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info5
+
+ - name: Check info
+ assert:
+ that:
+ - info5 is changed
+
+ - name: Create volume with options
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "device=/dev/something"
+ - "type=ext4"
+ register: info6
+
+ - name: Check info
+ assert:
+ that:
+ - info6 is changed
+
+ - name: Create volume with options again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "device=/dev/something"
+ - "type=ext4"
+ register: info7
+
+ - name: Check info
+ assert:
+ that:
+ - info7 is not changed
+
+ - name: Create volume w/o options
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info8
+
+ - name: Check info
+ assert:
+ that:
+ - info8 is changed
+
+ - name: Make sure volume doesn't exist
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
+ register: delete
+
+ - name: Get existing volume info
+ containers.podman.podman_volume_info:
+ name: "{{ volume_name }}"
+ register: info10
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - info10 is failed
+ - delete.volume == {}
+
+ - name: Create volume with UID option
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=uid=1001"
+ register: info11
+
+ - name: Check info
+ assert:
+ that:
+ - info11 is changed
+
+ - name: Create volume with UID option - again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=uid=1001"
+ register: info12
+
+ - name: Check info
+ assert:
+ that:
+ - info12 is not changed
+
+ - name: Create volume with UID option - default
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info13
+
+ - name: Check info
+ assert:
+ that:
+ - info13 is changed
+
+ - name: Create volume with GID option
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=gid=1001"
+ register: info14
+
+ - name: Check info
+ assert:
+ that:
+ - info14 is changed
+
+ - name: Create volume with GID option - again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=gid=1001"
+ register: info15
+
+ - name: Check info
+ assert:
+ that:
+ - info15 is not changed
+
+ - name: Create volume with GID option - default
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info16
+
+ - name: Check info
+ assert:
+ that:
+ - info16 is changed
+
+ - name: Create volume with GID and UID option
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=gid=1002,uid=1002"
+ register: info17
+
+ - name: Check info
+ assert:
+ that:
+ - info17 is changed
+
+ - name: Create volume with GID and UID option - again
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ options:
+ - "o=uid=1002"
+ - "o=gid=1002"
+ register: info18
+
+ - name: Check info
+ assert:
+ that:
+ - info18 is not changed
+
+ - name: Create volume with GID and UID option - default
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+ register: info19
+
+ - name: Check info
+ assert:
+ that:
+ - info19 is changed
+ always:
+
+ - name: Make sure volume doesn't exist
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml
new file mode 100644
index 00000000..9bd046d7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/integration/targets/podman_volume_info/tasks/main.yml
@@ -0,0 +1,65 @@
+- name: Test podman_volume_info
+ block:
+
+ - name: Print podman version
+ command: podman version
+
+ - name: Generate random value for volume name
+ set_fact:
+ volume_name: "{{ 'ansible-test-podman-%0x' % ((2**32) | random) }}"
+
+ - name: Make sure volume doesn't exist
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
+
+ - name: Get missing volume info
+ containers.podman.podman_volume_info:
+ name: "{{ volume_name }}"
+ register: nonexist
+ ignore_errors: true
+
+ - name: Check results
+ assert:
+ that:
+ - "'volumes' not in nonexist"
+ - nonexist is failed
+
+ - name: Make sure volume exists
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: present
+
+ - name: Get existing volume info
+ containers.podman.podman_volume_info:
+ name: "{{ volume_name }}"
+ register: existing_volume
+
+ - name: Dump podman volume inspect result
+ debug: var=existing_volume
+
+ - name: Comparison with 'podman volume inspect'
+ command: podman volume inspect "{{ volume_name }}"
+ register: podman_inspect
+
+ - name: Convert podman inspect output to JSON
+ set_fact:
+ podman_inspect_result: "{{ podman_inspect.stdout | from_json }}"
+
+ - name: Cleanup
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
+
+ - name: Make checks
+ assert:
+ that:
+ - "'volumes' in existing_volume"
+ - existing_volume.volumes
+ - "existing_volume.volumes == podman_inspect_result"
+ always:
+
+ - name: Cleanup
+ containers.podman.podman_volume:
+ name: "{{ volume_name }}"
+ state: absent
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt
new file mode 100644
index 00000000..1dc834b7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.10.txt
@@ -0,0 +1,5 @@
+plugins/modules/podman_image.py validate-modules:mutually_exclusive-unknown
+plugins/modules/podman_container.py validate-modules:parameter-list-no-elements
+tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086
+tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086
+plugins/module_utils/podman/common.py shebang!skip
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt
new file mode 100644
index 00000000..1dc834b7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.11.txt
@@ -0,0 +1,5 @@
+plugins/modules/podman_image.py validate-modules:mutually_exclusive-unknown
+plugins/modules/podman_container.py validate-modules:parameter-list-no-elements
+tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086
+tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086
+plugins/module_utils/podman/common.py shebang!skip
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt
new file mode 100644
index 00000000..9521178f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/ignore-2.9.txt
@@ -0,0 +1,3 @@
+tests/integration/targets/connection_buildah/runme.sh shellcheck:SC2086
+tests/integration/targets/connection_podman/runme.sh shellcheck:SC2086
+plugins/module_utils/podman/common.py shebang!skip
diff --git a/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/requirements.txt b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/requirements.txt
new file mode 100644
index 00000000..fd9f609d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/containers/podman/tests/sanity/requirements.txt
@@ -0,0 +1,8 @@
+packaging # needed for update-bundled and changelog
+sphinx ; python_version >= '3.5' # docs build requires python 3+
+sphinx-notfound-page ; python_version >= '3.5' # docs build requires python 3+
+straight.plugin ; python_version >= '3.5' # needed for hacking/build-ansible.py which will host changelog generation and requires python 3+
+voluptuous
+yamllint
+pylint
+virtualenv