From 1be4e3fd8f1c93e90e9fc9dbbd49cd8f3908a11a Mon Sep 17 00:00:00 2001 From: Yuriy Novostavskiy Date: Mon, 20 Jan 2025 16:23:54 +0100 Subject: [PATCH 1/5] Bump kubernetes.core version to 6.0.0 --- Makefile | 2 +- galaxy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e97dbb9704..80b41f3179 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Also needs to be updated in galaxy.yml -VERSION = 5.2.0-dev0 +VERSION = 6.0.0-dev0 TEST_ARGS ?= "" PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'` diff --git a/galaxy.yml b/galaxy.yml index d08c94ff70..6f7c2d12d7 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -25,7 +25,7 @@ tags: - openshift - okd - cluster -version: 5.2.0-dev0 +version: 6.0.0-dev0 build_ignore: - .DS_Store - "*.tar.gz" From aeee795578c577278fd5b9a91cbf42c2e804c732 Mon Sep 17 00:00:00 2001 From: Yuriy Novostavskiy Date: Tue, 21 Jan 2025 17:04:51 +0200 Subject: [PATCH 2/5] drop support of ansible-core<2.16.0 ansible-core 2.15 reach EOL in Nov 2024 --- README.md | 2 +- changelogs/fragments/20250121-drop-support-of-2.16.yml | 3 +++ meta/runtime.yml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/20250121-drop-support-of-2.16.yml diff --git a/README.md b/README.md index 5125ee0fc1..0bd3edf936 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ For more information about communication, see the [Ansible communication guide]( ## Ansible version compatibility -This collection has been tested against following Ansible versions: **>=2.15.0**. +This collection has been tested against following Ansible versions: **>=2.16.0**. For collections that support Ansible 2.9, please ensure you update your `network_os` to use the fully qualified collection name (for example, `cisco.ios.ios`). diff --git a/changelogs/fragments/20250121-drop-support-of-2.16.yml b/changelogs/fragments/20250121-drop-support-of-2.16.yml new file mode 100644 index 0000000000..7419fb5b47 --- /dev/null +++ b/changelogs/fragments/20250121-drop-support-of-2.16.yml @@ -0,0 +1,3 @@ +--- +breaking_changes: + - Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867). diff --git a/meta/runtime.yml b/meta/runtime.yml index 9724dc5923..75c5db896a 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -1,5 +1,5 @@ --- -requires_ansible: '>=2.15.0' +requires_ansible: '>=2.16.0' action_groups: helm: From 0f51639d8fc0207d58ff92b07b4b0aafe92de79b Mon Sep 17 00:00:00 2001 From: Yuriy Novostavskiy Date: Tue, 21 Jan 2025 17:09:11 +0200 Subject: [PATCH 3/5] remove deprecated k8s invetory plugin --- README.md | 5 - ...ml => 20250121-breaking-changes-6.0.0.yml} | 1 + .../rst/kubernetes_scenarios/k8s_intro.rst | 2 +- .../kubernetes_scenarios/k8s_inventory.rst | 88 ---- docs/docsite/rst/scenario_guide.rst | 1 - docs/kubernetes.core.k8s_drain_module.rst | 3 +- docs/kubernetes.core.k8s_inventory.rst | 372 -------------- meta/runtime.yml | 5 +- plugins/inventory/k8s.py | 476 ------------------ .../integration/targets/inventory_k8s/aliases | 3 - .../playbooks/create_resources.yml | 46 -- .../playbooks/delete_resources.yml | 30 -- .../targets/inventory_k8s/playbooks/play.yml | 90 ---- .../playbooks/test.inventory_k8s.yml | 2 - .../inventory_k8s/playbooks/vars/main.yml | 38 -- .../targets/inventory_k8s/runme.sh | 30 -- 16 files changed, 6 insertions(+), 1186 deletions(-) rename changelogs/fragments/{20250121-drop-support-of-2.16.yml => 20250121-breaking-changes-6.0.0.yml} (54%) delete mode 100644 docs/docsite/rst/kubernetes_scenarios/k8s_inventory.rst delete mode 100644 docs/kubernetes.core.k8s_inventory.rst delete mode 100644 plugins/inventory/k8s.py delete mode 100644 tests/integration/targets/inventory_k8s/aliases delete mode 100644 tests/integration/targets/inventory_k8s/playbooks/create_resources.yml delete mode 100644 tests/integration/targets/inventory_k8s/playbooks/delete_resources.yml delete mode 100644 tests/integration/targets/inventory_k8s/playbooks/play.yml delete mode 100644 tests/integration/targets/inventory_k8s/playbooks/test.inventory_k8s.yml delete mode 100644 tests/integration/targets/inventory_k8s/playbooks/vars/main.yml delete mode 100755 tests/integration/targets/inventory_k8s/runme.sh diff --git a/README.md b/README.md index 0bd3edf936..eb5e4b1f6c 100644 --- a/README.md +++ b/README.md @@ -57,11 +57,6 @@ Name | Description --- | --- kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret -### Inventory plugins -Name | Description ---- | --- -[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source - ### Lookup plugins Name | Description --- | --- diff --git a/changelogs/fragments/20250121-drop-support-of-2.16.yml b/changelogs/fragments/20250121-breaking-changes-6.0.0.yml similarity index 54% rename from changelogs/fragments/20250121-drop-support-of-2.16.yml rename to changelogs/fragments/20250121-breaking-changes-6.0.0.yml index 7419fb5b47..811b02fcc6 100644 --- a/changelogs/fragments/20250121-drop-support-of-2.16.yml +++ b/changelogs/fragments/20250121-breaking-changes-6.0.0.yml @@ -1,3 +1,4 @@ --- breaking_changes: - Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867). + - Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867). diff --git a/docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst b/docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst index e5bcfb8dfd..00dfcb3f27 100644 --- a/docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst +++ b/docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst @@ -17,7 +17,7 @@ Requirements To use the modules, you'll need the following: -- Ansible 2.9.17 or latest installed +- Ansible 2.16.0 or latest installed - `Kubernetes Python client `_ installed on the host that will execute the modules. diff --git a/docs/docsite/rst/kubernetes_scenarios/k8s_inventory.rst b/docs/docsite/rst/kubernetes_scenarios/k8s_inventory.rst deleted file mode 100644 index e7f4da9c53..0000000000 --- a/docs/docsite/rst/kubernetes_scenarios/k8s_inventory.rst +++ /dev/null @@ -1,88 +0,0 @@ -.. _ansible_collections.kubernetes.core.docsite.k8s_ansible_inventory: - -***************************************** -Using Kubernetes dynamic inventory plugin -***************************************** - -.. contents:: - :local: - -Kubernetes dynamic inventory plugin -=================================== - - -The best way to interact with your Pods is to use the Kubernetes dynamic inventory plugin, which queries Kubernetes APIs using ``kubectl`` command line available on controller node and tells Ansible what Pods can be managed. - -Requirements ------------- - -To use the Kubernetes dynamic inventory plugins, you must install `Kubernetes Python client `_, `kubectl `_ on your control node (the host running Ansible). - -.. code-block:: bash - - $ pip install kubernetes - -Please refer to Kubernetes official documentation for `installing kubectl `_ on the given operating systems. - -To use this Kubernetes dynamic inventory plugin, you need to enable it first by specifying the following in the ``ansible.cfg`` file: - -.. code-block:: ini - - [inventory] - enable_plugins = kubernetes.core.k8s - -Then, create a file that ends in ``.k8s.yml`` or ``.k8s.yaml`` in your working directory. - -The ``kubernetes.core.k8s`` inventory plugin takes in the same authentication information as any other Kubernetes modules. - -Here's an example of a valid inventory file: - -.. code-block:: yaml - - plugin: kubernetes.core.k8s - -Executing ``ansible-inventory --list -i .k8s.yml`` will create a list of Pods that are ready to be configured using Ansible. - -You can also provide the namespace to gather information about specific pods from the given namespace. For example, to gather information about Pods under the ``test`` namespace you will specify the ``namespaces`` parameter: - -.. code-block:: yaml - - plugin: kubernetes.core.k8s - connections: - - namespaces: - - test - -Using vaulted configuration files -================================= - -Since the inventory configuration file contains Kubernetes related sensitive information in plain text, a security risk, you may want to -encrypt your entire inventory configuration file. - -You can encrypt a valid inventory configuration file as follows: - -.. code-block:: bash - - $ ansible-vault encrypt .k8s.yml - New Vault password: - Confirm New Vault password: - Encryption successful - - $ echo "MySuperSecretPassw0rd!" > /path/to/vault_password_file - -And you can use this vaulted inventory configuration file using: - -.. code-block:: bash - - $ ansible-inventory -i .k8s.yml --list --vault-password-file=/path/to/vault_password_file - - -.. seealso:: - - `Kubernetes Python client - Issue Tracker `_ - The issue tracker for Kubernetes Python client - `Kubectl installation `_ - Installation guide for installing Kubectl - :ref:`working_with_playbooks` - An introduction to playbooks - :ref:`playbooks_vault` - Using Vault in playbooks diff --git a/docs/docsite/rst/scenario_guide.rst b/docs/docsite/rst/scenario_guide.rst index c0fbaecc07..118fffd525 100644 --- a/docs/docsite/rst/scenario_guide.rst +++ b/docs/docsite/rst/scenario_guide.rst @@ -13,6 +13,5 @@ To get started, please select one of the following topics. :maxdepth: 1 kubernetes_scenarios/k8s_intro - kubernetes_scenarios/k8s_inventory kubernetes_scenarios/k8s_scenarios diff --git a/docs/kubernetes.core.k8s_drain_module.rst b/docs/kubernetes.core.k8s_drain_module.rst index 95f8271491..995e911342 100644 --- a/docs/kubernetes.core.k8s_drain_module.rst +++ b/docs/kubernetes.core.k8s_drain_module.rst @@ -595,7 +595,8 @@ Examples kubernetes.core.k8s_drain: state: drain name: foo - force: yes + delete_options: + force: yes - name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes. kubernetes.core.k8s_drain: diff --git a/docs/kubernetes.core.k8s_inventory.rst b/docs/kubernetes.core.k8s_inventory.rst deleted file mode 100644 index 727027408b..0000000000 --- a/docs/kubernetes.core.k8s_inventory.rst +++ /dev/null @@ -1,372 +0,0 @@ -.. _kubernetes.core.k8s_inventory: - - -******************* -kubernetes.core.k8s -******************* - -**Kubernetes (K8s) inventory source** - - - -.. contents:: - :local: - :depth: 1 - -DEPRECATED ----------- -:Removed in collection release after -:Why: As discussed in https://github.com/ansible-collections/kubernetes.core/issues/31, we decided to -remove the k8s inventory plugin in release 6.0.0. - -:Alternative: Use :ref:`kubernetes.core.k8s_info ` and :ref:`ansible.builtin.add_host ` instead. - - - -Synopsis --------- -- Fetch containers and services for one or more clusters. -- Groups by cluster name, namespace, namespace_services, namespace_pods, and labels. -- Uses the kubectl connection plugin to access the Kubernetes cluster. -- Uses k8s.(yml|yaml) YAML configuration file to set parameter values. - - - -Requirements ------------- -The below requirements are needed on the local Ansible controller node that executes this inventory. - -- python >= 3.9 -- kubernetes >= 24.2.0 -- PyYAML >= 3.11 - - -Parameters ----------- - -.. raw:: html - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterChoices/DefaultsConfigurationComments
-
- connections - -
- - -
-
- - -
Optional list of cluster connection settings. If no connections are provided, the default ~/.kube/config and active context will be used, and objects will be returned for all namespaces the active user is authorized to access.
-
-
- api_key - -
- - -
-
- - -
Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.
-
-
- ca_cert - -
- - -
-
- - -
Path to a CA certificate used to authenticate with the API. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.
-

aliases: ssl_ca_cert
-
-
- client_cert - -
- - -
-
- - -
Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.
-

aliases: cert_file
-
-
- client_key - -
- - -
-
- - -
Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.
-

aliases: key_file
-
-
- context - -
- - -
-
- - -
The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.
-
-
- host - -
- - -
-
- - -
Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.
-
-
- kubeconfig - -
- - -
-
- - -
Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from ~/.kube/config. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.
-
-
- name - -
- - -
-
- - -
Optional name to assign to the cluster. If not provided, a name is constructed from the server and port.
-
-
- namespaces - -
- - -
-
- - -
List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized to access.
-
-
- password - -
- - -
-
- - -
Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.
-
-
- username - -
- - -
-
- - -
Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.
-
-
- validate_certs - -
- boolean -
-
-
    Choices: -
  • no
  • -
  • yes
  • -
-
- -
Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.
-

aliases: verify_ssl
-
-
- plugin - -
- - - / required -
-
-
    Choices: -
  • kubernetes.core.k8s
  • -
  • k8s
  • -
  • community.kubernetes.k8s
  • -
-
- -
token that ensures this is a source file for the 'k8s' plugin.
-
-
- - - - -Examples --------- - -.. code-block:: yaml - - # File must be named k8s.yaml or k8s.yml - - - name: Authenticate with token, and return all pods and services for all namespaces - plugin: kubernetes.core.k8s - connections: - - host: https://192.168.64.4:8443 - api_key: xxxxxxxxxxxxxxxx - validate_certs: false - - - name: Use default config (~/.kube/config) file and active context, and return objects for a specific namespace - plugin: kubernetes.core.k8s - connections: - - namespaces: - - testing - - - name: Use a custom config file, and a specific context. - plugin: kubernetes.core.k8s - connections: - - kubeconfig: /path/to/config - context: 'awx/192-168-64-4:8443/developer' - - - - -Status ------- - - -- This inventory will be removed in version 6.0.0. *[deprecated]* -- For more information see `DEPRECATED`_. - - -Authors -~~~~~~~ - -- Chris Houseknecht (@chouseknecht) -- Fabian von Feilitzsch (@fabianvf) - - -.. hint:: - Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up. diff --git a/meta/runtime.yml b/meta/runtime.yml index 75c5db896a..4547408a63 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -21,11 +21,10 @@ plugin_routing: openshift: redirect: community.okd.openshift k8s: - deprecation: + tombstone: removal_version: 6.0.0 warning_text: >- - The k8s inventory plugin has been deprecated and - will be removed in release 6.0.0. + The k8s inventory plugin was slated for deprecation in 3.3.0 and has been removed in release 6.0.0. Use kubernetes.core.k8s_info and ansible.builtin.add_host instead. modules: k8s_auth: redirect: community.okd.k8s_auth diff --git a/plugins/inventory/k8s.py b/plugins/inventory/k8s.py deleted file mode 100644 index 69957ce18b..0000000000 --- a/plugins/inventory/k8s.py +++ /dev/null @@ -1,476 +0,0 @@ -# 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 = """ - name: k8s - author: - - Chris Houseknecht (@chouseknecht) - - Fabian von Feilitzsch (@fabianvf) - - short_description: Kubernetes (K8s) inventory source - - description: - - Fetch containers and services for one or more clusters. - - Groups by cluster name, namespace, namespace_services, namespace_pods, and labels. - - Uses the kubectl connection plugin to access the Kubernetes cluster. - - Uses k8s.(yml|yaml) YAML configuration file to set parameter values. - - deprecated: - removed_in: 6.0.0 - why: | - As discussed in U(https://github.com/ansible-collections/kubernetes.core/issues/31), we decided to - remove the k8s inventory plugin in release 6.0.0. - alternative: "Use M(kubernetes.core.k8s_info) and M(ansible.builtin.add_host) instead." - - options: - plugin: - description: token that ensures this is a source file for the 'k8s' plugin. - required: True - choices: ['kubernetes.core.k8s', 'k8s', 'community.kubernetes.k8s'] - connections: - description: - - Optional list of cluster connection settings. If no connections are provided, the default - I(~/.kube/config) and active context will be used, and objects will be returned for all namespaces - the active user is authorized to access. - suboptions: - name: - description: - - Optional name to assign to the cluster. If not provided, a name is constructed from the server - and port. - kubeconfig: - description: - - Path to an existing Kubernetes config file. If not provided, and no other connection - options are provided, the Kubernetes client will attempt to load the default - configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG - environment variable. - context: - description: - - The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment - variable. - host: - description: - - Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable. - api_key: - description: - - Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment - variable. - username: - description: - - Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME - environment variable. - password: - description: - - Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD - environment variable. - client_cert: - description: - - Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE - environment variable. - aliases: [ cert_file ] - client_key: - description: - - Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE - environment variable. - aliases: [ key_file ] - ca_cert: - description: - - Path to a CA certificate used to authenticate with the API. Can also be specified via - K8S_AUTH_SSL_CA_CERT environment variable. - aliases: [ ssl_ca_cert ] - validate_certs: - description: - - "Whether or not to verify the API server's SSL certificates. Can also be specified via - K8S_AUTH_VERIFY_SSL environment variable." - type: bool - aliases: [ verify_ssl ] - namespaces: - description: - - List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized - to access. - - requirements: - - "python >= 3.9" - - "kubernetes >= 24.2.0" - - "PyYAML >= 3.11" -""" - -EXAMPLES = r""" -# File must be named k8s.yaml or k8s.yml - -- name: Authenticate with token, and return all pods and services for all namespaces - plugin: kubernetes.core.k8s - connections: - - host: https://192.168.64.4:8443 - api_key: xxxxxxxxxxxxxxxx - validate_certs: false - -- name: Use default config (~/.kube/config) file and active context, and return objects for a specific namespace - plugin: kubernetes.core.k8s - connections: - - namespaces: - - testing - -- name: Use a custom config file, and a specific context. - plugin: kubernetes.core.k8s - connections: - - kubeconfig: /path/to/config - context: 'awx/192-168-64-4:8443/developer' -""" - -import json - -from ansible.errors import AnsibleError -from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable - -try: - from kubernetes.dynamic.exceptions import DynamicApiError - - HAS_K8S_MODULE_HELPER = True - k8s_import_exception = None -except ImportError as e: - HAS_K8S_MODULE_HELPER = False - k8s_import_exception = e -from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import ( - get_api_client, -) - - -def format_dynamic_api_exc(exc): - if exc.body: - if exc.headers and exc.headers.get("Content-Type") == "application/json": - message = json.loads(exc.body).get("message") - if message: - return message - return exc.body - else: - return "%s Reason: %s" % (exc.status, exc.reason) - - -class K8sInventoryException(Exception): - pass - - -class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): - NAME = "kubernetes.core.k8s" - - connection_plugin = "kubernetes.core.kubectl" - transport = "kubectl" - - def parse(self, inventory, loader, path, cache=True): - super(InventoryModule, self).parse(inventory, loader, path) - - self.display.deprecated( - "The 'k8s' inventory plugin has been deprecated and will be removed in release 6.0.0", - version="6.0.0", - collection_name="kubernetes.core", - ) - cache_key = self._get_cache_prefix(path) - config_data = self._read_config_data(path) - self.setup(config_data, cache, cache_key) - - def setup(self, config_data, cache, cache_key): - connections = config_data.get("connections") - - if not HAS_K8S_MODULE_HELPER: - raise K8sInventoryException( - "This module requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format( - k8s_import_exception - ) - ) - - source_data = None - if cache and cache_key in self._cache: - try: - source_data = self._cache[cache_key] - except KeyError: - pass - - if not source_data: - self.fetch_objects(connections) - - def fetch_objects(self, connections): - if connections: - if not isinstance(connections, list): - raise K8sInventoryException("Expecting connections to be a list.") - - for connection in connections: - if not isinstance(connection, dict): - raise K8sInventoryException( - "Expecting connection to be a dictionary." - ) - client = get_api_client(**connection) - name = connection.get( - "name", self.get_default_host_name(client.configuration.host) - ) - if connection.get("namespaces"): - namespaces = connection["namespaces"] - else: - namespaces = self.get_available_namespaces(client) - for namespace in namespaces: - self.get_pods_for_namespace(client, name, namespace) - self.get_services_for_namespace(client, name, namespace) - else: - client = get_api_client() - name = self.get_default_host_name(client.configuration.host) - namespaces = self.get_available_namespaces(client) - for namespace in namespaces: - self.get_pods_for_namespace(client, name, namespace) - self.get_services_for_namespace(client, name, namespace) - - @staticmethod - def get_default_host_name(host): - return ( - host.replace("https://", "") - .replace("http://", "") - .replace(".", "-") - .replace(":", "_") - ) - - def get_available_namespaces(self, client): - v1_namespace = client.resources.get(api_version="v1", kind="Namespace") - try: - obj = v1_namespace.get() - except DynamicApiError as exc: - self.display.debug(exc) - raise K8sInventoryException( - "Error fetching Namespace list: %s" % format_dynamic_api_exc(exc) - ) - return [namespace.metadata.name for namespace in obj.items] - - def get_pods_for_namespace(self, client, name, namespace): - v1_pod = client.resources.get(api_version="v1", kind="Pod") - try: - obj = v1_pod.get(namespace=namespace) - except DynamicApiError as exc: - self.display.debug(exc) - raise K8sInventoryException( - "Error fetching Pod list: %s" % format_dynamic_api_exc(exc) - ) - - namespace_group = "namespace_{0}".format(namespace) - namespace_pods_group = "{0}_pods".format(namespace_group) - - self.inventory.add_group(name) - self.inventory.add_group(namespace_group) - self.inventory.add_child(name, namespace_group) - self.inventory.add_group(namespace_pods_group) - self.inventory.add_child(namespace_group, namespace_pods_group) - - for pod in obj.items: - pod_name = pod.metadata.name - pod_groups = [] - pod_annotations = ( - {} if not pod.metadata.annotations else dict(pod.metadata.annotations) - ) - - if pod.metadata.labels: - # create a group for each label_value - for key, value in pod.metadata.labels: - group_name = "label_{0}_{1}".format(key, value) - if group_name not in pod_groups: - pod_groups.append(group_name) - self.inventory.add_group(group_name) - pod_labels = dict(pod.metadata.labels) - else: - pod_labels = {} - - if not pod.status.containerStatuses: - continue - - for container in pod.status.containerStatuses: - # add each pod_container to the namespace group, and to each label_value group - container_name = "{0}_{1}".format(pod.metadata.name, container.name) - self.inventory.add_host(container_name) - self.inventory.add_child(namespace_pods_group, container_name) - if pod_groups: - for group in pod_groups: - self.inventory.add_child(group, container_name) - - # Add hostvars - self.inventory.set_variable(container_name, "object_type", "pod") - self.inventory.set_variable(container_name, "labels", pod_labels) - self.inventory.set_variable( - container_name, "annotations", pod_annotations - ) - self.inventory.set_variable( - container_name, "cluster_name", pod.metadata.clusterName - ) - self.inventory.set_variable( - container_name, "pod_node_name", pod.spec.nodeName - ) - self.inventory.set_variable(container_name, "pod_name", pod.spec.name) - self.inventory.set_variable( - container_name, "pod_host_ip", pod.status.hostIP - ) - self.inventory.set_variable( - container_name, "pod_phase", pod.status.phase - ) - self.inventory.set_variable(container_name, "pod_ip", pod.status.podIP) - self.inventory.set_variable( - container_name, "pod_self_link", pod.metadata.selfLink - ) - self.inventory.set_variable( - container_name, "pod_resource_version", pod.metadata.resourceVersion - ) - self.inventory.set_variable(container_name, "pod_uid", pod.metadata.uid) - self.inventory.set_variable( - container_name, "container_name", container.image - ) - self.inventory.set_variable( - container_name, "container_image", container.image - ) - if container.state.running: - self.inventory.set_variable( - container_name, "container_state", "Running" - ) - if container.state.terminated: - self.inventory.set_variable( - container_name, "container_state", "Terminated" - ) - if container.state.waiting: - self.inventory.set_variable( - container_name, "container_state", "Waiting" - ) - self.inventory.set_variable( - container_name, "container_ready", container.ready - ) - self.inventory.set_variable( - container_name, "ansible_remote_tmp", "/tmp/" - ) - self.inventory.set_variable( - container_name, "ansible_connection", self.connection_plugin - ) - self.inventory.set_variable( - container_name, "ansible_{0}_pod".format(self.transport), pod_name - ) - self.inventory.set_variable( - container_name, - "ansible_{0}_container".format(self.transport), - container.name, - ) - self.inventory.set_variable( - container_name, - "ansible_{0}_namespace".format(self.transport), - namespace, - ) - - def get_services_for_namespace(self, client, name, namespace): - v1_service = client.resources.get(api_version="v1", kind="Service") - try: - obj = v1_service.get(namespace=namespace) - except DynamicApiError as exc: - self.display.debug(exc) - raise K8sInventoryException( - "Error fetching Service list: %s" % format_dynamic_api_exc(exc) - ) - - namespace_group = "namespace_{0}".format(namespace) - namespace_services_group = "{0}_services".format(namespace_group) - - self.inventory.add_group(name) - self.inventory.add_group(namespace_group) - self.inventory.add_child(name, namespace_group) - self.inventory.add_group(namespace_services_group) - self.inventory.add_child(namespace_group, namespace_services_group) - - for service in obj.items: - service_name = service.metadata.name - service_labels = ( - {} if not service.metadata.labels else dict(service.metadata.labels) - ) - service_annotations = ( - {} - if not service.metadata.annotations - else dict(service.metadata.annotations) - ) - - self.inventory.add_host(service_name) - - if service.metadata.labels: - # create a group for each label_value - for key, value in service.metadata.labels: - group_name = "label_{0}_{1}".format(key, value) - self.inventory.add_group(group_name) - self.inventory.add_child(group_name, service_name) - - try: - self.inventory.add_child(namespace_services_group, service_name) - except AnsibleError: - raise - - ports = [ - { - "name": port.name, - "port": port.port, - "protocol": port.protocol, - "targetPort": port.targetPort, - "nodePort": port.nodePort, - } - for port in service.spec.ports or [] - ] - - # add hostvars - self.inventory.set_variable(service_name, "object_type", "service") - self.inventory.set_variable(service_name, "labels", service_labels) - self.inventory.set_variable( - service_name, "annotations", service_annotations - ) - self.inventory.set_variable( - service_name, "cluster_name", service.metadata.clusterName - ) - self.inventory.set_variable(service_name, "ports", ports) - self.inventory.set_variable(service_name, "type", service.spec.type) - self.inventory.set_variable( - service_name, "self_link", service.metadata.selfLink - ) - self.inventory.set_variable( - service_name, "resource_version", service.metadata.resourceVersion - ) - self.inventory.set_variable(service_name, "uid", service.metadata.uid) - - if service.spec.externalTrafficPolicy: - self.inventory.set_variable( - service_name, - "external_traffic_policy", - service.spec.externalTrafficPolicy, - ) - if service.spec.externalIPs: - self.inventory.set_variable( - service_name, "external_ips", service.spec.externalIPs - ) - - if service.spec.externalName: - self.inventory.set_variable( - service_name, "external_name", service.spec.externalName - ) - - if service.spec.healthCheckNodePort: - self.inventory.set_variable( - service_name, - "health_check_node_port", - service.spec.healthCheckNodePort, - ) - if service.spec.loadBalancerIP: - self.inventory.set_variable( - service_name, "load_balancer_ip", service.spec.loadBalancerIP - ) - if service.spec.selector: - self.inventory.set_variable( - service_name, "selector", dict(service.spec.selector) - ) - - if ( - hasattr(service.status.loadBalancer, "ingress") - and service.status.loadBalancer.ingress - ): - load_balancer = [ - {"hostname": ingress.hostname, "ip": ingress.ip} - for ingress in service.status.loadBalancer.ingress - ] - self.inventory.set_variable( - service_name, "load_balancer", load_balancer - ) diff --git a/tests/integration/targets/inventory_k8s/aliases b/tests/integration/targets/inventory_k8s/aliases deleted file mode 100644 index c023328eb5..0000000000 --- a/tests/integration/targets/inventory_k8s/aliases +++ /dev/null @@ -1,3 +0,0 @@ -context/target -time=42 -k8s diff --git a/tests/integration/targets/inventory_k8s/playbooks/create_resources.yml b/tests/integration/targets/inventory_k8s/playbooks/create_resources.yml deleted file mode 100644 index 7e16f94271..0000000000 --- a/tests/integration/targets/inventory_k8s/playbooks/create_resources.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -- name: Create inventory files - hosts: localhost - gather_facts: false - - collections: - - kubernetes.core - - roles: - - role: setup_kubeconfig - kubeconfig_operation: 'save' - - tasks: - - name: Create inventory files - copy: - content: "{{ item.content }}" - dest: "{{ item.path }}" - vars: - hostname: "{{ lookup('file', user_credentials_dir + '/host_data.txt') }}" - test_cert_file: "{{ user_credentials_dir | realpath + '/cert_file_data.txt' }}" - test_key_file: "{{ user_credentials_dir | realpath + '/key_file_data.txt' }}" - test_ca_cert: "{{ user_credentials_dir | realpath + '/ssl_ca_cert_data.txt' }}" - with_items: - - path: "test_inventory_aliases_with_ssl_k8s.yml" - content: | - --- - plugin: kubernetes.core.k8s - connections: - - namespaces: - - inventory - host: "{{ hostname }}" - cert_file: "{{ test_cert_file }}" - key_file: "{{ test_key_file }}" - verify_ssl: true - ssl_ca_cert: "{{ test_ca_cert }}" - - path: "test_inventory_aliases_no_ssl_k8s.yml" - content: | - --- - plugin: kubernetes.core.k8s - connections: - - namespaces: - - inventory - host: "{{ hostname }}" - cert_file: "{{ test_cert_file }}" - key_file: "{{ test_key_file }}" - verify_ssl: false diff --git a/tests/integration/targets/inventory_k8s/playbooks/delete_resources.yml b/tests/integration/targets/inventory_k8s/playbooks/delete_resources.yml deleted file mode 100644 index ec09ec5cf2..0000000000 --- a/tests/integration/targets/inventory_k8s/playbooks/delete_resources.yml +++ /dev/null @@ -1,30 +0,0 @@ ---- -- name: Delete inventory namespace - hosts: localhost - connection: local - gather_facts: true - - roles: - - role: setup_kubeconfig - kubeconfig_operation: 'revert' - - tasks: - - name: Delete temporary files - file: - state: absent - path: "{{ user_credentials_dir ~ '/' ~ item }}" - ignore_errors: true - with_items: - - test_inventory_aliases_with_ssl_k8s.yml - - test_inventory_aliases_no_ssl_k8s.yml - - ssl_ca_cert_data.txt - - key_file_data.txt - - cert_file_data.txt - - host_data.txt - - - name: Remove inventory namespace - k8s: - api_version: v1 - kind: Namespace - name: inventory - state: absent diff --git a/tests/integration/targets/inventory_k8s/playbooks/play.yml b/tests/integration/targets/inventory_k8s/playbooks/play.yml deleted file mode 100644 index 07baf1a3ab..0000000000 --- a/tests/integration/targets/inventory_k8s/playbooks/play.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -- name: Converge - hosts: localhost - connection: local - - collections: - - kubernetes.core - - vars_files: - - vars/main.yml - - tasks: - - name: Delete existing namespace - k8s: - api_version: v1 - kind: Namespace - name: inventory - wait: yes - state: absent - - - name: Ensure namespace exists - k8s: - api_version: v1 - kind: Namespace - name: inventory - - - name: Add a deployment - k8s: - definition: - apiVersion: apps/v1 - kind: Deployment - metadata: - name: inventory - namespace: inventory - spec: - replicas: 1 - selector: - matchLabels: - app: "{{ k8s_pod_name }}" - template: "{{ k8s_pod_template }}" - wait: yes - wait_timeout: 400 - vars: - k8s_pod_name: inventory - k8s_pod_image: python - k8s_pod_command: - - python - - '-m' - - http.server - k8s_pod_env: - - name: TEST - value: test - - - meta: refresh_inventory - -- name: Verify inventory and connection plugins - hosts: namespace_inventory_pods - gather_facts: no - - vars: - file_content: | - Hello world - - tasks: - - name: End play if host not running (TODO should we not add these to the inventory?) - meta: end_host - when: pod_phase != "Running" - - - debug: var=hostvars - - setup: - - - debug: var=ansible_facts - - - name: Assert the TEST environment variable was retrieved - assert: - that: ansible_facts.env.TEST == 'test' - - - name: Copy a file into the host - copy: - content: '{{ file_content }}' - dest: /tmp/test_file - - - name: Retrieve the file from the host - slurp: - src: /tmp/test_file - register: slurped_file - - - name: Assert the file content matches expectations - assert: - that: (slurped_file.content|b64decode) == file_content diff --git a/tests/integration/targets/inventory_k8s/playbooks/test.inventory_k8s.yml b/tests/integration/targets/inventory_k8s/playbooks/test.inventory_k8s.yml deleted file mode 100644 index cdbb9316e6..0000000000 --- a/tests/integration/targets/inventory_k8s/playbooks/test.inventory_k8s.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -plugin: kubernetes.core.k8s diff --git a/tests/integration/targets/inventory_k8s/playbooks/vars/main.yml b/tests/integration/targets/inventory_k8s/playbooks/vars/main.yml deleted file mode 100644 index 5656784f4c..0000000000 --- a/tests/integration/targets/inventory_k8s/playbooks/vars/main.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -k8s_pod_metadata: - labels: - app: "{{ k8s_pod_name }}" - -k8s_pod_spec: - serviceAccount: "{{ k8s_pod_service_account }}" - containers: - - image: "{{ k8s_pod_image }}" - imagePullPolicy: Always - name: "{{ k8s_pod_name }}" - command: "{{ k8s_pod_command }}" - readinessProbe: - initialDelaySeconds: 15 - exec: - command: - - /bin/true - resources: "{{ k8s_pod_resources }}" - ports: "{{ k8s_pod_ports }}" - env: "{{ k8s_pod_env }}" - - -k8s_pod_service_account: default - -k8s_pod_resources: - limits: - cpu: "100m" - memory: "100Mi" - -k8s_pod_command: [] - -k8s_pod_ports: [] - -k8s_pod_env: [] - -k8s_pod_template: - metadata: "{{ k8s_pod_metadata }}" - spec: "{{ k8s_pod_spec }}" diff --git a/tests/integration/targets/inventory_k8s/runme.sh b/tests/integration/targets/inventory_k8s/runme.sh deleted file mode 100755 index 0691d8d5d9..0000000000 --- a/tests/integration/targets/inventory_k8s/runme.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -export ANSIBLE_ROLES_PATH="../" -USER_CREDENTIALS_DIR=$(pwd) - -ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@" - -{ -export ANSIBLE_CALLBACKS_ENABLED=profile_tasks -export ANSIBLE_INVENTORY_ENABLED=kubernetes.core.k8s,yaml -export ANSIBLE_PYTHON_INTERPRETER=auto_silent - -ansible-playbook playbooks/play.yml -i playbooks/test.inventory_k8s.yml "$@" && - -ansible-playbook playbooks/create_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@" && - -ansible-inventory -i playbooks/test_inventory_aliases_with_ssl_k8s.yml --list "$@" && - -ansible-inventory -i playbooks/test_inventory_aliases_no_ssl_k8s.yml --list "$@" && - -unset ANSIBLE_INVENTORY_ENABLED && - -ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@" - -} || { - ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@" - exit 1 -} \ No newline at end of file From 17f41c4c80a2acedee68a432dc617aa54440de4d Mon Sep 17 00:00:00 2001 From: Yuriy Novostavskiy Date: Tue, 21 Jan 2025 19:56:07 +0200 Subject: [PATCH 4/5] Sanity fix by temporarily replacing 6.0.0 with 6.0.0-dev0 in meta/runtime.yml Version 6.0.0-dev0 MUST be replaced with 6.0.0 in the release 6.0.0 PR/commit --- meta/runtime.yml | 3 ++- tests/sanity/ignore-2.14.txt | 31 ------------------------------- 2 files changed, 2 insertions(+), 32 deletions(-) delete mode 100644 tests/sanity/ignore-2.14.txt diff --git a/meta/runtime.yml b/meta/runtime.yml index 4547408a63..bde8842f6e 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -22,7 +22,8 @@ plugin_routing: redirect: community.okd.openshift k8s: tombstone: - removal_version: 6.0.0 + # To be replaced with 6.0.0 in release 6.0.0 commit + removal_version: 6.0.0-dev0 warning_text: >- The k8s inventory plugin was slated for deprecation in 3.3.0 and has been removed in release 6.0.0. Use kubernetes.core.k8s_info and ansible.builtin.add_host instead. modules: diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt deleted file mode 100644 index bdcaf2c155..0000000000 --- a/tests/sanity/ignore-2.14.txt +++ /dev/null @@ -1,31 +0,0 @@ -plugins/module_utils/client/discovery.py import-3.9!skip -plugins/module_utils/client/discovery.py import-3.10!skip -plugins/module_utils/client/discovery.py import-3.11!skip -plugins/module_utils/client/resource.py import-3.9!skip -plugins/module_utils/client/resource.py import-3.10!skip -plugins/module_utils/client/resource.py import-3.11!skip -plugins/module_utils/k8sdynamicclient.py import-3.9!skip -plugins/module_utils/k8sdynamicclient.py import-3.10!skip -plugins/module_utils/k8sdynamicclient.py import-3.11!skip -plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc -plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc -plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc -tests/unit/module_utils/fixtures/clusteroperator.yml yamllint!skip -tests/unit/module_utils/fixtures/definitions.yml yamllint!skip -tests/unit/module_utils/fixtures/deployments.yml yamllint!skip -tests/unit/module_utils/fixtures/pods.yml yamllint!skip -tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip -tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip -tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml yamllint!skip -tests/integration/targets/helm/files/test-chart/templates/configmap.yaml yamllint!skip -tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml yamllint!skip -tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip -plugins/modules/k8s.py validate-modules:return-syntax-error -plugins/modules/k8s_scale.py validate-modules:return-syntax-error -plugins/modules/k8s_service.py validate-modules:return-syntax-error -plugins/modules/k8s_taint.py validate-modules:return-syntax-error -tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip -tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip -tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip -tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip - From 02efb68db3cdd1edfc329370e64b599d6797ae15 Mon Sep 17 00:00:00 2001 From: Yuriy Novostavskiy Date: Wed, 23 Apr 2025 00:02:11 +0300 Subject: [PATCH 5/5] remove sanity ignore for 2.15, add for 2.20 reson for that commit is a stable-2.19 branch of ansible that means that devel and milestone switched to 2.20 --- tests/sanity/{ignore-2.15.txt => ignore-2.20.txt} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename tests/sanity/{ignore-2.15.txt => ignore-2.20.txt} (84%) diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.20.txt similarity index 84% rename from tests/sanity/ignore-2.15.txt rename to tests/sanity/ignore-2.20.txt index f534f27a3e..d6216adfd5 100644 --- a/tests/sanity/ignore-2.15.txt +++ b/tests/sanity/ignore-2.20.txt @@ -1,12 +1,12 @@ -plugins/module_utils/client/discovery.py import-3.9!skip -plugins/module_utils/client/discovery.py import-3.10!skip plugins/module_utils/client/discovery.py import-3.11!skip -plugins/module_utils/client/resource.py import-3.9!skip -plugins/module_utils/client/resource.py import-3.10!skip +plugins/module_utils/client/discovery.py import-3.12!skip +plugins/module_utils/client/discovery.py import-3.13!skip plugins/module_utils/client/resource.py import-3.11!skip -plugins/module_utils/k8sdynamicclient.py import-3.9!skip -plugins/module_utils/k8sdynamicclient.py import-3.10!skip +plugins/module_utils/client/resource.py import-3.12!skip +plugins/module_utils/client/resource.py import-3.13!skip plugins/module_utils/k8sdynamicclient.py import-3.11!skip +plugins/module_utils/k8sdynamicclient.py import-3.12!skip +plugins/module_utils/k8sdynamicclient.py import-3.13!skip plugins/module_utils/version.py pylint!skip plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc