# Copyright (c), Felix Fontein , 2020 # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import annotations import pytest from ansible.inventory.data import InventoryData from ansible.parsing.dataloader import DataLoader from ansible.template import Templar from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import ( create_autospec, ) from ansible_collections.community.internal_test_tools.tests.unit.utils.trust import ( make_trusted, ) from ansible_collections.community.docker.plugins.inventory.docker_containers import ( InventoryModule, ) @pytest.fixture(scope="module") def templar(): dataloader = create_autospec(DataLoader, instance=True) return Templar(loader=dataloader) @pytest.fixture(scope="module") def inventory(templar): r = InventoryModule() r.inventory = InventoryData() r.templar = templar return r LOVING_THARP = { "Id": "7bd547963679e3209cafd52aff21840b755c96fd37abcd7a6e19da8da6a7f49a", "Name": "/loving_tharp", "Image": "sha256:349f492ff18add678364a62a67ce9a13487f14293ae0af1baf02398aa432f385", "State": { "Running": True, }, "Config": { "Image": "quay.io/ansible/ubuntu1804-test-container:1.21.0", }, } LOVING_THARP_STACK = { "Id": "7bd547963679e3209cafd52aff21840b755c96fd37abcd7a6e19da8da6a7f49a", "Name": "/loving_tharp", "Image": "sha256:349f492ff18add678364a62a67ce9a13487f14293ae0af1baf02398aa432f385", "State": { "Running": True, }, "Config": { "Image": "quay.io/ansible/ubuntu1804-test-container:1.21.0", "Labels": { "com.docker.stack.namespace": "my_stack", }, }, "NetworkSettings": { "Ports": { "22/tcp": [{"HostIp": "0.0.0.0", "HostPort": "32802"}], }, }, } LOVING_THARP_SERVICE = { "Id": "7bd547963679e3209cafd52aff21840b755c96fd37abcd7a6e19da8da6a7f49a", "Name": "/loving_tharp", "Image": "sha256:349f492ff18add678364a62a67ce9a13487f14293ae0af1baf02398aa432f385", "State": { "Running": True, }, "Config": { "Image": "quay.io/ansible/ubuntu1804-test-container:1.21.0", "Labels": { "com.docker.swarm.service.name": "my_service", }, }, } def create_get_option(options, default=False): def get_option(option): if option in options: return options[option] return default return get_option class FakeClient: def __init__(self, *hosts): self.get_results = {} list_reply = [] for host in hosts: list_reply.append( { "Id": host["Id"], "Names": [host["Name"]] if host["Name"] else [], "Image": host["Config"]["Image"], "ImageId": host["Image"], } ) self.get_results[f"/containers/{host['Name']}/json"] = host self.get_results[f"/containers/{host['Id']}/json"] = host self.get_results["/containers/json"] = list_reply def get_json(self, url, *param, **kwargs): url = url.format(*param) return self.get_results[url] def test_populate(inventory, mocker): client = FakeClient(LOVING_THARP) inventory.get_option = mocker.MagicMock( side_effect=create_get_option( { "verbose_output": True, "connection_type": "docker-api", "add_legacy_groups": False, "compose": {}, "groups": {}, "keyed_groups": {}, "filters": None, } ) ) inventory._populate(client) host_1 = inventory.inventory.get_host("loving_tharp") host_1_vars = host_1.get_vars() assert host_1_vars["ansible_host"] == "loving_tharp" assert host_1_vars["ansible_connection"] == "community.docker.docker_api" assert "ansible_ssh_host" not in host_1_vars assert "ansible_ssh_port" not in host_1_vars assert "docker_state" in host_1_vars assert "docker_config" in host_1_vars assert "docker_image" in host_1_vars assert len(inventory.inventory.groups["ungrouped"].hosts) == 0 assert len(inventory.inventory.groups["all"].hosts) == 0 assert len(inventory.inventory.groups) == 2 assert len(inventory.inventory.hosts) == 1 def test_populate_service(inventory, mocker): client = FakeClient(LOVING_THARP_SERVICE) inventory.get_option = mocker.MagicMock( side_effect=create_get_option( { "verbose_output": False, "connection_type": "docker-cli", "add_legacy_groups": True, "compose": {}, "groups": {}, "keyed_groups": {}, "docker_host": "unix://var/run/docker.sock", "filters": None, } ) ) inventory._populate(client) host_1 = inventory.inventory.get_host("loving_tharp") host_1_vars = host_1.get_vars() assert host_1_vars["ansible_host"] == "loving_tharp" assert host_1_vars["ansible_connection"] == "community.docker.docker" assert "ansible_ssh_host" not in host_1_vars assert "ansible_ssh_port" not in host_1_vars assert "docker_state" not in host_1_vars assert "docker_config" not in host_1_vars assert "docker_image" not in host_1_vars assert len(inventory.inventory.groups["ungrouped"].hosts) == 0 assert len(inventory.inventory.groups["all"].hosts) == 0 assert len(inventory.inventory.groups["7bd547963679e"].hosts) == 1 assert ( len( inventory.inventory.groups[ "7bd547963679e3209cafd52aff21840b755c96fd37abcd7a6e19da8da6a7f49a" ].hosts ) == 1 ) assert ( len( inventory.inventory.groups[ "image_quay.io/ansible/ubuntu1804-test-container:1.21.0" ].hosts ) == 1 ) assert len(inventory.inventory.groups["loving_tharp"].hosts) == 1 assert len(inventory.inventory.groups["running"].hosts) == 1 assert len(inventory.inventory.groups["stopped"].hosts) == 0 assert len(inventory.inventory.groups["service_my_service"].hosts) == 1 assert len(inventory.inventory.groups["unix://var/run/docker.sock"].hosts) == 1 assert len(inventory.inventory.groups) == 10 assert len(inventory.inventory.hosts) == 1 def test_populate_stack(inventory, mocker): client = FakeClient(LOVING_THARP_STACK) inventory.get_option = mocker.MagicMock( side_effect=create_get_option( { "verbose_output": False, "connection_type": "ssh", "add_legacy_groups": True, "compose": {}, "groups": {}, "keyed_groups": {}, "docker_host": "unix://var/run/docker.sock", "default_ip": "127.0.0.1", "private_ssh_port": 22, "filters": None, } ) ) inventory._populate(client) host_1 = inventory.inventory.get_host("loving_tharp") host_1_vars = host_1.get_vars() assert host_1_vars["ansible_ssh_host"] == "127.0.0.1" assert host_1_vars["ansible_ssh_port"] == "32802" assert "ansible_host" not in host_1_vars assert "ansible_connection" not in host_1_vars assert "docker_state" not in host_1_vars assert "docker_config" not in host_1_vars assert "docker_image" not in host_1_vars assert len(inventory.inventory.groups["ungrouped"].hosts) == 0 assert len(inventory.inventory.groups["all"].hosts) == 0 assert len(inventory.inventory.groups["7bd547963679e"].hosts) == 1 assert ( len( inventory.inventory.groups[ "7bd547963679e3209cafd52aff21840b755c96fd37abcd7a6e19da8da6a7f49a" ].hosts ) == 1 ) assert ( len( inventory.inventory.groups[ "image_quay.io/ansible/ubuntu1804-test-container:1.21.0" ].hosts ) == 1 ) assert len(inventory.inventory.groups["loving_tharp"].hosts) == 1 assert len(inventory.inventory.groups["running"].hosts) == 1 assert len(inventory.inventory.groups["stopped"].hosts) == 0 assert len(inventory.inventory.groups["stack_my_stack"].hosts) == 1 assert len(inventory.inventory.groups["unix://var/run/docker.sock"].hosts) == 1 assert len(inventory.inventory.groups) == 10 assert len(inventory.inventory.hosts) == 1 def test_populate_filter_none(inventory, mocker): client = FakeClient(LOVING_THARP) inventory.get_option = mocker.MagicMock( side_effect=create_get_option( { "verbose_output": True, "connection_type": "docker-api", "add_legacy_groups": False, "compose": {}, "groups": {}, "keyed_groups": {}, "filters": [ {"exclude": True}, ], } ) ) inventory._populate(client) assert len(inventory.inventory.hosts) == 0 def test_populate_filter(inventory, mocker): client = FakeClient(LOVING_THARP) inventory.get_option = mocker.MagicMock( side_effect=create_get_option( { "verbose_output": True, "connection_type": "docker-api", "add_legacy_groups": False, "compose": {}, "groups": {}, "keyed_groups": {}, "filters": [ {"include": make_trusted("docker_state.Running is true")}, {"exclude": True}, ], } ) ) inventory._populate(client) host_1 = inventory.inventory.get_host("loving_tharp") host_1_vars = host_1.get_vars() assert host_1_vars["ansible_host"] == "loving_tharp" assert len(inventory.inventory.hosts) == 1