mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-03-26 21:33:02 +00:00
Merge pull request #481 from ansible-collections/2.x-refactor
Refactor common.py
This commit is contained in:
3
changelogs/fragments/481-refactor-common.yml
Normal file
3
changelogs/fragments/481-refactor-common.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
major_changes:
|
||||
- refactor K8sAnsibleMixin into module_utils/k8s/ (https://github.com/ansible-collections/kubernetes.core/pull/481).
|
||||
@@ -130,6 +130,7 @@ except ImportError as e:
|
||||
|
||||
|
||||
def configuration_digest(configuration, **kwargs):
|
||||
"""This function has been deprecated and will be removed in version 4.0.0."""
|
||||
m = hashlib.sha256()
|
||||
for k in AUTH_ARG_MAP:
|
||||
if not hasattr(configuration, k):
|
||||
@@ -150,6 +151,8 @@ def configuration_digest(configuration, **kwargs):
|
||||
|
||||
|
||||
class unique_string(str):
|
||||
"""This function has been deprecated and will be removed in version 4.0.0."""
|
||||
|
||||
_low = None
|
||||
|
||||
def __hash__(self):
|
||||
@@ -169,6 +172,7 @@ class unique_string(str):
|
||||
|
||||
|
||||
def get_api_client(module=None, **kwargs):
|
||||
"""This function has been deprecated and will be removed in version 4.0.0. Please use module_utils.k8s.client.get_api_client() instead."""
|
||||
auth = {}
|
||||
|
||||
def _raise_or_fail(exc, msg):
|
||||
@@ -340,6 +344,11 @@ get_api_client._pool = {}
|
||||
|
||||
class K8sAnsibleMixin(object):
|
||||
def __init__(self, module, pyyaml_required=True, *args, **kwargs):
|
||||
module.deprecate(
|
||||
msg="The K8sAnsibleMixin class has been deprecated and refactored into the module_utils/k8s/ directory.",
|
||||
version="4.0.0",
|
||||
collection_name="kubernetes.core",
|
||||
)
|
||||
if not HAS_K8S_MODULE_HELPER:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib("kubernetes"),
|
||||
|
||||
@@ -24,6 +24,9 @@ from abc import ABCMeta, abstractmethod
|
||||
import tarfile
|
||||
|
||||
# from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
@@ -376,12 +379,17 @@ class K8SCopyToPod(K8SCopy):
|
||||
)
|
||||
|
||||
|
||||
def check_pod(k8s_ansible_mixin, module):
|
||||
resource = k8s_ansible_mixin.find_resource("Pod", None, True)
|
||||
def check_pod(svc):
|
||||
module = svc.module
|
||||
namespace = module.params.get("namespace")
|
||||
name = module.params.get("pod")
|
||||
container = module.params.get("container")
|
||||
|
||||
try:
|
||||
resource = svc.find_resource("Pod", None, True)
|
||||
except CoreException as e:
|
||||
module.fail_json(msg=to_native(e))
|
||||
|
||||
def _fail(exc):
|
||||
arg = {}
|
||||
if hasattr(exc, "body"):
|
||||
@@ -398,7 +406,7 @@ def check_pod(k8s_ansible_mixin, module):
|
||||
module.fail_json(msg=msg, **arg)
|
||||
|
||||
try:
|
||||
result = resource.get(name=name, namespace=namespace)
|
||||
result = svc.client.get(resource, name=name, namespace=namespace)
|
||||
containers = [
|
||||
c["name"] for c in result.to_dict()["status"]["containerStatuses"]
|
||||
]
|
||||
|
||||
355
plugins/module_utils/k8s/client.py
Normal file
355
plugins/module_utils/k8s/client.py
Normal file
@@ -0,0 +1,355 @@
|
||||
# Copyright: (c) 2021, Red Hat | Ansible
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from ansible.module_utils.six import iteritems, string_types
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_MAP,
|
||||
AUTH_ARG_SPEC,
|
||||
AUTH_PROXY_HEADERS_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
requires as _requires,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils import (
|
||||
k8sdynamicclient,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.discovery import (
|
||||
LazyDiscoverer,
|
||||
)
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
try:
|
||||
import kubernetes
|
||||
from kubernetes.dynamic.exceptions import (
|
||||
ResourceNotFoundError,
|
||||
ResourceNotUniqueError,
|
||||
)
|
||||
from kubernetes.dynamic.resource import Resource
|
||||
except ImportError:
|
||||
# kubernetes import error is handled in module setup
|
||||
# This is defined only for the sake of Ansible's checked import requirement
|
||||
Resource = Any # type: ignore
|
||||
|
||||
try:
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings()
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
|
||||
_pool = {}
|
||||
|
||||
|
||||
class unique_string(str):
|
||||
_low = None
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self is other
|
||||
|
||||
def lower(self):
|
||||
if self._low is None:
|
||||
lower = str.lower(self)
|
||||
if str.__eq__(lower, self):
|
||||
self._low = self
|
||||
else:
|
||||
self._low = unique_string(lower)
|
||||
return self._low
|
||||
|
||||
|
||||
def _create_auth_spec(module=None, **kwargs) -> Dict:
|
||||
auth: Dict = {}
|
||||
# If authorization variables aren't defined, look for them in environment variables
|
||||
for true_name, arg_name in AUTH_ARG_MAP.items():
|
||||
if module and module.params.get(arg_name) is not None:
|
||||
auth[true_name] = module.params.get(arg_name)
|
||||
elif arg_name in kwargs and kwargs.get(arg_name) is not None:
|
||||
auth[true_name] = kwargs.get(arg_name)
|
||||
elif arg_name == "proxy_headers":
|
||||
# specific case for 'proxy_headers' which is a dictionary
|
||||
proxy_headers = {}
|
||||
for key in AUTH_PROXY_HEADERS_SPEC.keys():
|
||||
env_value = os.getenv(
|
||||
"K8S_AUTH_PROXY_HEADERS_{0}".format(key.upper()), None
|
||||
)
|
||||
if env_value is not None:
|
||||
if AUTH_PROXY_HEADERS_SPEC[key].get("type") == "bool":
|
||||
env_value = env_value.lower() not in ["0", "false", "no"]
|
||||
proxy_headers[key] = env_value
|
||||
if proxy_headers is not {}:
|
||||
auth[true_name] = proxy_headers
|
||||
else:
|
||||
env_value = os.getenv(
|
||||
"K8S_AUTH_{0}".format(arg_name.upper()), None
|
||||
) or os.getenv("K8S_AUTH_{0}".format(true_name.upper()), None)
|
||||
if env_value is not None:
|
||||
if AUTH_ARG_SPEC[arg_name].get("type") == "bool":
|
||||
env_value = env_value.lower() not in ["0", "false", "no"]
|
||||
auth[true_name] = env_value
|
||||
|
||||
return auth
|
||||
|
||||
|
||||
def _load_config(auth: Dict) -> None:
|
||||
kubeconfig = auth.get("kubeconfig")
|
||||
optional_arg = {
|
||||
"context": auth.get("context"),
|
||||
"persist_config": auth.get("persist_config"),
|
||||
}
|
||||
if kubeconfig:
|
||||
if isinstance(kubeconfig, string_types):
|
||||
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||
elif isinstance(kubeconfig, dict):
|
||||
kubernetes.config.load_kube_config_from_dict(
|
||||
config_dict=kubeconfig, **optional_arg
|
||||
)
|
||||
else:
|
||||
kubernetes.config.load_kube_config(config_file=None, **optional_arg)
|
||||
|
||||
|
||||
def _create_configuration(auth: Dict):
|
||||
def auth_set(*names: list) -> bool:
|
||||
return all(auth.get(name) for name in names)
|
||||
|
||||
if auth_set("host"):
|
||||
# Removing trailing slashes if any from hostname
|
||||
auth["host"] = auth.get("host").rstrip("/")
|
||||
|
||||
if auth_set("username", "password", "host") or auth_set("api_key", "host"):
|
||||
# We have enough in the parameters to authenticate, no need to load incluster or kubeconfig
|
||||
pass
|
||||
elif auth_set("kubeconfig") or auth_set("context"):
|
||||
try:
|
||||
_load_config(auth)
|
||||
except Exception as err:
|
||||
raise err
|
||||
|
||||
else:
|
||||
# First try to do incluster config, then kubeconfig
|
||||
try:
|
||||
kubernetes.config.load_incluster_config()
|
||||
except kubernetes.config.ConfigException:
|
||||
try:
|
||||
_load_config(auth)
|
||||
except Exception as err:
|
||||
raise err
|
||||
|
||||
# Override any values in the default configuration with Ansible parameters
|
||||
# As of kubernetes-client v12.0.0, get_default_copy() is required here
|
||||
try:
|
||||
configuration = kubernetes.client.Configuration().get_default_copy()
|
||||
except AttributeError:
|
||||
configuration = kubernetes.client.Configuration()
|
||||
|
||||
for key, value in iteritems(auth):
|
||||
if key in AUTH_ARG_MAP.keys() and value is not None:
|
||||
if key == "api_key":
|
||||
setattr(
|
||||
configuration, key, {"authorization": "Bearer {0}".format(value)}
|
||||
)
|
||||
elif key == "proxy_headers":
|
||||
headers = urllib3.util.make_headers(**value)
|
||||
setattr(configuration, key, headers)
|
||||
else:
|
||||
setattr(configuration, key, value)
|
||||
|
||||
return configuration
|
||||
|
||||
|
||||
def _create_headers(module=None, **kwargs):
|
||||
header_map = {
|
||||
"impersonate_user": "Impersonate-User",
|
||||
"impersonate_groups": "Impersonate-Group",
|
||||
}
|
||||
|
||||
headers = {}
|
||||
for arg_name, header_name in header_map.items():
|
||||
value = None
|
||||
if module and module.params.get(arg_name) is not None:
|
||||
value = module.params.get(arg_name)
|
||||
elif arg_name in kwargs and kwargs.get(arg_name) is not None:
|
||||
value = kwargs.get(arg_name)
|
||||
else:
|
||||
value = os.getenv("K8S_AUTH_{0}".format(arg_name.upper()), None)
|
||||
if value is not None:
|
||||
if AUTH_ARG_SPEC[arg_name].get("type") == "list":
|
||||
value = [x for x in value.split(",") if x != ""]
|
||||
if value:
|
||||
headers[header_name] = value
|
||||
return headers
|
||||
|
||||
|
||||
def _configuration_digest(configuration, **kwargs) -> str:
|
||||
m = hashlib.sha256()
|
||||
for k in AUTH_ARG_MAP:
|
||||
if not hasattr(configuration, k):
|
||||
v = None
|
||||
else:
|
||||
v = getattr(configuration, k)
|
||||
if v and k in ["ssl_ca_cert", "cert_file", "key_file"]:
|
||||
with open(str(v), "r") as fd:
|
||||
content = fd.read()
|
||||
m.update(content.encode())
|
||||
else:
|
||||
m.update(str(v).encode())
|
||||
for k, v in kwargs.items():
|
||||
content = "{0}: {1}".format(k, v)
|
||||
m.update(content.encode())
|
||||
digest = m.hexdigest()
|
||||
|
||||
return digest
|
||||
|
||||
|
||||
def _set_header(client, header, value):
|
||||
if isinstance(value, list):
|
||||
for v in value:
|
||||
client.set_default_header(header_name=unique_string(header), header_value=v)
|
||||
else:
|
||||
client.set_default_header(header_name=header, header_value=value)
|
||||
|
||||
|
||||
def cache(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
client = None
|
||||
hashable_kwargs = {}
|
||||
for k, v in kwargs.items():
|
||||
if isinstance(v, list):
|
||||
hashable_kwargs[k] = ",".join(sorted(v))
|
||||
else:
|
||||
hashable_kwargs[k] = v
|
||||
digest = _configuration_digest(*args, **hashable_kwargs)
|
||||
if digest in _pool:
|
||||
client = _pool[digest]
|
||||
else:
|
||||
client = func(*args, **kwargs)
|
||||
_pool[digest] = client
|
||||
|
||||
return client
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@cache
|
||||
def create_api_client(configuration, **headers):
|
||||
client = kubernetes.client.ApiClient(configuration)
|
||||
for header, value in headers.items():
|
||||
_set_header(client, header, value)
|
||||
return k8sdynamicclient.K8SDynamicClient(client, discoverer=LazyDiscoverer)
|
||||
|
||||
|
||||
class K8SClient:
|
||||
"""A Client class for K8S modules.
|
||||
|
||||
This class has the primary purpose to proxy the kubernetes client and resource objects.
|
||||
If there is a need for other methods or attributes to be proxied, they can be added here.
|
||||
"""
|
||||
|
||||
def __init__(self, configuration, client, dry_run: bool = False) -> None:
|
||||
self.configuration = configuration
|
||||
self.client = client
|
||||
self.dry_run = dry_run
|
||||
|
||||
@property
|
||||
def resources(self) -> List[Any]:
|
||||
return self.client.resources
|
||||
|
||||
def _find_resource_with_prefix(
|
||||
self, prefix: str, kind: str, api_version: str
|
||||
) -> Resource:
|
||||
for attribute in ["kind", "name", "singular_name"]:
|
||||
try:
|
||||
return self.client.resources.get(
|
||||
**{"prefix": prefix, "api_version": api_version, attribute: kind}
|
||||
)
|
||||
except (ResourceNotFoundError, ResourceNotUniqueError):
|
||||
pass
|
||||
return self.client.resources.get(
|
||||
prefix=prefix, api_version=api_version, short_names=[kind]
|
||||
)
|
||||
|
||||
def resource(self, kind: str, api_version: str) -> Resource:
|
||||
"""Fetch a kubernetes client resource.
|
||||
|
||||
This will attempt to find a kubernetes resource trying, in order, kind,
|
||||
name, singular_name and short_names.
|
||||
"""
|
||||
try:
|
||||
if api_version == "v1":
|
||||
return self._find_resource_with_prefix("api", kind, api_version)
|
||||
except ResourceNotFoundError:
|
||||
pass
|
||||
return self._find_resource_with_prefix(None, kind, api_version)
|
||||
|
||||
def _ensure_dry_run(self, params: Dict) -> Dict:
|
||||
if self.dry_run:
|
||||
params["dry_run"] = True
|
||||
return params
|
||||
|
||||
def validate(
|
||||
self, resource, version: Optional[str] = None, strict: Optional[bool] = False
|
||||
):
|
||||
return self.client.validate(resource, version, strict)
|
||||
|
||||
def get(self, resource, **params):
|
||||
return resource.get(**params)
|
||||
|
||||
def delete(self, resource, **params):
|
||||
return resource.delete(**self._ensure_dry_run(params))
|
||||
|
||||
def apply(self, resource, definition, namespace, **params):
|
||||
return resource.apply(
|
||||
definition, namespace=namespace, **self._ensure_dry_run(params)
|
||||
)
|
||||
|
||||
def create(self, resource, definition, **params):
|
||||
return resource.create(definition, **self._ensure_dry_run(params))
|
||||
|
||||
def replace(self, resource, definition, **params):
|
||||
return resource.replace(definition, **self._ensure_dry_run(params))
|
||||
|
||||
def patch(self, resource, definition, **params):
|
||||
return resource.patch(definition, **self._ensure_dry_run(params))
|
||||
|
||||
|
||||
def get_api_client(module=None, **kwargs: Optional[Any]) -> K8SClient:
|
||||
auth_spec = _create_auth_spec(module, **kwargs)
|
||||
if module:
|
||||
requires = module.requires
|
||||
else:
|
||||
requires = _requires
|
||||
if isinstance(auth_spec.get("kubeconfig"), dict):
|
||||
requires("kubernetes", "17.17.0", "to use in-memory config")
|
||||
if auth_spec.get("no_proxy"):
|
||||
requires("kubernetes", "19.15.0", "to use the no_proxy feature")
|
||||
|
||||
try:
|
||||
configuration = _create_configuration(auth_spec)
|
||||
headers = _create_headers(module, **kwargs)
|
||||
client = create_api_client(configuration, **headers)
|
||||
except kubernetes.config.ConfigException as e:
|
||||
msg = "Could not create API client: {0}".format(e)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
k8s_client = K8SClient(
|
||||
configuration=configuration,
|
||||
client=client,
|
||||
dry_run=module.params.get("dry_run", False),
|
||||
)
|
||||
|
||||
return k8s_client
|
||||
171
plugins/module_utils/k8s/core.py
Normal file
171
plugins/module_utils/k8s/core.py
Normal file
@@ -0,0 +1,171 @@
|
||||
import traceback
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||
LooseVersion,
|
||||
)
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
|
||||
|
||||
class AnsibleK8SModule:
|
||||
"""A base module class for K8S modules.
|
||||
|
||||
This class should be used instead of directly using AnsibleModule. If there
|
||||
is a need for other methods or attributes to be proxied, they can be added
|
||||
here.
|
||||
"""
|
||||
|
||||
default_settings = {
|
||||
"check_k8s": True,
|
||||
"check_pyyaml": True,
|
||||
"module_class": AnsibleModule,
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
local_settings = {}
|
||||
for key in AnsibleK8SModule.default_settings:
|
||||
try:
|
||||
local_settings[key] = kwargs.pop(key)
|
||||
except KeyError:
|
||||
local_settings[key] = AnsibleK8SModule.default_settings[key]
|
||||
self.settings = local_settings
|
||||
|
||||
self._module = self.settings["module_class"](**kwargs)
|
||||
|
||||
if self.settings["check_k8s"]:
|
||||
self.requires("kubernetes")
|
||||
self.has_at_least("kubernetes", "12.0.0", warn=True)
|
||||
|
||||
if self.settings["check_pyyaml"]:
|
||||
self.requires("pyyaml")
|
||||
|
||||
@property
|
||||
def check_mode(self):
|
||||
return self._module.check_mode
|
||||
|
||||
@property
|
||||
def _diff(self):
|
||||
return self._module._diff
|
||||
|
||||
@property
|
||||
def _name(self):
|
||||
return self._module._name
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
return self._module.params
|
||||
|
||||
def warn(self, *args, **kwargs):
|
||||
return self._module.warn(*args, **kwargs)
|
||||
|
||||
def deprecate(self, *args, **kwargs):
|
||||
return self._module.deprecate(*args, **kwargs)
|
||||
|
||||
def debug(self, *args, **kwargs):
|
||||
return self._module.debug(*args, **kwargs)
|
||||
|
||||
def exit_json(self, *args, **kwargs):
|
||||
return self._module.exit_json(*args, **kwargs)
|
||||
|
||||
def fail_json(self, *args, **kwargs):
|
||||
return self._module.fail_json(*args, **kwargs)
|
||||
|
||||
def fail_from_exception(self, exception):
|
||||
msg = to_text(exception)
|
||||
tb = "".join(
|
||||
traceback.format_exception(None, exception, exception.__traceback__)
|
||||
)
|
||||
return self.fail_json(msg=msg, exception=tb)
|
||||
|
||||
def has_at_least(
|
||||
self, dependency: str, minimum: Optional[str] = None, warn: bool = False
|
||||
) -> bool:
|
||||
supported = has_at_least(dependency, minimum)
|
||||
if not supported and warn:
|
||||
self.warn(
|
||||
"{0}<{1} is not supported or tested. Some features may not work.".format(
|
||||
dependency, minimum
|
||||
)
|
||||
)
|
||||
return supported
|
||||
|
||||
def requires(
|
||||
self,
|
||||
dependency: str,
|
||||
minimum: Optional[str] = None,
|
||||
reason: Optional[str] = None,
|
||||
) -> None:
|
||||
try:
|
||||
requires(dependency, minimum, reason=reason)
|
||||
except Exception as e:
|
||||
self.fail_json(msg=to_text(e))
|
||||
|
||||
|
||||
def gather_versions() -> dict:
|
||||
versions = {}
|
||||
try:
|
||||
import jsonpatch
|
||||
|
||||
versions["jsonpatch"] = jsonpatch.__version__
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import kubernetes
|
||||
|
||||
versions["kubernetes"] = kubernetes.__version__
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import kubernetes_validate
|
||||
|
||||
versions["kubernetes-validate"] = kubernetes_validate.__version__
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import yaml
|
||||
|
||||
versions["pyyaml"] = yaml.__version__
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
return versions
|
||||
|
||||
|
||||
def has_at_least(dependency: str, minimum: Optional[str] = None) -> bool:
|
||||
"""Check if a specific dependency is present at a minimum version.
|
||||
|
||||
If a minimum version is not specified it will check only that the
|
||||
dependency is present.
|
||||
"""
|
||||
dependencies = gather_versions()
|
||||
current = dependencies.get(dependency)
|
||||
if current is not None:
|
||||
if minimum is None:
|
||||
return True
|
||||
supported = LooseVersion(current) >= LooseVersion(minimum)
|
||||
return supported
|
||||
return False
|
||||
|
||||
|
||||
def requires(
|
||||
dependency: str, minimum: Optional[str] = None, reason: Optional[str] = None
|
||||
) -> None:
|
||||
"""Fail if a specific dependency is not present at a minimum version.
|
||||
|
||||
If a minimum version is not specified it will require only that the
|
||||
dependency is present. This function raises an exception when the
|
||||
dependency is not found at the required version.
|
||||
"""
|
||||
if not has_at_least(dependency, minimum):
|
||||
if minimum is not None:
|
||||
lib = "{0}>={1}".format(dependency, minimum)
|
||||
else:
|
||||
lib = dependency
|
||||
raise Exception(missing_required_lib(lib, reason=reason))
|
||||
12
plugins/module_utils/k8s/exceptions.py
Normal file
12
plugins/module_utils/k8s/exceptions.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# Copyright: (c) 2021, Red Hat | Ansible
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
class CoreException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ResourceTimeout(CoreException):
|
||||
def __init__(self, message="", result=None):
|
||||
self.result = result or {}
|
||||
super().__init__(message)
|
||||
129
plugins/module_utils/k8s/resource.py
Normal file
129
plugins/module_utils/k8s/resource.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# Copyright: (c) 2021, Red Hat | Ansible
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
import os
|
||||
from typing import cast, Dict, Iterable, List, Optional, Union
|
||||
|
||||
from ansible.module_utils.six import string_types
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
|
||||
class ResourceDefinition(dict):
|
||||
"""Representation of a resource definition.
|
||||
|
||||
This is a thin wrapper around a dictionary representation of a resource
|
||||
definition, with a few properties defined for conveniently accessing the
|
||||
commonly used fields.
|
||||
"""
|
||||
|
||||
@property
|
||||
def kind(self) -> Optional[str]:
|
||||
return self.get("kind")
|
||||
|
||||
@property
|
||||
def api_version(self) -> Optional[str]:
|
||||
return self.get("apiVersion")
|
||||
|
||||
@property
|
||||
def namespace(self) -> Optional[str]:
|
||||
metadata = self.get("metadata", {})
|
||||
return metadata.get("namespace")
|
||||
|
||||
@property
|
||||
def name(self) -> Optional[str]:
|
||||
metadata = self.get("metadata", {})
|
||||
return metadata.get("name")
|
||||
|
||||
|
||||
def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
||||
"""Create a list of ResourceDefinitions from module inputs.
|
||||
|
||||
This will take the module's inputs and return a list of ResourceDefintion
|
||||
objects. The resource definitions returned by this function should be as
|
||||
complete a definition as we can create based on the input. Any *List kinds
|
||||
will be removed and replaced by the resources contained in it.
|
||||
"""
|
||||
if params.get("resource_definition"):
|
||||
d = cast(Union[str, List, Dict], params.get("resource_definition"))
|
||||
definitions = from_yaml(d)
|
||||
elif params.get("src"):
|
||||
d = cast(str, params.get("src"))
|
||||
definitions = from_file(d)
|
||||
else:
|
||||
# We'll create an empty definition and let merge_params set values
|
||||
# from the module parameters.
|
||||
definitions = [{}]
|
||||
|
||||
resource_definitions: List[Dict] = []
|
||||
for definition in definitions:
|
||||
merge_params(definition, params)
|
||||
kind = cast(Optional[str], definition.get("kind"))
|
||||
if kind and kind.endswith("List"):
|
||||
resource_definitions += flatten_list_kind(definition, params)
|
||||
else:
|
||||
resource_definitions.append(definition)
|
||||
return list(map(ResourceDefinition, resource_definitions))
|
||||
|
||||
|
||||
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
||||
"""Load resource definitions from a yaml definition."""
|
||||
definitions: List[Dict] = []
|
||||
if isinstance(definition, string_types):
|
||||
definitions += yaml.safe_load_all(definition)
|
||||
elif isinstance(definition, list):
|
||||
for item in definition:
|
||||
if isinstance(item, string_types):
|
||||
definitions += yaml.safe_load_all(item)
|
||||
else:
|
||||
definitions.append(item)
|
||||
else:
|
||||
definition = cast(Dict, definition)
|
||||
definitions.append(definition)
|
||||
return filter(None, definitions)
|
||||
|
||||
|
||||
def from_file(filepath: str) -> Iterable[Dict]:
|
||||
"""Load resource definitions from a path to a yaml file."""
|
||||
path = os.path.normpath(filepath)
|
||||
with open(path, "rb") as f:
|
||||
definitions = list(yaml.safe_load_all(f))
|
||||
return filter(None, definitions)
|
||||
|
||||
|
||||
def merge_params(definition: Dict, params: Dict) -> Dict:
|
||||
"""Merge module parameters with the resource definition.
|
||||
|
||||
Fields in the resource definition take precedence over module parameters.
|
||||
"""
|
||||
definition.setdefault("kind", params.get("kind"))
|
||||
definition.setdefault("apiVersion", params.get("api_version"))
|
||||
metadata = definition.setdefault("metadata", {})
|
||||
# The following should only be set if we have values for them
|
||||
if params.get("namespace"):
|
||||
metadata.setdefault("namespace", params.get("namespace"))
|
||||
if params.get("name"):
|
||||
metadata.setdefault("name", params.get("name"))
|
||||
if params.get("generate_name"):
|
||||
metadata.setdefault("generateName", params.get("generate_name"))
|
||||
return definition
|
||||
|
||||
|
||||
def flatten_list_kind(definition: Dict, params: Dict) -> List[Dict]:
|
||||
"""Replace *List kind with the items it contains.
|
||||
|
||||
This will take a definition for a *List resource and return a list of
|
||||
definitions for the items contained within the List.
|
||||
"""
|
||||
items = []
|
||||
kind = cast(str, definition.get("kind"))[:-4]
|
||||
api_version = definition.get("apiVersion")
|
||||
for item in definition.get("items", []):
|
||||
item.setdefault("kind", kind)
|
||||
item.setdefault("apiVersion", api_version)
|
||||
items.append(merge_params(item, params))
|
||||
return items
|
||||
199
plugins/module_utils/k8s/runner.py
Normal file
199
plugins/module_utils/k8s/runner.py
Normal file
@@ -0,0 +1,199 @@
|
||||
# Copyright: (c) 2021, Red Hat | Ansible
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from typing import Dict
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||
create_definitions,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
diff_objects,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
ResourceTimeout,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import exists
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.selector import (
|
||||
LabelSelectorFilter,
|
||||
)
|
||||
|
||||
|
||||
def validate(client, module, resource):
|
||||
def _prepend_resource_info(resource, msg):
|
||||
return "%s %s: %s" % (resource["kind"], resource["metadata"]["name"], msg)
|
||||
|
||||
module.requires("kubernetes-validate")
|
||||
|
||||
warnings, errors = client.validate(
|
||||
resource,
|
||||
module.params["validate"].get("version"),
|
||||
module.params["validate"].get("strict"),
|
||||
)
|
||||
|
||||
if errors and module.params["validate"]["fail_on_error"]:
|
||||
module.fail_json(
|
||||
msg="\n".join([_prepend_resource_info(resource, error) for error in errors])
|
||||
)
|
||||
return [_prepend_resource_info(resource, msg) for msg in warnings + errors]
|
||||
|
||||
|
||||
def run_module(module) -> None:
|
||||
results = []
|
||||
changed = False
|
||||
client = get_api_client(module)
|
||||
svc = K8sService(client, module)
|
||||
try:
|
||||
definitions = create_definitions(module.params)
|
||||
except Exception as e:
|
||||
msg = "Failed to load resource definition: {0}".format(e)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
for definition in definitions:
|
||||
result = {"changed": False, "result": {}}
|
||||
warnings = []
|
||||
|
||||
if module.params.get("validate") is not None:
|
||||
warnings = validate(client, module, definition)
|
||||
|
||||
try:
|
||||
result = perform_action(svc, definition, module.params)
|
||||
except Exception as e:
|
||||
try:
|
||||
error = e.result
|
||||
except AttributeError:
|
||||
error = {}
|
||||
try:
|
||||
error["reason"] = e.__cause__.reason
|
||||
except AttributeError:
|
||||
pass
|
||||
error["msg"] = to_native(e)
|
||||
if warnings:
|
||||
error.setdefault("warnings", []).extend(warnings)
|
||||
|
||||
if module.params.get("continue_on_error"):
|
||||
result["error"] = error
|
||||
else:
|
||||
module.fail_json(**error)
|
||||
|
||||
if warnings:
|
||||
result.setdefault("warnings", []).extend(warnings)
|
||||
changed |= result["changed"]
|
||||
results.append(result)
|
||||
|
||||
if len(results) == 1:
|
||||
module.exit_json(**results[0])
|
||||
|
||||
module.exit_json(**{"changed": changed, "result": {"results": results}})
|
||||
|
||||
|
||||
def perform_action(svc, definition: Dict, params: Dict) -> Dict:
|
||||
origin_name = definition["metadata"].get("name")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
label_selectors = params.get("label_selectors")
|
||||
state = params.get("state", None)
|
||||
kind = definition.get("kind")
|
||||
api_version = definition.get("apiVersion")
|
||||
|
||||
result = {"changed": False, "result": {}}
|
||||
instance = {}
|
||||
|
||||
resource = svc.find_resource(kind, api_version, fail=True)
|
||||
definition["kind"] = resource.kind
|
||||
definition["apiVersion"] = resource.group_version
|
||||
existing = svc.retrieve(resource, definition)
|
||||
|
||||
if state == "absent":
|
||||
if exists(existing) and existing.kind.endswith("List"):
|
||||
instance = []
|
||||
for item in existing.items:
|
||||
r = svc.delete(resource, item, existing)
|
||||
instance.append(r)
|
||||
else:
|
||||
instance = svc.delete(resource, definition, existing)
|
||||
result["method"] = "delete"
|
||||
if exists(existing):
|
||||
result["changed"] = True
|
||||
else:
|
||||
if label_selectors:
|
||||
filter_selector = LabelSelectorFilter(label_selectors)
|
||||
if not filter_selector.isMatching(definition):
|
||||
result["changed"] = False
|
||||
result["msg"] = (
|
||||
"resource 'kind={kind},name={name},namespace={namespace}' "
|
||||
"filtered by label_selectors.".format(
|
||||
kind=kind,
|
||||
name=origin_name,
|
||||
namespace=namespace,
|
||||
)
|
||||
)
|
||||
return result
|
||||
|
||||
if params.get("apply"):
|
||||
instance = svc.apply(resource, definition, existing)
|
||||
result["method"] = "apply"
|
||||
elif not existing:
|
||||
if state == "patched":
|
||||
result.setdefault("warnings", []).append(
|
||||
"resource 'kind={kind},name={name}' was not found but will not be "
|
||||
"created as 'state' parameter has been set to '{state}'".format(
|
||||
kind=kind, name=definition["metadata"].get("name"), state=state
|
||||
)
|
||||
)
|
||||
return result
|
||||
instance = svc.create(resource, definition)
|
||||
result["method"] = "create"
|
||||
result["changed"] = True
|
||||
elif params.get("force", False):
|
||||
instance = svc.replace(resource, definition, existing)
|
||||
result["method"] = "replace"
|
||||
else:
|
||||
instance = svc.update(resource, definition, existing)
|
||||
result["method"] = "update"
|
||||
|
||||
# If needed, wait and/or create diff
|
||||
success = True
|
||||
|
||||
if result["method"] == "delete":
|
||||
# wait logic is a bit different for delete as `instance` may be a status object
|
||||
if params.get("wait") and not svc.module.check_mode:
|
||||
success, waited, duration = svc.wait(resource, definition)
|
||||
result["duration"] = duration
|
||||
else:
|
||||
if params.get("wait") and not svc.module.check_mode:
|
||||
success, instance, duration = svc.wait(resource, instance)
|
||||
result["duration"] = duration
|
||||
|
||||
if result["method"] not in ("create", "delete"):
|
||||
if existing:
|
||||
existing = existing.to_dict()
|
||||
else:
|
||||
existing = {}
|
||||
match, diffs = diff_objects(existing, instance)
|
||||
if match and diffs:
|
||||
result.setdefault("warnings", []).append(
|
||||
"No meaningful diff was generated, but the API may not be idempotent "
|
||||
"(only metadata.generation or metadata.resourceVersion were changed)"
|
||||
)
|
||||
result["changed"] = not match
|
||||
if svc.module._diff:
|
||||
result["diff"] = diffs
|
||||
|
||||
result["result"] = instance
|
||||
if not success:
|
||||
raise ResourceTimeout(
|
||||
'"{0}" "{1}": Timed out waiting on resource'.format(
|
||||
definition["kind"], origin_name
|
||||
),
|
||||
result,
|
||||
)
|
||||
|
||||
return result
|
||||
502
plugins/module_utils/k8s/service.py
Normal file
502
plugins/module_utils/k8s/service.py
Normal file
@@ -0,0 +1,502 @@
|
||||
# Copyright: (c) 2021, Red Hat | Ansible
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import (
|
||||
generate_hash,
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
Waiter,
|
||||
exists,
|
||||
resource_absent,
|
||||
get_waiter,
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
requires,
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import (
|
||||
NotFoundError,
|
||||
ResourceNotFoundError,
|
||||
ResourceNotUniqueError,
|
||||
ConflictError,
|
||||
ForbiddenError,
|
||||
MethodNotAllowedError,
|
||||
BadRequestError,
|
||||
)
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.resource import Resource, ResourceInstance
|
||||
except ImportError:
|
||||
# These are defined only for the sake of Ansible's checked import requirement
|
||||
Resource = Any # type: ignore
|
||||
ResourceInstance = Any # type: ignore
|
||||
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.apply import (
|
||||
apply_object,
|
||||
)
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.apply import (
|
||||
recursive_diff,
|
||||
)
|
||||
except ImportError:
|
||||
from ansible.module_utils.common.dict_transformations import recursive_diff
|
||||
|
||||
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
_encode_stringdata,
|
||||
)
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
|
||||
class K8sService:
|
||||
"""A Service class for K8S modules.
|
||||
This class has the primary purpose is to perform work on the cluster (e.g., create, apply, replace, update, delete).
|
||||
"""
|
||||
|
||||
def __init__(self, client, module) -> None:
|
||||
self.client = client
|
||||
self.module = module
|
||||
|
||||
def find_resource(
|
||||
self, kind: str, api_version: str, fail: bool = False
|
||||
) -> Optional[Resource]:
|
||||
try:
|
||||
return self.client.resource(kind, api_version)
|
||||
except (ResourceNotFoundError, ResourceNotUniqueError):
|
||||
if fail:
|
||||
raise CoreException(
|
||||
"Failed to find exact match for %s.%s by [kind, name, singularName, shortNames]"
|
||||
% (api_version, kind)
|
||||
)
|
||||
|
||||
def wait(
|
||||
self, resource: Resource, instance: Dict
|
||||
) -> Tuple[bool, Optional[Dict], int]:
|
||||
wait_sleep = self.module.params.get("wait_sleep")
|
||||
wait_timeout = self.module.params.get("wait_timeout")
|
||||
wait_condition = None
|
||||
if self.module.params.get("wait_condition") and self.module.params[
|
||||
"wait_condition"
|
||||
].get("type"):
|
||||
wait_condition = self.module.params["wait_condition"]
|
||||
state = "present"
|
||||
if self.module.params.get("state") == "absent":
|
||||
state = "absent"
|
||||
label_selectors = self.module.params.get("label_selectors")
|
||||
|
||||
waiter = get_waiter(
|
||||
self.client, resource, condition=wait_condition, state=state
|
||||
)
|
||||
return waiter.wait(
|
||||
timeout=wait_timeout,
|
||||
sleep=wait_sleep,
|
||||
name=instance["metadata"].get("name"),
|
||||
namespace=instance["metadata"].get("namespace"),
|
||||
label_selectors=label_selectors,
|
||||
)
|
||||
|
||||
def create_project_request(self, definition: Dict) -> Dict:
|
||||
definition["kind"] = "ProjectRequest"
|
||||
results = {"changed": False, "result": {}}
|
||||
resource = self.find_resource(
|
||||
"ProjectRequest", definition["apiVersion"], fail=True
|
||||
)
|
||||
if not self.module.check_mode:
|
||||
try:
|
||||
k8s_obj = self.client.create(resource, definition)
|
||||
results["result"] = k8s_obj.to_dict()
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to create object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
results["changed"] = True
|
||||
|
||||
return results
|
||||
|
||||
def patch_resource(
|
||||
self,
|
||||
resource: Resource,
|
||||
definition: Dict,
|
||||
name: str,
|
||||
namespace: str,
|
||||
merge_type: str = None,
|
||||
) -> Dict:
|
||||
if merge_type == "json":
|
||||
self.module.deprecate(
|
||||
msg="json as a merge_type value is deprecated. Please use the k8s_json_patch module instead.",
|
||||
version="3.0.0",
|
||||
collection_name="kubernetes.core",
|
||||
)
|
||||
try:
|
||||
params = dict(name=name, namespace=namespace)
|
||||
if self.module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
if merge_type:
|
||||
params["content_type"] = "application/{0}-patch+json".format(merge_type)
|
||||
return self.client.patch(resource, definition, **params).to_dict()
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to patch object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
def retrieve(self, resource: Resource, definition: Dict) -> ResourceInstance:
|
||||
state = self.module.params.get("state", None)
|
||||
append_hash = self.module.params.get("append_hash", False)
|
||||
name = definition["metadata"].get("name")
|
||||
generate_name = definition["metadata"].get("generateName")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
label_selectors = self.module.params.get("label_selectors")
|
||||
existing: ResourceInstance = None
|
||||
|
||||
try:
|
||||
# ignore append_hash for resources other than ConfigMap and Secret
|
||||
if append_hash and definition["kind"] in ["ConfigMap", "Secret"]:
|
||||
if name:
|
||||
name = "%s-%s" % (name, generate_hash(definition))
|
||||
definition["metadata"]["name"] = name
|
||||
elif generate_name:
|
||||
definition["metadata"]["generateName"] = "%s-%s" % (
|
||||
generate_name,
|
||||
generate_hash(definition),
|
||||
)
|
||||
params = {}
|
||||
if name:
|
||||
params["name"] = name
|
||||
if namespace:
|
||||
params["namespace"] = namespace
|
||||
if label_selectors:
|
||||
params["label_selector"] = ",".join(label_selectors)
|
||||
if "name" in params or "label_selector" in params:
|
||||
existing = self.client.get(resource, **params)
|
||||
except (NotFoundError, MethodNotAllowedError):
|
||||
pass
|
||||
except ForbiddenError as e:
|
||||
if (
|
||||
definition["kind"] in ["Project", "ProjectRequest"]
|
||||
and state != "absent"
|
||||
):
|
||||
return self.create_project_request(definition)
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
return existing
|
||||
|
||||
def find(
|
||||
self,
|
||||
kind: str,
|
||||
api_version: str,
|
||||
name: str = None,
|
||||
namespace: Optional[str] = None,
|
||||
label_selectors: Optional[List[str]] = None,
|
||||
field_selectors: Optional[List[str]] = None,
|
||||
wait: Optional[bool] = False,
|
||||
wait_sleep: Optional[int] = 5,
|
||||
wait_timeout: Optional[int] = 120,
|
||||
state: Optional[str] = "present",
|
||||
condition: Optional[Dict] = None,
|
||||
) -> Dict:
|
||||
resource = self.find_resource(kind, api_version)
|
||||
api_found = bool(resource)
|
||||
if not api_found:
|
||||
return dict(
|
||||
resources=[],
|
||||
msg='Failed to find API for resource with apiVersion "{0}" and kind "{1}"'.format(
|
||||
api_version, kind
|
||||
),
|
||||
api_found=False,
|
||||
)
|
||||
|
||||
if not label_selectors:
|
||||
label_selectors = []
|
||||
if not field_selectors:
|
||||
field_selectors = []
|
||||
|
||||
result = {"resources": [], "api_found": True}
|
||||
|
||||
# With a timeout of 0 the waiter will do a single check and return, effectively not waiting.
|
||||
if not wait:
|
||||
wait_timeout = 0
|
||||
|
||||
if state == "present":
|
||||
predicate = exists
|
||||
else:
|
||||
predicate = resource_absent
|
||||
|
||||
waiter = Waiter(self.client, resource, predicate)
|
||||
|
||||
# This is an initial check to get the resource or resources that we then need to wait on individually.
|
||||
try:
|
||||
success, resources, duration = waiter.wait(
|
||||
timeout=wait_timeout,
|
||||
sleep=wait_sleep,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
label_selectors=label_selectors,
|
||||
field_selectors=field_selectors,
|
||||
)
|
||||
except BadRequestError:
|
||||
return result
|
||||
except CoreException as e:
|
||||
result["msg"] = to_native(e)
|
||||
return result
|
||||
|
||||
# There is either no result or there is a List resource with no items
|
||||
if (
|
||||
not resources
|
||||
or resources["kind"].endswith("List")
|
||||
and not resources.get("items")
|
||||
):
|
||||
return result
|
||||
|
||||
instances = resources.get("items") or [resources]
|
||||
|
||||
if not wait:
|
||||
result["resources"] = instances
|
||||
return result
|
||||
|
||||
# Now wait for the specified state of any resource instances we have found.
|
||||
waiter = get_waiter(self.client, resource, state=state, condition=condition)
|
||||
for instance in instances:
|
||||
name = instance["metadata"].get("name")
|
||||
namespace = instance["metadata"].get("namespace")
|
||||
success, res, duration = waiter.wait(
|
||||
timeout=wait_timeout,
|
||||
sleep=wait_sleep,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
)
|
||||
if not success:
|
||||
raise CoreException(
|
||||
"Failed to gather information about %s(s) even"
|
||||
" after waiting for %s seconds" % (res.get("kind"), duration)
|
||||
)
|
||||
result["resources"].append(res)
|
||||
return result
|
||||
|
||||
def create(self, resource: Resource, definition: Dict) -> Dict:
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
name = definition["metadata"].get("name")
|
||||
results = {"changed": False, "result": {}}
|
||||
|
||||
if self.module.check_mode and not self.client.dry_run:
|
||||
k8s_obj = _encode_stringdata(definition)
|
||||
else:
|
||||
params = {}
|
||||
if self.module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
try:
|
||||
k8s_obj = self.client.create(
|
||||
resource, definition, namespace=namespace, **params
|
||||
).to_dict()
|
||||
except ConflictError:
|
||||
# Some resources, like ProjectRequests, can't be created multiple times,
|
||||
# because the resources that they create don't match their kind
|
||||
# In this case we'll mark it as unchanged and warn the user
|
||||
self.module.warn(
|
||||
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
|
||||
if the resource you are creating does not directly create a resource of the same kind.".format(
|
||||
name
|
||||
)
|
||||
)
|
||||
return results
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to create object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
return k8s_obj
|
||||
|
||||
def apply(
|
||||
self,
|
||||
resource: Resource,
|
||||
definition: Dict,
|
||||
existing: Optional[ResourceInstance] = None,
|
||||
) -> Dict:
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
|
||||
server_side_apply = self.module.params.get("server_side_apply")
|
||||
if server_side_apply:
|
||||
requires("kubernetes", "19.15.0", reason="to use server side apply")
|
||||
if self.module.check_mode and not self.client.dry_run:
|
||||
ignored, patch = apply_object(resource, _encode_stringdata(definition))
|
||||
if existing:
|
||||
k8s_obj = dict_merge(existing.to_dict(), patch)
|
||||
else:
|
||||
k8s_obj = patch
|
||||
else:
|
||||
try:
|
||||
params = {}
|
||||
if self.module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
if server_side_apply:
|
||||
params["server_side"] = True
|
||||
params.update(server_side_apply)
|
||||
k8s_obj = self.client.apply(
|
||||
resource, definition, namespace=namespace, **params
|
||||
).to_dict()
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to apply object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
return k8s_obj
|
||||
|
||||
def replace(
|
||||
self,
|
||||
resource: Resource,
|
||||
definition: Dict,
|
||||
existing: ResourceInstance,
|
||||
) -> Dict:
|
||||
append_hash = self.module.params.get("append_hash", False)
|
||||
name = definition["metadata"].get("name")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
|
||||
if self.module.check_mode and not self.module.client.dry_run:
|
||||
k8s_obj = _encode_stringdata(definition)
|
||||
else:
|
||||
params = {}
|
||||
if self.module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
try:
|
||||
k8s_obj = self.client.replace(
|
||||
resource,
|
||||
definition,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
append_hash=append_hash,
|
||||
**params
|
||||
).to_dict()
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to replace object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
return k8s_obj
|
||||
|
||||
def update(
|
||||
self, resource: Resource, definition: Dict, existing: ResourceInstance
|
||||
) -> Dict:
|
||||
name = definition["metadata"].get("name")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
|
||||
if self.module.check_mode and not self.client.dry_run:
|
||||
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
|
||||
else:
|
||||
exception = None
|
||||
for merge_type in self.module.params.get("merge_type") or [
|
||||
"strategic-merge",
|
||||
"merge",
|
||||
]:
|
||||
try:
|
||||
k8s_obj = self.patch_resource(
|
||||
resource,
|
||||
definition,
|
||||
name,
|
||||
namespace,
|
||||
merge_type=merge_type,
|
||||
)
|
||||
exception = None
|
||||
except CoreException as e:
|
||||
exception = e
|
||||
continue
|
||||
break
|
||||
if exception:
|
||||
raise exception
|
||||
return k8s_obj
|
||||
|
||||
def delete(
|
||||
self,
|
||||
resource: Resource,
|
||||
definition: Dict,
|
||||
existing: Optional[ResourceInstance] = None,
|
||||
) -> Dict:
|
||||
delete_options = self.module.params.get("delete_options")
|
||||
label_selectors = self.module.params.get("label_selectors")
|
||||
name = definition["metadata"].get("name")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
params = {}
|
||||
|
||||
if not exists(existing):
|
||||
return {}
|
||||
|
||||
# Delete the object
|
||||
if self.module.check_mode and not self.client.dry_run:
|
||||
return {}
|
||||
|
||||
if name:
|
||||
params["name"] = name
|
||||
|
||||
if namespace:
|
||||
params["namespace"] = namespace
|
||||
|
||||
if label_selectors:
|
||||
params["label_selector"] = ",".join(label_selectors)
|
||||
|
||||
if delete_options:
|
||||
body = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "DeleteOptions",
|
||||
}
|
||||
body.update(delete_options)
|
||||
params["body"] = body
|
||||
|
||||
if self.module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
try:
|
||||
k8s_obj = self.client.delete(resource, **params).to_dict()
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to delete object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
return k8s_obj
|
||||
|
||||
|
||||
def diff_objects(existing: Dict, new: Dict) -> Tuple[bool, Dict]:
|
||||
result = {}
|
||||
diff = recursive_diff(existing, new)
|
||||
if not diff:
|
||||
return True, result
|
||||
|
||||
result["before"] = diff[0]
|
||||
result["after"] = diff[1]
|
||||
|
||||
if list(result["after"].keys()) != ["metadata"] or list(
|
||||
result["before"].keys()
|
||||
) != ["metadata"]:
|
||||
return False, result
|
||||
|
||||
# If only metadata.generation and metadata.resourceVersion changed, ignore it
|
||||
ignored_keys = set(["generation", "resourceVersion"])
|
||||
|
||||
if not set(result["after"]["metadata"].keys()).issubset(ignored_keys):
|
||||
return False, result
|
||||
if not set(result["before"]["metadata"].keys()).issubset(ignored_keys):
|
||||
return False, result
|
||||
|
||||
return True, result
|
||||
238
plugins/module_utils/k8s/waiter.py
Normal file
238
plugins/module_utils/k8s/waiter.py
Normal file
@@ -0,0 +1,238 @@
|
||||
import time
|
||||
from functools import partial
|
||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
from kubernetes.dynamic.resource import Resource, ResourceField, ResourceInstance
|
||||
except ImportError:
|
||||
# These are defined only for the sake of Ansible's checked import requirement
|
||||
Resource = Any # type: ignore
|
||||
ResourceInstance = Any # type: ignore
|
||||
pass
|
||||
|
||||
try:
|
||||
from urllib3.exceptions import HTTPError
|
||||
except ImportError:
|
||||
# Handled during module setup
|
||||
pass
|
||||
|
||||
|
||||
def deployment_ready(deployment: ResourceInstance) -> bool:
|
||||
# FIXME: frustratingly bool(deployment.status) is True even if status is empty
|
||||
# Furthermore deployment.status.availableReplicas == deployment.status.replicas == None if status is empty
|
||||
# deployment.status.replicas is None is perfectly ok if desired replicas == 0
|
||||
# Scaling up means that we also need to check that we're not in a
|
||||
# situation where status.replicas == status.availableReplicas
|
||||
# but spec.replicas != status.replicas
|
||||
return bool(
|
||||
deployment.status
|
||||
and deployment.spec.replicas == (deployment.status.replicas or 0)
|
||||
and deployment.status.availableReplicas == deployment.status.replicas
|
||||
and deployment.status.observedGeneration == deployment.metadata.generation
|
||||
and not deployment.status.unavailableReplicas
|
||||
)
|
||||
|
||||
|
||||
def pod_ready(pod: ResourceInstance) -> bool:
|
||||
return bool(
|
||||
pod.status
|
||||
and pod.status.containerStatuses is not None
|
||||
and all(container.ready for container in pod.status.containerStatuses)
|
||||
)
|
||||
|
||||
|
||||
def daemonset_ready(daemonset: ResourceInstance) -> bool:
|
||||
return bool(
|
||||
daemonset.status
|
||||
and daemonset.status.desiredNumberScheduled is not None
|
||||
and daemonset.status.updatedNumberScheduled
|
||||
== daemonset.status.desiredNumberScheduled
|
||||
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
|
||||
and daemonset.status.observedGeneration == daemonset.metadata.generation
|
||||
and not daemonset.status.unavailableReplicas
|
||||
)
|
||||
|
||||
|
||||
def statefulset_ready(statefulset: ResourceInstance) -> bool:
|
||||
# These may be None
|
||||
updated_replicas = statefulset.status.updatedReplicas or 0
|
||||
ready_replicas = statefulset.status.readyReplicas or 0
|
||||
return bool(
|
||||
statefulset.status
|
||||
and statefulset.spec.updateStrategy.type == "RollingUpdate"
|
||||
and statefulset.status.observedGeneration
|
||||
== (statefulset.metadata.generation or 0)
|
||||
and statefulset.status.updateRevision == statefulset.status.currentRevision
|
||||
and updated_replicas == statefulset.spec.replicas
|
||||
and ready_replicas == statefulset.spec.replicas
|
||||
and statefulset.status.replicas == statefulset.spec.replicas
|
||||
)
|
||||
|
||||
|
||||
def custom_condition(condition: Dict, resource: ResourceInstance) -> bool:
|
||||
if not resource.status or not resource.status.conditions:
|
||||
return False
|
||||
matches = [x for x in resource.status.conditions if x.type == condition["type"]]
|
||||
if not matches:
|
||||
return False
|
||||
# There should never be more than one condition of a specific type
|
||||
match: ResourceField = matches[0]
|
||||
if match.status == "Unknown":
|
||||
if match.status == condition["status"]:
|
||||
if "reason" not in condition:
|
||||
return True
|
||||
if condition["reason"]:
|
||||
return match.reason == condition["reason"]
|
||||
return False
|
||||
status = True if match.status == "True" else False
|
||||
if status == boolean(condition["status"], strict=False):
|
||||
if condition.get("reason"):
|
||||
return match.reason == condition["reason"]
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def resource_absent(resource: ResourceInstance) -> bool:
|
||||
return not exists(resource)
|
||||
|
||||
|
||||
def exists(resource: Optional[ResourceInstance]) -> bool:
|
||||
"""Simple predicate to check for existence of a resource.
|
||||
|
||||
While a List type resource technically always exists, this will only return
|
||||
true if the List contains items."""
|
||||
return bool(resource) and not empty_list(resource)
|
||||
|
||||
|
||||
RESOURCE_PREDICATES = {
|
||||
"DaemonSet": daemonset_ready,
|
||||
"Deployment": deployment_ready,
|
||||
"Pod": pod_ready,
|
||||
"StatefulSet": statefulset_ready,
|
||||
}
|
||||
|
||||
|
||||
def empty_list(resource: ResourceInstance) -> bool:
|
||||
return resource["kind"].endswith("List") and not resource.get("items")
|
||||
|
||||
|
||||
def clock(total: int, interval: int) -> Iterator[int]:
|
||||
start = time.monotonic()
|
||||
yield 0
|
||||
while (time.monotonic() - start) < total:
|
||||
time.sleep(interval)
|
||||
yield int(time.monotonic() - start)
|
||||
|
||||
|
||||
class Waiter:
|
||||
def __init__(
|
||||
self, client, resource: Resource, predicate: Callable[[ResourceInstance], bool]
|
||||
):
|
||||
self.client = client
|
||||
self.resource = resource
|
||||
self.predicate = predicate
|
||||
|
||||
def wait(
|
||||
self,
|
||||
timeout: int,
|
||||
sleep: int,
|
||||
name: Optional[str] = None,
|
||||
namespace: Optional[str] = None,
|
||||
label_selectors: Optional[List[str]] = None,
|
||||
field_selectors: Optional[List[str]] = None,
|
||||
) -> Tuple[bool, Dict, int]:
|
||||
params = {}
|
||||
|
||||
if name:
|
||||
params["name"] = name
|
||||
|
||||
if namespace:
|
||||
params["namespace"] = namespace
|
||||
|
||||
if label_selectors:
|
||||
params["label_selector"] = ",".join(label_selectors)
|
||||
|
||||
if field_selectors:
|
||||
params["field_selector"] = ",".join(field_selectors)
|
||||
|
||||
instance = {}
|
||||
response = None
|
||||
elapsed = 0
|
||||
for i in clock(timeout, sleep):
|
||||
exception = None
|
||||
elapsed = i
|
||||
try:
|
||||
response = self.client.get(self.resource, **params)
|
||||
except NotFoundError:
|
||||
response = None
|
||||
# Retry connection errors as it may be intermittent network issues
|
||||
except HTTPError as e:
|
||||
exception = e
|
||||
if self.predicate(response):
|
||||
break
|
||||
if exception:
|
||||
msg = (
|
||||
"Exception '{0}' raised while trying to get resource using {1}".format(
|
||||
exception, params
|
||||
)
|
||||
)
|
||||
raise CoreException(msg) from exception
|
||||
if response:
|
||||
instance = response.to_dict()
|
||||
return self.predicate(response), instance, elapsed
|
||||
|
||||
|
||||
class DummyWaiter:
|
||||
"""A no-op waiter that simply returns the item being waited on.
|
||||
|
||||
No API call will be made with this waiter; the function returns
|
||||
immediately. This waiter is useful for waiting on resource instances in
|
||||
check mode, for example.
|
||||
"""
|
||||
|
||||
def wait(
|
||||
self,
|
||||
definition: Dict,
|
||||
timeout: int,
|
||||
sleep: int,
|
||||
label_selectors: Optional[List[str]] = None,
|
||||
) -> Tuple[bool, Optional[Dict], int]:
|
||||
return True, definition, 0
|
||||
|
||||
|
||||
# The better solution would be typing.Protocol, but this is only in 3.8+
|
||||
SupportsWait = Union[Waiter, DummyWaiter]
|
||||
|
||||
|
||||
def get_waiter(
|
||||
client,
|
||||
resource: Resource,
|
||||
state: str = "present",
|
||||
condition: Optional[Dict] = None,
|
||||
check_mode: Optional[bool] = False,
|
||||
) -> SupportsWait:
|
||||
"""Create a Waiter object based on the specified resource.
|
||||
|
||||
This is a convenience method for creating a waiter from a resource.
|
||||
Based on the arguments and the kind of resource, an appropriate waiter
|
||||
will be returned. A waiter can also be created directly, of course.
|
||||
"""
|
||||
if check_mode:
|
||||
return DummyWaiter()
|
||||
if state == "present":
|
||||
if condition:
|
||||
predicate: Callable[[ResourceInstance], bool] = partial(
|
||||
custom_condition, condition
|
||||
)
|
||||
else:
|
||||
predicate = RESOURCE_PREDICATES.get(resource.kind, exists)
|
||||
else:
|
||||
predicate = resource_absent
|
||||
return Waiter(client, resource, predicate)
|
||||
@@ -391,6 +391,15 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
RESOURCE_ARG_SPEC,
|
||||
DELETE_OPTS_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import (
|
||||
run_module,
|
||||
)
|
||||
|
||||
|
||||
def validate_spec():
|
||||
@@ -437,28 +446,6 @@ def argspec():
|
||||
return argument_spec
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
k8s_ansible_mixin.module = module
|
||||
k8s_ansible_mixin.argspec = module.argument_spec
|
||||
k8s_ansible_mixin.check_mode = k8s_ansible_mixin.module.check_mode
|
||||
k8s_ansible_mixin.params = k8s_ansible_mixin.module.params
|
||||
k8s_ansible_mixin.fail_json = k8s_ansible_mixin.module.fail_json
|
||||
k8s_ansible_mixin.fail = k8s_ansible_mixin.module.fail_json
|
||||
k8s_ansible_mixin.exit_json = k8s_ansible_mixin.module.exit_json
|
||||
k8s_ansible_mixin.warn = k8s_ansible_mixin.module.warn
|
||||
k8s_ansible_mixin.warnings = []
|
||||
|
||||
k8s_ansible_mixin.kind = k8s_ansible_mixin.params.get("kind")
|
||||
k8s_ansible_mixin.api_version = k8s_ansible_mixin.params.get("api_version")
|
||||
k8s_ansible_mixin.name = k8s_ansible_mixin.params.get("name")
|
||||
k8s_ansible_mixin.generate_name = k8s_ansible_mixin.params.get("generate_name")
|
||||
k8s_ansible_mixin.namespace = k8s_ansible_mixin.params.get("namespace")
|
||||
|
||||
k8s_ansible_mixin.check_library_version()
|
||||
k8s_ansible_mixin.set_resource_definitions(module)
|
||||
k8s_ansible_mixin.execute_module()
|
||||
|
||||
|
||||
def main():
|
||||
mutually_exclusive = [
|
||||
("resource_definition", "src"),
|
||||
@@ -467,19 +454,17 @@ def main():
|
||||
("template", "src"),
|
||||
("name", "generate_name"),
|
||||
]
|
||||
module = AnsibleModule(
|
||||
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
argument_spec=argspec(),
|
||||
mutually_exclusive=mutually_exclusive,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
run_module(module)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -141,36 +141,32 @@ apis:
|
||||
|
||||
|
||||
import copy
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
|
||||
HAS_K8S = False
|
||||
try:
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import (
|
||||
ResourceList,
|
||||
)
|
||||
except ImportError:
|
||||
# Handled during module setup
|
||||
pass
|
||||
|
||||
HAS_K8S = True
|
||||
except ImportError as e:
|
||||
K8S_IMP_ERR = e
|
||||
K8S_IMP_EXC = traceback.format_exc()
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC,
|
||||
)
|
||||
|
||||
|
||||
def execute_module(module, client):
|
||||
invalidate_cache = boolean(
|
||||
module.params.get("invalidate_cache", True), strict=False
|
||||
)
|
||||
if invalidate_cache:
|
||||
if module.params.get("invalidate_cache"):
|
||||
client.resources.invalidate_cache()
|
||||
results = defaultdict(dict)
|
||||
for resource in list(client.resources):
|
||||
@@ -204,7 +200,7 @@ def execute_module(module, client):
|
||||
|
||||
version_info = {
|
||||
"client": version,
|
||||
"server": client.version,
|
||||
"server": client.client.version,
|
||||
}
|
||||
module.exit_json(
|
||||
changed=False, apis=results, connection=connection, version=version_info
|
||||
@@ -218,18 +214,18 @@ def argspec():
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
if not HAS_K8S:
|
||||
module.fail_json(
|
||||
msg=missing_required_lib("kubernetes"),
|
||||
exception=K8S_IMP_EXC,
|
||||
error=to_native(K8S_IMP_ERR),
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule, argument_spec=argspec(), supports_check_mode=True
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
execute_module(module, client=get_api_client(module=module))
|
||||
try:
|
||||
execute_module(module, client=get_api_client(module=module))
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -142,6 +142,19 @@ import copy
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC,
|
||||
)
|
||||
@@ -171,23 +184,9 @@ def argspec():
|
||||
|
||||
|
||||
def execute_module(module):
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module, pyyaml_required=False)
|
||||
k8s_ansible_mixin.check_library_version()
|
||||
|
||||
k8s_ansible_mixin.module = module
|
||||
k8s_ansible_mixin.argspec = module.argument_spec
|
||||
k8s_ansible_mixin.params = k8s_ansible_mixin.module.params
|
||||
k8s_ansible_mixin.fail_json = k8s_ansible_mixin.module.fail_json
|
||||
k8s_ansible_mixin.fail = k8s_ansible_mixin.module.fail_json
|
||||
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
containers = check_pod(k8s_ansible_mixin, module)
|
||||
client = get_api_client(module=module)
|
||||
svc = K8sService(client, module)
|
||||
containers = check_pod(svc)
|
||||
if len(containers) > 1 and module.params.get("container") is None:
|
||||
module.fail_json(
|
||||
msg="Pod contains more than 1 container, option 'container' should be set"
|
||||
@@ -195,9 +194,9 @@ def execute_module(module):
|
||||
|
||||
state = module.params.get("state")
|
||||
if state == "to_pod":
|
||||
k8s_copy = K8SCopyToPod(module, k8s_ansible_mixin.client)
|
||||
k8s_copy = K8SCopyToPod(module, client.client)
|
||||
else:
|
||||
k8s_copy = K8SCopyFromPod(module, k8s_ansible_mixin.client)
|
||||
k8s_copy = K8SCopyFromPod(module, client.client)
|
||||
|
||||
try:
|
||||
k8s_copy.run()
|
||||
@@ -206,15 +205,20 @@ def execute_module(module):
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
argument_spec=argspec(),
|
||||
check_pyyaml=False,
|
||||
mutually_exclusive=[("local_path", "content")],
|
||||
required_if=[("state", "from_pod", ["local_path"])],
|
||||
required_one_of=[["local_path", "content"]],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
execute_module(module)
|
||||
try:
|
||||
execute_module(module)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -136,6 +136,16 @@ from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule impo
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
@@ -244,30 +254,9 @@ def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
|
||||
|
||||
|
||||
class K8sDrainAnsible(object):
|
||||
def __init__(self, module):
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
def __init__(self, module, client):
|
||||
self._module = module
|
||||
self._k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
self._k8s_ansible_mixin.client = get_api_client(module=self._module)
|
||||
|
||||
self._k8s_ansible_mixin.module = self._module
|
||||
self._k8s_ansible_mixin.argspec = self._module.argument_spec
|
||||
self._k8s_ansible_mixin.check_mode = self._module.check_mode
|
||||
self._k8s_ansible_mixin.params = self._module.params
|
||||
self._k8s_ansible_mixin.fail_json = self._module.fail_json
|
||||
self._k8s_ansible_mixin.fail = self._module.fail_json
|
||||
self._k8s_ansible_mixin.exit_json = self._module.exit_json
|
||||
self._k8s_ansible_mixin.warn = self._module.warn
|
||||
self._k8s_ansible_mixin.warnings = []
|
||||
|
||||
self._api_instance = core_v1_api.CoreV1Api(
|
||||
self._k8s_ansible_mixin.client.client
|
||||
)
|
||||
self._k8s_ansible_mixin.check_library_version()
|
||||
self._api_instance = core_v1_api.CoreV1Api(client.client)
|
||||
|
||||
# delete options
|
||||
self._drain_options = module.params.get("delete_options", {})
|
||||
@@ -503,7 +492,7 @@ def argspec():
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec())
|
||||
module = AnsibleK8SModule(module_class=AnsibleModule, argument_spec=argspec())
|
||||
|
||||
if not HAS_EVICTION_API:
|
||||
module.fail_json(
|
||||
@@ -512,8 +501,12 @@ def main():
|
||||
error=to_native(k8s_import_exception),
|
||||
)
|
||||
|
||||
k8s_drain = K8sDrainAnsible(module)
|
||||
k8s_drain.execute_module()
|
||||
try:
|
||||
client = get_api_client(module=module)
|
||||
k8s_drain = K8sDrainAnsible(module, client.client)
|
||||
k8s_drain.execute_module()
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -138,6 +138,15 @@ from ansible.module_utils._text import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
AUTH_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
try:
|
||||
from kubernetes.client.apis import core_v1_api
|
||||
@@ -157,10 +166,9 @@ def argspec():
|
||||
return spec
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
|
||||
def execute_module(module, client):
|
||||
# Load kubernetes.client.Configuration
|
||||
api = core_v1_api.CoreV1Api(k8s_ansible_mixin.client.client)
|
||||
api = core_v1_api.CoreV1Api(client.client)
|
||||
|
||||
# hack because passing the container as None breaks things
|
||||
optional_kwargs = {}
|
||||
@@ -228,18 +236,18 @@ def execute_module(module, k8s_ansible_mixin):
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
check_pyyaml=False,
|
||||
argument_spec=argspec(),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module)
|
||||
execute_module(module, client.client)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -155,10 +155,22 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
AUTH_ARG_SPEC,
|
||||
WAIT_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
)
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
facts = k8s_ansible_mixin.kubernetes_facts(
|
||||
def execute_module(module, svc):
|
||||
facts = svc.find(
|
||||
module.params["kind"],
|
||||
module.params["api_version"],
|
||||
name=module.params["name"],
|
||||
@@ -190,19 +202,15 @@ def argspec():
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule, argument_spec=argspec(), supports_check_mode=True
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
k8s_ansible_mixin.fail_json = module.fail_json
|
||||
k8s_ansible_mixin.fail = module.fail_json
|
||||
k8s_ansible_mixin.exit_json = module.exit_json
|
||||
k8s_ansible_mixin.warn = module.warn
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module)
|
||||
svc = K8sService(client, module)
|
||||
execute_module(module, svc)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -136,10 +136,22 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
AUTH_ARG_SPEC,
|
||||
WAIT_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
K8sAnsibleMixin,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
diff_objects,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
get_waiter,
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import DynamicApiError
|
||||
@@ -185,7 +197,7 @@ def json_patch(existing, patch):
|
||||
return None, error
|
||||
|
||||
|
||||
def execute_module(k8s_module, module):
|
||||
def execute_module(module, client):
|
||||
kind = module.params.get("kind")
|
||||
api_version = module.params.get("api_version")
|
||||
name = module.params.get("name")
|
||||
@@ -200,19 +212,14 @@ def execute_module(k8s_module, module):
|
||||
"type"
|
||||
):
|
||||
wait_condition = module.params["wait_condition"]
|
||||
# definition is needed for wait
|
||||
definition = {
|
||||
"kind": kind,
|
||||
"metadata": {"name": name, "namespace": namespace},
|
||||
}
|
||||
|
||||
def build_error_msg(kind, name, msg):
|
||||
return "%s %s: %s" % (kind, name, msg)
|
||||
|
||||
resource = k8s_module.find_resource(kind, api_version, fail=True)
|
||||
resource = client.resource(kind, api_version)
|
||||
|
||||
try:
|
||||
existing = resource.get(name=name, namespace=namespace)
|
||||
existing = client.get(resource, name=name, namespace=namespace)
|
||||
except DynamicApiError as exc:
|
||||
msg = "Failed to retrieve requested object: {0}".format(exc.body)
|
||||
module.fail_json(
|
||||
@@ -227,7 +234,7 @@ def execute_module(k8s_module, module):
|
||||
msg=build_error_msg(kind, name, msg), error="", status="", reason=""
|
||||
)
|
||||
|
||||
if module.check_mode and not k8s_module.supports_dry_run:
|
||||
if module.check_mode and not client.dry_run:
|
||||
obj, error = json_patch(existing.to_dict(), patch)
|
||||
if error:
|
||||
module.fail_json(**error)
|
||||
@@ -236,7 +243,8 @@ def execute_module(k8s_module, module):
|
||||
if module.check_mode:
|
||||
params["dry_run"] = "All"
|
||||
try:
|
||||
obj = resource.patch(
|
||||
obj = client.patch(
|
||||
resource,
|
||||
patch,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
@@ -255,10 +263,11 @@ def execute_module(k8s_module, module):
|
||||
success = True
|
||||
result = {"result": obj}
|
||||
if wait and not module.check_mode:
|
||||
success, result["result"], result["duration"] = k8s_module.wait(
|
||||
resource, definition, wait_sleep, wait_timeout, condition=wait_condition
|
||||
waiter = get_waiter(client, resource, condition=wait_condition)
|
||||
success, result["result"], result["duration"] = waiter.wait(
|
||||
wait_timeout, wait_sleep, name, namespace
|
||||
)
|
||||
match, diffs = k8s_module.diff_objects(existing.to_dict(), obj)
|
||||
match, diffs = diff_objects(existing.to_dict(), obj)
|
||||
result["changed"] = not match
|
||||
if module._diff:
|
||||
result["diff"] = diffs
|
||||
@@ -274,13 +283,14 @@ def main():
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||
args.update(JSON_PATCH_ARGS)
|
||||
module = AnsibleModule(argument_spec=args, supports_check_mode=True)
|
||||
k8s_module = K8sAnsibleMixin(module)
|
||||
k8s_module.params = module.params
|
||||
k8s_module.check_library_version()
|
||||
client = get_api_client(module)
|
||||
k8s_module.client = client
|
||||
execute_module(k8s_module, module)
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule, argument_spec=args, supports_check_mode=True
|
||||
)
|
||||
try:
|
||||
client = get_api_client(module)
|
||||
execute_module(module, client)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -128,12 +128,22 @@ import copy
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
from ansible.module_utils.six import PY2
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC,
|
||||
NAME_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
)
|
||||
|
||||
|
||||
def argspec():
|
||||
@@ -151,32 +161,30 @@ def argspec():
|
||||
return args
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
name = module.params.get("name")
|
||||
namespace = module.params.get("namespace")
|
||||
label_selector = ",".join(module.params.get("label_selectors", {}))
|
||||
def execute_module(svc, params):
|
||||
name = params.get("name")
|
||||
namespace = params.get("namespace")
|
||||
label_selector = ",".join(params.get("label_selectors", {}))
|
||||
if name and label_selector:
|
||||
module.fail(msg="Only one of name or label_selectors can be provided")
|
||||
raise CoreException("Only one of name or label_selectors can be provided")
|
||||
|
||||
resource = k8s_ansible_mixin.find_resource(
|
||||
module.params["kind"], module.params["api_version"], fail=True
|
||||
)
|
||||
v1_pods = k8s_ansible_mixin.find_resource("Pod", "v1", fail=True)
|
||||
resource = svc.find_resource(params["kind"], params["api_version"], fail=True)
|
||||
v1_pods = svc.find_resource("Pod", "v1", fail=True)
|
||||
|
||||
if "log" not in resource.subresources:
|
||||
if not name:
|
||||
module.fail(
|
||||
msg="name must be provided for resources that do not support the log subresource"
|
||||
raise CoreException(
|
||||
"name must be provided for resources that do not support the log subresource"
|
||||
)
|
||||
instance = resource.get(name=name, namespace=namespace)
|
||||
label_selector = ",".join(extract_selectors(module, instance))
|
||||
label_selector = ",".join(extract_selectors(instance))
|
||||
resource = v1_pods
|
||||
|
||||
if label_selector:
|
||||
instances = v1_pods.get(namespace=namespace, label_selector=label_selector)
|
||||
if not instances.items:
|
||||
module.fail(
|
||||
msg="No pods in namespace {0} matched selector {1}".format(
|
||||
raise CoreException(
|
||||
"No pods in namespace {0} matched selector {1}".format(
|
||||
namespace, label_selector
|
||||
)
|
||||
)
|
||||
@@ -185,33 +193,32 @@ def execute_module(module, k8s_ansible_mixin):
|
||||
resource = v1_pods
|
||||
|
||||
kwargs = {}
|
||||
if module.params.get("container"):
|
||||
kwargs["query_params"] = dict(container=module.params["container"])
|
||||
if params.get("container"):
|
||||
kwargs["query_params"] = {"container": params["container"]}
|
||||
|
||||
if module.params.get("since_seconds"):
|
||||
if params.get("since_seconds"):
|
||||
kwargs.setdefault("query_params", {}).update(
|
||||
{"sinceSeconds": module.params["since_seconds"]}
|
||||
{"sinceSeconds": params["since_seconds"]}
|
||||
)
|
||||
|
||||
if module.params.get("previous"):
|
||||
kwargs.setdefault("query_params", {}).update(
|
||||
{"previous": module.params["previous"]}
|
||||
)
|
||||
if params.get("previous"):
|
||||
kwargs.setdefault("query_params", {}).update({"previous": params["previous"]})
|
||||
|
||||
log = serialize_log(
|
||||
resource.log.get(name=name, namespace=namespace, serialize=False, **kwargs)
|
||||
response = resource.log.get(
|
||||
name=name, namespace=namespace, serialize=False, **kwargs
|
||||
)
|
||||
log = response.data.decode("utf8")
|
||||
|
||||
module.exit_json(changed=False, log=log, log_lines=log.split("\n"))
|
||||
return {"changed": False, "log": log, "log_lines": log.split("\n")}
|
||||
|
||||
|
||||
def extract_selectors(module, instance):
|
||||
def extract_selectors(instance):
|
||||
# Parses selectors on an object based on the specifications documented here:
|
||||
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
|
||||
selectors = []
|
||||
if not instance.spec.selector:
|
||||
module.fail(
|
||||
msg="{0} {1} does not support the log subresource directly, and no Pod selector was found on the object".format(
|
||||
raise CoreException(
|
||||
"{0} {1} does not support the log subresource directly, and no Pod selector was found on the object".format(
|
||||
"/".join(instance.group, instance.apiVersion), instance.kind
|
||||
)
|
||||
)
|
||||
@@ -245,8 +252,8 @@ def extract_selectors(module, instance):
|
||||
)
|
||||
)
|
||||
else:
|
||||
module.fail(
|
||||
msg="The k8s_log module does not support the {0} matchExpression operator".format(
|
||||
raise CoreException(
|
||||
"The k8s_log module does not support the {0} matchExpression operator".format(
|
||||
operator.lower()
|
||||
)
|
||||
)
|
||||
@@ -254,22 +261,18 @@ def extract_selectors(module, instance):
|
||||
return selectors
|
||||
|
||||
|
||||
def serialize_log(response):
|
||||
if PY2:
|
||||
return response.data
|
||||
return response.data.decode("utf8")
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule, argument_spec=argspec(), supports_check_mode=True
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module=module)
|
||||
svc = K8sService(client, module)
|
||||
result = execute_module(svc, module.params)
|
||||
module.exit_json(**result)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -86,12 +86,23 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
AUTH_ARG_SPEC,
|
||||
NAME_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
)
|
||||
|
||||
|
||||
def get_managed_resource(module):
|
||||
def get_managed_resource(kind):
|
||||
managed_resource = {}
|
||||
|
||||
kind = module.params["kind"]
|
||||
if kind == "DaemonSet":
|
||||
managed_resource["kind"] = "ControllerRevision"
|
||||
managed_resource["api_version"] = "apps/v1"
|
||||
@@ -99,14 +110,17 @@ def get_managed_resource(module):
|
||||
managed_resource["kind"] = "ReplicaSet"
|
||||
managed_resource["api_version"] = "apps/v1"
|
||||
else:
|
||||
module.fail(msg="Cannot perform rollback on resource of kind {0}".format(kind))
|
||||
raise CoreException(
|
||||
"Cannot perform rollback on resource of kind {0}".format(kind)
|
||||
)
|
||||
return managed_resource
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
def execute_module(svc):
|
||||
results = []
|
||||
module = svc.module
|
||||
|
||||
resources = k8s_ansible_mixin.kubernetes_facts(
|
||||
resources = svc.find(
|
||||
module.params["kind"],
|
||||
module.params["api_version"],
|
||||
module.params["name"],
|
||||
@@ -117,14 +131,16 @@ def execute_module(module, k8s_ansible_mixin):
|
||||
|
||||
changed = False
|
||||
for resource in resources["resources"]:
|
||||
result = perform_action(module, k8s_ansible_mixin, resource)
|
||||
result = perform_action(svc, resource)
|
||||
changed = result["changed"] or changed
|
||||
results.append(result)
|
||||
|
||||
module.exit_json(**{"changed": changed, "rollback_info": results})
|
||||
|
||||
|
||||
def perform_action(module, k8s_ansible_mixin, resource):
|
||||
def perform_action(svc, resource):
|
||||
module = svc.module
|
||||
|
||||
if module.params["kind"] == "DaemonSet":
|
||||
current_revision = resource["metadata"]["generation"]
|
||||
elif module.params["kind"] == "Deployment":
|
||||
@@ -132,8 +148,8 @@ def perform_action(module, k8s_ansible_mixin, resource):
|
||||
"deployment.kubernetes.io/revision"
|
||||
]
|
||||
|
||||
managed_resource = get_managed_resource(module)
|
||||
managed_resources = k8s_ansible_mixin.kubernetes_facts(
|
||||
managed_resource = get_managed_resource(module.params["kind"])
|
||||
managed_resources = svc.find(
|
||||
managed_resource["kind"],
|
||||
managed_resource["api_version"],
|
||||
"",
|
||||
@@ -185,7 +201,7 @@ def perform_action(module, k8s_ansible_mixin, resource):
|
||||
|
||||
rollback = resource
|
||||
if not module.check_mode:
|
||||
rollback = k8s_ansible_mixin.client.request(
|
||||
rollback = svc.client.client.request(
|
||||
"PATCH",
|
||||
"/apis/{0}/namespaces/{1}/{2}/{3}".format(
|
||||
module.params["api_version"],
|
||||
@@ -242,15 +258,16 @@ def get_previous_revision(all_resources, current_revision):
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule, argument_spec=argspec(), supports_check_mode=True
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module=module)
|
||||
svc = K8sService(client, module)
|
||||
execute_module(svc)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -143,6 +143,14 @@ result:
|
||||
|
||||
import copy
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
@@ -151,7 +159,25 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
RESOURCE_ARG_SPEC,
|
||||
NAME_ARG_SPEC,
|
||||
)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
ResourceTimeout,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
diff_objects,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
get_waiter,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||
create_definitions,
|
||||
)
|
||||
|
||||
SCALE_ARG_SPEC = {
|
||||
"replicas": {"type": "int", "required": True},
|
||||
@@ -163,27 +189,20 @@ SCALE_ARG_SPEC = {
|
||||
}
|
||||
|
||||
|
||||
def execute_module(
|
||||
module,
|
||||
k8s_ansible_mixin,
|
||||
):
|
||||
k8s_ansible_mixin.set_resource_definitions(module)
|
||||
|
||||
definition = k8s_ansible_mixin.resource_definitions[0]
|
||||
|
||||
name = definition["metadata"]["name"]
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
api_version = definition["apiVersion"]
|
||||
kind = definition["kind"]
|
||||
def execute_module(client, module):
|
||||
current_replicas = module.params.get("current_replicas")
|
||||
replicas = module.params.get("replicas")
|
||||
resource_version = module.params.get("resource_version")
|
||||
|
||||
definitions = create_definitions(module.params)
|
||||
definition = definitions[0]
|
||||
name = definition["metadata"].get("name")
|
||||
namespace = definition["metadata"].get("namespace")
|
||||
api_version = definition["apiVersion"]
|
||||
kind = definition["kind"]
|
||||
label_selectors = module.params.get("label_selectors")
|
||||
if not label_selectors:
|
||||
label_selectors = []
|
||||
continue_on_error = module.params.get("continue_on_error")
|
||||
|
||||
wait = module.params.get("wait")
|
||||
wait_time = module.params.get("wait_timeout")
|
||||
wait_sleep = module.params.get("wait_sleep")
|
||||
@@ -195,12 +214,7 @@ def execute_module(
|
||||
if wait:
|
||||
return_attributes["duration"] = 0
|
||||
|
||||
resource = k8s_ansible_mixin.find_resource(kind, api_version, fail=True)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
NotFoundError,
|
||||
)
|
||||
|
||||
resource = client.resource(kind, api_version)
|
||||
multiple_scale = False
|
||||
try:
|
||||
existing = resource.get(
|
||||
@@ -211,11 +225,10 @@ def execute_module(
|
||||
multiple_scale = len(existing_items) > 1
|
||||
else:
|
||||
existing_items = [existing]
|
||||
except NotFoundError as exc:
|
||||
module.fail_json(
|
||||
msg="Failed to retrieve requested object: {0}".format(exc),
|
||||
error=exc.value.get("status"),
|
||||
)
|
||||
except NotFoundError as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
if multiple_scale:
|
||||
# when scaling multiple resource, the 'result' is changed to 'results' and is a list
|
||||
@@ -278,23 +291,28 @@ def execute_module(
|
||||
if module.check_mode:
|
||||
result["result"] = existing.to_dict()
|
||||
else:
|
||||
result["result"] = resource.patch(existing.to_dict()).to_dict()
|
||||
result["result"] = client.patch(
|
||||
resource, existing.to_dict()
|
||||
).to_dict()
|
||||
else:
|
||||
result = scale(
|
||||
module,
|
||||
k8s_ansible_mixin,
|
||||
resource,
|
||||
existing,
|
||||
replicas,
|
||||
wait,
|
||||
wait_time,
|
||||
wait_sleep,
|
||||
)
|
||||
try:
|
||||
result = scale(
|
||||
client,
|
||||
module,
|
||||
resource,
|
||||
existing,
|
||||
replicas,
|
||||
wait,
|
||||
wait_time,
|
||||
wait_sleep,
|
||||
)
|
||||
except CoreException as e:
|
||||
module.fail_json(msg=to_native(e))
|
||||
changed = changed or result["changed"]
|
||||
else:
|
||||
name = existing.metadata.name
|
||||
namespace = existing.metadata.namespace
|
||||
existing = resource.get(name=name, namespace=namespace)
|
||||
existing = client.get(resource, name=name, namespace=namespace)
|
||||
result = {"changed": False, "result": existing.to_dict()}
|
||||
if module._diff:
|
||||
result["diff"] = {}
|
||||
@@ -320,8 +338,8 @@ def argspec():
|
||||
|
||||
|
||||
def scale(
|
||||
client,
|
||||
module,
|
||||
k8s_ansible_mixin,
|
||||
resource,
|
||||
existing_object,
|
||||
replicas,
|
||||
@@ -334,8 +352,8 @@ def scale(
|
||||
kind = existing_object.kind
|
||||
|
||||
if not hasattr(resource, "scale"):
|
||||
module.fail_json(
|
||||
msg="Cannot perform scale on resource of kind {0}".format(resource.kind)
|
||||
raise CoreException(
|
||||
"Cannot perform scale on resource of kind {0}".format(resource.kind)
|
||||
)
|
||||
|
||||
scale_obj = {
|
||||
@@ -344,32 +362,37 @@ def scale(
|
||||
"spec": {"replicas": replicas},
|
||||
}
|
||||
|
||||
existing = resource.get(name=name, namespace=namespace)
|
||||
existing = client.get(resource, name=name, namespace=namespace)
|
||||
|
||||
result = dict()
|
||||
if module.check_mode:
|
||||
k8s_obj = copy.deepcopy(existing.to_dict())
|
||||
k8s_obj["spec"]["replicas"] = replicas
|
||||
match, diffs = k8s_ansible_mixin.diff_objects(existing.to_dict(), k8s_obj)
|
||||
if wait:
|
||||
result["duration"] = 0
|
||||
result["result"] = k8s_obj
|
||||
else:
|
||||
try:
|
||||
resource.scale.patch(body=scale_obj)
|
||||
except Exception as exc:
|
||||
module.fail_json(msg="Scale request failed: {0}".format(exc))
|
||||
except Exception as e:
|
||||
reason = e.body if hasattr(e, "body") else e
|
||||
msg = "Scale request failed: {0}".format(reason)
|
||||
raise CoreException(msg) from e
|
||||
|
||||
k8s_obj = resource.get(name=name, namespace=namespace).to_dict()
|
||||
k8s_obj = client.get(resource, name=name, namespace=namespace).to_dict()
|
||||
result["result"] = k8s_obj
|
||||
if wait and not module.check_mode:
|
||||
success, result["result"], result["duration"] = k8s_ansible_mixin.wait(
|
||||
resource, scale_obj, wait_sleep, wait_time
|
||||
if wait:
|
||||
waiter = get_waiter(client, resource)
|
||||
success, result["result"], result["duration"] = waiter.wait(
|
||||
timeout=wait_time,
|
||||
sleep=wait_sleep,
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
)
|
||||
if not success:
|
||||
module.fail_json(msg="Resource scaling timed out", **result)
|
||||
raise ResourceTimeout("Resource scaling timed out", **result)
|
||||
|
||||
match, diffs = k8s_ansible_mixin.diff_objects(existing.to_dict(), k8s_obj)
|
||||
match, diffs = diff_objects(existing.to_dict(), result["result"])
|
||||
result["changed"] = not match
|
||||
if module._diff:
|
||||
result["diff"] = diffs
|
||||
@@ -381,19 +404,18 @@ def main():
|
||||
mutually_exclusive = [
|
||||
("resource_definition", "src"),
|
||||
]
|
||||
module = AnsibleModule(
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
argument_spec=argspec(),
|
||||
mutually_exclusive=mutually_exclusive,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module=module)
|
||||
execute_module(client, module)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -154,6 +154,22 @@ from ansible_collections.kubernetes.core.plugins.module_utils.args_common import
|
||||
COMMON_ARG_SPEC,
|
||||
RESOURCE_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||
create_definitions,
|
||||
)
|
||||
|
||||
|
||||
SERVICE_ARG_SPEC = {
|
||||
"apply": {"type": "bool", "default": False},
|
||||
@@ -195,10 +211,35 @@ def argspec():
|
||||
return argument_spec
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
"""Module execution"""
|
||||
k8s_ansible_mixin.set_resource_definitions(module)
|
||||
def perform_action(svc, resource, definition, params):
|
||||
state = params.get("state", None)
|
||||
result = {}
|
||||
|
||||
existing = svc.retrieve(resource, definition)
|
||||
|
||||
if state == "absent":
|
||||
result = svc.delete(resource, definition, existing)
|
||||
result["method"] = "delete"
|
||||
else:
|
||||
if params.get("apply"):
|
||||
result = svc.apply(resource, definition, existing)
|
||||
result["method"] = "apply"
|
||||
elif not existing:
|
||||
result = svc.create(resource, definition)
|
||||
result["method"] = "create"
|
||||
elif params.get("force", False):
|
||||
result = svc.replace(resource, definition, existing)
|
||||
result["method"] = "replace"
|
||||
else:
|
||||
result = svc.update(resource, definition, existing)
|
||||
result["method"] = "update"
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def execute_module(svc):
|
||||
"""Module execution"""
|
||||
module = svc.module
|
||||
api_version = "v1"
|
||||
selector = module.params.get("selector")
|
||||
service_type = module.params.get("type")
|
||||
@@ -218,28 +259,30 @@ def execute_module(module, k8s_ansible_mixin):
|
||||
def_meta["name"] = module.params.get("name")
|
||||
def_meta["namespace"] = module.params.get("namespace")
|
||||
|
||||
# 'resource_definition:' has lower priority than module parameters
|
||||
definition = dict(
|
||||
merge_dicts(k8s_ansible_mixin.resource_definitions[0], definition)
|
||||
)
|
||||
definitions = create_definitions(module.params)
|
||||
|
||||
resource = k8s_ansible_mixin.find_resource("Service", api_version, fail=True)
|
||||
definition = k8s_ansible_mixin.set_defaults(resource, definition)
|
||||
result = k8s_ansible_mixin.perform_action(resource, definition)
|
||||
# 'resource_definition:' has lower priority than module parameters
|
||||
definition = dict(merge_dicts(definitions[0], definition))
|
||||
resource = svc.find_resource("Service", api_version, fail=True)
|
||||
|
||||
result = perform_action(svc, resource, definition, module.params)
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
argument_spec=argspec(),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
k8s_ansible_mixin = K8sAnsibleMixin(module)
|
||||
k8s_ansible_mixin.client = get_api_client(module=module)
|
||||
execute_module(module, k8s_ansible_mixin)
|
||||
try:
|
||||
client = get_api_client(module=module)
|
||||
svc = K8sService(client, module)
|
||||
execute_module(svc)
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -126,22 +126,29 @@ result:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin,
|
||||
get_api_client,
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
CoreException,
|
||||
)
|
||||
|
||||
try:
|
||||
from kubernetes.client.api import core_v1_api
|
||||
from kubernetes.client.exceptions import ApiException
|
||||
except ImportError:
|
||||
# ImportError are managed by the common module already.
|
||||
# ImportErrors are handled during module setup
|
||||
pass
|
||||
|
||||
|
||||
@@ -191,21 +198,9 @@ def argspec():
|
||||
|
||||
|
||||
class K8sTaintAnsible:
|
||||
def __init__(self, module):
|
||||
def __init__(self, module, client):
|
||||
self.module = module
|
||||
self.k8s_ansible_mixin = K8sAnsibleMixin(module=self.module)
|
||||
self.k8s_ansible_mixin.client = get_api_client(module=self.module)
|
||||
self.k8s_ansible_mixin.module = self.module
|
||||
self.k8s_ansible_mixin.argspec = self.module.argument_spec
|
||||
self.k8s_ansible_mixin.check_mode = self.module.check_mode
|
||||
self.k8s_ansible_mixin.params = self.module.params
|
||||
self.k8s_ansible_mixin.fail_json = self.module.fail_json
|
||||
self.k8s_ansible_mixin.fail = self.module.fail_json
|
||||
self.k8s_ansible_mixin.exit_json = self.module.exit_json
|
||||
self.k8s_ansible_mixin.warn = self.module.warn
|
||||
self.k8s_ansible_mixin.warnings = []
|
||||
self.api_instance = core_v1_api.CoreV1Api(self.k8s_ansible_mixin.client.client)
|
||||
self.k8s_ansible_mixin.check_library_version()
|
||||
self.api_instance = core_v1_api.CoreV1Api(client.client)
|
||||
self.changed = False
|
||||
|
||||
def get_node(self, name):
|
||||
@@ -301,12 +296,17 @@ class K8sTaintAnsible:
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
module = AnsibleK8SModule(
|
||||
module_class=AnsibleModule,
|
||||
argument_spec=argspec(),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
k8s_taint = K8sTaintAnsible(module)
|
||||
k8s_taint.execute_module()
|
||||
try:
|
||||
client = get_api_client(module)
|
||||
k8s_taint = K8sTaintAnsible(module, client.client)
|
||||
k8s_taint.execute_module()
|
||||
except CoreException as e:
|
||||
module.fail_from_exception(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
kubernetes-validate
|
||||
coverage==4.5.4
|
||||
mock
|
||||
pytest
|
||||
pytest-xdist
|
||||
pytest-mock
|
||||
|
||||
2
tests/config.yml
Normal file
2
tests/config.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
modules:
|
||||
python_requires: ">=3.6"
|
||||
@@ -5,7 +5,7 @@
|
||||
# This is a job definition that runs for 10 minutes and won't gracefully
|
||||
# shutdown. It allows us to test foreground vs background deletion.
|
||||
job_definition:
|
||||
apiVersion: v1
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "{{ gc_name }}"
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
- name: patch service using json merge patch
|
||||
kubernetes.core.k8s:
|
||||
kind: Deployment
|
||||
api_version: apps/v1
|
||||
namespace: "{{ k8s_patch_namespace }}"
|
||||
name: "{{ k8s_merge }}"
|
||||
merge_type:
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
assert:
|
||||
that:
|
||||
- patch_resource.changed
|
||||
- patch_resource.result.results | selectattr('warning', 'defined') | list | length == 1
|
||||
- patch_resource.result.results | selectattr('warnings', 'defined') | list | length == 1
|
||||
|
||||
- name: Ensure namespace {{ patch_only_namespace[0] }} was patched correctly
|
||||
kubernetes.core.k8s_info:
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
- name: Reapply the earlier deployment
|
||||
k8s:
|
||||
definition:
|
||||
api_version: apps/v1
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: scale-deploy
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
- assert:
|
||||
that:
|
||||
- k8s_no_validate is failed
|
||||
- "k8s_no_validate.msg == 'kubernetes-validate python library is required to validate resources'"
|
||||
- "'Failed to import the required Python library (kubernetes-validate)' in k8s_no_validate.msg"
|
||||
|
||||
- file:
|
||||
path: "{{ virtualenv }}"
|
||||
@@ -201,7 +201,7 @@
|
||||
- name: assert that task failed with proper message
|
||||
assert:
|
||||
that:
|
||||
- '"kubernetes >= 17.17.0 is required" in _result.msg'
|
||||
- '"This is required to use in-memory config." in _result.msg'
|
||||
when:
|
||||
- _stat.stat.exists
|
||||
- _stat.stat.readable
|
||||
|
||||
@@ -1,262 +1,178 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml 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
|
||||
plugins/module_utils/__init__.py compile-2.6!skip
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.6!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.6!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.6!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.6!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.6!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.6!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.6!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.9!skip
|
||||
plugins/module_utils/common.py compile-2.6!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.6!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.6!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.6!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.6!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.6!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.6!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.6!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.6!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.6!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.6!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.6!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.6!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.6!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.6!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.6!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.6!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.6!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.6!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.6!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.6!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_cluster_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.6!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.6!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.6!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.6!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.6!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.6!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.6!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.6!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.6!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py compile-2.6!skip
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.6!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
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/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py compile-2.6!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.6!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.6!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-3.5!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!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
|
||||
plugins/doc_fragments/k8s_name_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/_version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/copy.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py future-import-boilerplate!skip
|
||||
plugins/connection/kubectl.py future-import-boilerplate!skip
|
||||
plugins/inventory/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/action/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/filter/k8s.py future-import-boilerplate!skip
|
||||
tests/unit/conftest.py future-import-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py future-import-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_name_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/_version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py compile-2.6!skip
|
||||
plugins/module_utils/copy.py compile-2.7!skip
|
||||
plugins/module_utils/copy.py import-2.6!skip
|
||||
plugins/module_utils/copy.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/connection/kubectl.py metaclass-boilerplate!skip
|
||||
plugins/inventory/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/action/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/filter/k8s.py metaclass-boilerplate!skip
|
||||
tests/unit/conftest.py metaclass-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py metaclass-boilerplate!skip
|
||||
|
||||
@@ -1,262 +1,178 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml 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
|
||||
plugins/module_utils/__init__.py compile-2.6!skip
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.6!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.6!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.6!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.6!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.6!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.6!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.6!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.9!skip
|
||||
plugins/module_utils/common.py compile-2.6!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.6!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.6!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.6!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.6!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.6!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.6!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.6!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.6!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.6!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.6!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.6!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.6!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.6!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.6!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.6!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.6!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.6!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.6!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.6!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.6!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_cluster_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.6!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.6!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.6!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.6!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.6!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.6!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.6!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.6!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.6!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py compile-2.6!skip
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.6!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
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/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py compile-2.6!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.6!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.6!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-3.5!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!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
|
||||
plugins/doc_fragments/k8s_name_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/_version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/copy.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py future-import-boilerplate!skip
|
||||
plugins/connection/kubectl.py future-import-boilerplate!skip
|
||||
plugins/inventory/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/action/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/filter/k8s.py future-import-boilerplate!skip
|
||||
tests/unit/conftest.py future-import-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py future-import-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_name_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/_version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py compile-2.6!skip
|
||||
plugins/module_utils/copy.py compile-2.7!skip
|
||||
plugins/module_utils/copy.py import-2.6!skip
|
||||
plugins/module_utils/copy.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/connection/kubectl.py metaclass-boilerplate!skip
|
||||
plugins/inventory/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/action/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/filter/k8s.py metaclass-boilerplate!skip
|
||||
tests/unit/conftest.py metaclass-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py metaclass-boilerplate!skip
|
||||
|
||||
@@ -1,248 +1,31 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml 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
|
||||
plugins/module_utils/__init__.py compile-2.6!skip
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.6!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.6!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.6!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.6!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.6!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.6!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
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 metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.6!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.9!skip
|
||||
plugins/module_utils/client/resource.py import-3.10!skip
|
||||
plugins/module_utils/common.py compile-2.6!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.6!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.6!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.6!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.6!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.6!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.6!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.6!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.6!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.6!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.6!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.6!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.6!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.6!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.6!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.6!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.6!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.6!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.6!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.6!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.6!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_cluster_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.6!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.6!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.6!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.6!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.6!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.6!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.6!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.6!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.6!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py compile-2.6!skip
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.6!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
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/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
plugins/modules/k8s_cp.py compile-2.6!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.6!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
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
|
||||
|
||||
@@ -1,196 +1,31 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml 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
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
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 metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.9!skip
|
||||
plugins/module_utils/client/resource.py import-3.10!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
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/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!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
|
||||
plugins/module_utils/copy.py future-import-boilerplate!skip
|
||||
plugins/module_utils/copy.py metaclass-boilerplate!skip
|
||||
|
||||
@@ -1,196 +1,31 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml 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
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
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 metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.9!skip
|
||||
plugins/module_utils/client/resource.py import-3.10!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
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/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!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
|
||||
plugins/module_utils/copy.py future-import-boilerplate!skip
|
||||
plugins/module_utils/copy.py metaclass-boilerplate!skip
|
||||
|
||||
@@ -1,255 +1,171 @@
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!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/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
|
||||
plugins/module_utils/__init__.py compile-2.6!skip
|
||||
plugins/module_utils/__init__.py compile-2.7!skip
|
||||
plugins/module_utils/__init__.py compile-3.5!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py import-2.6!skip
|
||||
plugins/module_utils/__init__.py import-2.7!skip
|
||||
plugins/module_utils/__init__.py import-3.5!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py compile-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.6!skip
|
||||
plugins/module_utils/ansiblemodule.py import-2.7!skip
|
||||
plugins/module_utils/ansiblemodule.py import-3.5!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py compile-2.6!skip
|
||||
plugins/module_utils/apply.py compile-2.7!skip
|
||||
plugins/module_utils/apply.py compile-3.5!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py import-2.6!skip
|
||||
plugins/module_utils/apply.py import-2.7!skip
|
||||
plugins/module_utils/apply.py import-3.5!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/args_common.py compile-2.6!skip
|
||||
plugins/module_utils/args_common.py compile-2.7!skip
|
||||
plugins/module_utils/args_common.py compile-3.5!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py import-2.6!skip
|
||||
plugins/module_utils/args_common.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py import-3.5!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py import-2.6!skip
|
||||
plugins/module_utils/client/discovery.py import-2.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.5!skip
|
||||
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py import-2.6!skip
|
||||
plugins/module_utils/client/resource.py import-2.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.5!skip
|
||||
plugins/module_utils/client/resource.py import-3.6!skip
|
||||
plugins/module_utils/client/resource.py import-3.7!skip
|
||||
plugins/module_utils/client/resource.py import-3.8!skip
|
||||
plugins/module_utils/common.py compile-2.6!skip
|
||||
plugins/module_utils/common.py compile-2.7!skip
|
||||
plugins/module_utils/common.py compile-3.5!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py import-2.6!skip
|
||||
plugins/module_utils/common.py import-2.7!skip
|
||||
plugins/module_utils/common.py import-3.5!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py compile-2.6!skip
|
||||
plugins/module_utils/exceptions.py compile-2.7!skip
|
||||
plugins/module_utils/exceptions.py compile-3.5!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py import-2.6!skip
|
||||
plugins/module_utils/exceptions.py import-2.7!skip
|
||||
plugins/module_utils/exceptions.py import-3.5!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py compile-2.6!skip
|
||||
plugins/module_utils/hashes.py compile-2.7!skip
|
||||
plugins/module_utils/hashes.py compile-3.5!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py import-2.6!skip
|
||||
plugins/module_utils/hashes.py import-2.7!skip
|
||||
plugins/module_utils/hashes.py import-3.5!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py compile-2.6!skip
|
||||
plugins/module_utils/helm.py compile-2.7!skip
|
||||
plugins/module_utils/helm.py compile-3.5!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py import-2.6!skip
|
||||
plugins/module_utils/helm.py import-2.7!skip
|
||||
plugins/module_utils/helm.py import-3.5!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py compile-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-2.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.5!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py compile-2.6!skip
|
||||
plugins/modules/__init__.py compile-2.7!skip
|
||||
plugins/modules/__init__.py compile-3.5!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py import-2.6!skip
|
||||
plugins/modules/__init__.py import-2.7!skip
|
||||
plugins/modules/__init__.py import-3.5!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py compile-2.6!skip
|
||||
plugins/modules/helm.py compile-2.7!skip
|
||||
plugins/modules/helm.py compile-3.5!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py import-2.6!skip
|
||||
plugins/modules/helm.py import-2.7!skip
|
||||
plugins/modules/helm.py import-3.5!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py compile-2.6!skip
|
||||
plugins/modules/helm_info.py compile-2.7!skip
|
||||
plugins/modules/helm_info.py compile-3.5!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py import-2.6!skip
|
||||
plugins/modules/helm_info.py import-2.7!skip
|
||||
plugins/modules/helm_info.py import-3.5!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py import-2.6!skip
|
||||
plugins/modules/helm_plugin.py import-2.7!skip
|
||||
plugins/modules/helm_plugin.py import-3.5!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py compile-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py compile-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.6!skip
|
||||
plugins/modules/helm_plugin_info.py import-2.7!skip
|
||||
plugins/modules/helm_plugin_info.py import-3.5!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py compile-2.6!skip
|
||||
plugins/modules/helm_repository.py compile-2.7!skip
|
||||
plugins/modules/helm_repository.py compile-3.5!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py import-2.6!skip
|
||||
plugins/modules/helm_repository.py import-2.7!skip
|
||||
plugins/modules/helm_repository.py import-3.5!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py compile-2.6!skip
|
||||
plugins/modules/helm_template.py compile-2.7!skip
|
||||
plugins/modules/helm_template.py compile-3.5!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py import-2.6!skip
|
||||
plugins/modules/helm_template.py import-2.7!skip
|
||||
plugins/modules/helm_template.py import-3.5!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py compile-2.6!skip
|
||||
plugins/modules/k8s.py compile-2.7!skip
|
||||
plugins/modules/k8s.py compile-3.5!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py import-2.6!skip
|
||||
plugins/modules/k8s.py import-2.7!skip
|
||||
plugins/modules/k8s.py import-3.5!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_cluster_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.6!skip
|
||||
plugins/modules/k8s_cluster_info.py import-2.7!skip
|
||||
plugins/modules/k8s_cluster_info.py import-3.5!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py compile-2.6!skip
|
||||
plugins/modules/k8s_exec.py compile-2.7!skip
|
||||
plugins/modules/k8s_exec.py compile-3.5!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py import-2.6!skip
|
||||
plugins/modules/k8s_exec.py import-2.7!skip
|
||||
plugins/modules/k8s_exec.py import-3.5!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py compile-2.6!skip
|
||||
plugins/modules/k8s_info.py compile-2.7!skip
|
||||
plugins/modules/k8s_info.py compile-3.5!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py import-2.6!skip
|
||||
plugins/modules/k8s_info.py import-2.7!skip
|
||||
plugins/modules/k8s_info.py import-3.5!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py compile-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py compile-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.6!skip
|
||||
plugins/modules/k8s_json_patch.py import-2.7!skip
|
||||
plugins/modules/k8s_json_patch.py import-3.5!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py compile-2.6!skip
|
||||
plugins/modules/k8s_log.py compile-2.7!skip
|
||||
plugins/modules/k8s_log.py compile-3.5!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py import-2.6!skip
|
||||
plugins/modules/k8s_log.py import-2.7!skip
|
||||
plugins/modules/k8s_log.py import-3.5!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.6!skip
|
||||
plugins/modules/k8s_rollback.py compile-2.7!skip
|
||||
plugins/modules/k8s_rollback.py compile-3.5!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py import-2.6!skip
|
||||
plugins/modules/k8s_rollback.py import-2.7!skip
|
||||
plugins/modules/k8s_rollback.py import-3.5!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py compile-2.6!skip
|
||||
plugins/modules/k8s_scale.py compile-2.7!skip
|
||||
plugins/modules/k8s_scale.py compile-3.5!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py import-2.6!skip
|
||||
plugins/modules/k8s_scale.py import-2.7!skip
|
||||
plugins/modules/k8s_scale.py import-3.5!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py compile-2.6!skip
|
||||
plugins/modules/k8s_service.py compile-2.7!skip
|
||||
plugins/modules/k8s_service.py compile-3.5!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py import-2.6!skip
|
||||
plugins/modules/k8s_service.py import-2.7!skip
|
||||
plugins/modules/k8s_service.py import-3.5!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
tests/sanity/refresh_ignore_files shebang!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py compile-2.6!skip
|
||||
plugins/modules/k8s_cp.py compile-2.7!skip
|
||||
plugins/modules/k8s_cp.py import-2.6!skip
|
||||
plugins/modules/k8s_cp.py import-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.6!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-2.7!skip
|
||||
tests/integration/targets/k8s_copy/library/kubectl_file_compare.py compile-3.5!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py metaclass-boilerplate!skip
|
||||
tests/integration/targets/helm/library/helm_test_version.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py compile-2.7!skip
|
||||
plugins/modules/k8s_taint.py compile-3.5!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py import-2.7!skip
|
||||
plugins/modules/k8s_taint.py import-3.5!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_name_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py future-import-boilerplate!skip
|
||||
plugins/module_utils/helm.py future-import-boilerplate!skip
|
||||
plugins/module_utils/apply.py future-import-boilerplate!skip
|
||||
plugins/module_utils/hashes.py future-import-boilerplate!skip
|
||||
plugins/module_utils/version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/_version.py future-import-boilerplate!skip
|
||||
plugins/module_utils/copy.py future-import-boilerplate!skip
|
||||
plugins/module_utils/args_common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/__init__.py future-import-boilerplate!skip
|
||||
plugins/module_utils/selector.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py future-import-boilerplate!skip
|
||||
plugins/module_utils/common.py future-import-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py future-import-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py future-import-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py future-import-boilerplate!skip
|
||||
plugins/connection/kubectl.py future-import-boilerplate!skip
|
||||
plugins/inventory/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/k8s.py future-import-boilerplate!skip
|
||||
plugins/lookup/kustomize.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_template.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py future-import-boilerplate!skip
|
||||
plugins/modules/helm.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_info.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_repository.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_log.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py future-import-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_service.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py future-import-boilerplate!skip
|
||||
plugins/modules/__init__.py future-import-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py future-import-boilerplate!skip
|
||||
plugins/action/k8s_info.py future-import-boilerplate!skip
|
||||
plugins/filter/k8s.py future-import-boilerplate!skip
|
||||
tests/unit/conftest.py future-import-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py future-import-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py future-import-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py future-import-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py future-import-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_name_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_auth_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/helm_common_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_state_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_wait_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_scale_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_delete_options.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/__init__.py metaclass-boilerplate!skip
|
||||
plugins/doc_fragments/k8s_resource_options.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/helm.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/apply.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/hashes.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/_version.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/copy.py compile-2.6!skip
|
||||
plugins/module_utils/copy.py compile-2.7!skip
|
||||
plugins/module_utils/copy.py import-2.6!skip
|
||||
plugins/module_utils/copy.py import-2.7!skip
|
||||
plugins/module_utils/args_common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/__init__.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/selector.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8sdynamicclient.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/common.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/ansiblemodule.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/client/discovery.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/resource.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/core.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/waiter.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/client.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/runner.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/service.py metaclass-boilerplate!skip
|
||||
plugins/module_utils/k8s/exceptions.py metaclass-boilerplate!skip
|
||||
plugins/connection/kubectl.py metaclass-boilerplate!skip
|
||||
plugins/inventory/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/k8s.py metaclass-boilerplate!skip
|
||||
plugins/lookup/kustomize.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_scale.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_template.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_exec.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_repository.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_rollback.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_log.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_drain.py metaclass-boilerplate!skip
|
||||
plugins/modules/helm_plugin.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_taint.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_service.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cluster_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_cp.py metaclass-boilerplate!skip
|
||||
plugins/modules/__init__.py metaclass-boilerplate!skip
|
||||
plugins/modules/k8s_json_patch.py metaclass-boilerplate!skip
|
||||
plugins/action/k8s_info.py metaclass-boilerplate!skip
|
||||
plugins/filter/k8s.py metaclass-boilerplate!skip
|
||||
tests/unit/conftest.py metaclass-boilerplate!skip
|
||||
tests/unit/utils/ansible_module_mock.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_marshal.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_discoverer.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_hashes.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_resource.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_service.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_waiter.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_common.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_selector.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_apply.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_runner.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_client.py metaclass-boilerplate!skip
|
||||
tests/unit/module_utils/test_core.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template_module.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_helm_template.py metaclass-boilerplate!skip
|
||||
tests/unit/modules/test_module_helm.py metaclass-boilerplate!skip
|
||||
tests/unit/action/test_remove_omit.py metaclass-boilerplate!skip
|
||||
|
||||
@@ -1,39 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import itertools
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
target_dir = Path('.')
|
||||
|
||||
ignore_dir = target_dir / "tests" / "sanity"
|
||||
module_dir = target_dir / "plugins" / "modules"
|
||||
module_utils_dir = target_dir / "plugins" / "module_utils"
|
||||
ignore_dir.mkdir(parents=True, exist_ok=True)
|
||||
# Mapping of Ansible versions to supported Python versions
|
||||
ANSIBLE_VERSIONS = {
|
||||
"2.9": ["3.6", "3.7", "3.8"],
|
||||
"2.10": ["3.6", "3.7", "3.8", "3.9"],
|
||||
"2.11": ["3.6", "3.7", "3.8", "3.9"],
|
||||
"2.12": ["3.6", "3.7", "3.8", "3.9", "3.10"],
|
||||
"2.13": ["3.6", "3.7", "3.8", "3.9", "3.10"],
|
||||
"2.14": ["3.6", "3.7", "3.8", "3.9", "3.10"],
|
||||
}
|
||||
|
||||
skip_list = [
|
||||
"compile-2.6!skip", # Py3.8+
|
||||
"compile-2.7!skip", # Py3.8+
|
||||
"compile-3.5!skip", # Py3.8+
|
||||
"import-2.6!skip", # Py3.8+
|
||||
"import-2.7!skip", # Py3.8+
|
||||
"import-3.5!skip", # Py3.8+
|
||||
"future-import-boilerplate!skip", # Py2 only
|
||||
"metaclass-boilerplate!skip", # Py2 only
|
||||
IMPORT_SKIPS = [
|
||||
"plugins/module_utils/client/discovery.py",
|
||||
"plugins/module_utils/client/resource.py",
|
||||
"plugins/module_utils/k8sdynamicclient.py",
|
||||
]
|
||||
|
||||
for version in ["2.9", "2.10", "2.11", "2.12"]:
|
||||
ignore_file = ignore_dir / f"ignore-{version}.txt"
|
||||
ignore_content = ignore_file.read_text().split("\n")
|
||||
ignore_content.append(f"tests/sanity/refresh_ignore_files shebang!skip")
|
||||
# Adds validate-modules:parameter-type-not-in-doc
|
||||
PARAM_TYPE_SKIPS = [
|
||||
"plugins/modules/k8s.py",
|
||||
"plugins/modules/k8s_scale.py",
|
||||
"plugins/modules/k8s_service.py",
|
||||
]
|
||||
|
||||
for f in module_dir.glob("*.py"):
|
||||
if f.is_symlink():
|
||||
continue
|
||||
for test in skip_list:
|
||||
ignore_content.append(f"{f} {test}")
|
||||
for f in module_utils_dir.glob("*.py"):
|
||||
if f.is_symlink():
|
||||
continue
|
||||
for test in skip_list:
|
||||
ignore_content.append(f"{f} {test}")
|
||||
ignore_file = ignore_dir / f"ignore-{version}.txt"
|
||||
ignore_file.write_text("\n".join(sorted(set(ignore_content))).lstrip("\n"))
|
||||
# Adds validate-modules:return-syntax-error
|
||||
RETURN_SYNTAX_SKIPS = [
|
||||
"plugins/modules/k8s.py",
|
||||
"plugins/modules/k8s_scale.py",
|
||||
"plugins/modules/k8s_service.py",
|
||||
"plugins/modules/k8s_taint.py",
|
||||
]
|
||||
|
||||
YAML_LINT_SKIPS = [
|
||||
"tests/unit/module_utils/fixtures/definitions.yml",
|
||||
"tests/unit/module_utils/fixtures/deployments.yml",
|
||||
"tests/unit/module_utils/fixtures/pods.yml",
|
||||
"tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml",
|
||||
"tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml",
|
||||
"tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml",
|
||||
"tests/integration/targets/helm/files/test-chart/templates/configmap.yaml",
|
||||
"tests/integration/targets/k8s_scale/files/deployment.yaml",
|
||||
]
|
||||
|
||||
# Add shebang!skip
|
||||
SHEBANG_SKIPS = [
|
||||
"tests/sanity/refresh_ignore_files",
|
||||
]
|
||||
|
||||
|
||||
def import_skips(*versions):
|
||||
for f in IMPORT_SKIPS:
|
||||
for v in versions:
|
||||
yield f"{f} import-{v}!skip"
|
||||
|
||||
def param_type_skips():
|
||||
for f in PARAM_TYPE_SKIPS:
|
||||
yield f"{f} validate-modules:parameter-type-not-in-doc"
|
||||
|
||||
|
||||
def return_syntax_skips(ansible_version):
|
||||
if ansible_version != "2.9":
|
||||
for f in RETURN_SYNTAX_SKIPS:
|
||||
yield f"{f} validate-modules:return-syntax-error"
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
def yaml_lint_skips():
|
||||
for f in YAML_LINT_SKIPS:
|
||||
yield f"{f} yamllint!skip"
|
||||
|
||||
|
||||
def shebang_skips():
|
||||
for f in SHEBANG_SKIPS:
|
||||
yield f"{f} shebang!skip"
|
||||
|
||||
|
||||
def import_boilerplate(path, ansible_version):
|
||||
if ansible_version in ("2.9", "2.10", "2.11"):
|
||||
for f in (p for p in path.glob("**/*.py") if not p.is_symlink()):
|
||||
yield f"{f} future-import-boilerplate!skip"
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
def metaclass_boilerplate(path, ansible_version):
|
||||
if ansible_version in ("2.9", "2.10", "2.11"):
|
||||
for f in (p for p in path.glob("**/*.py") if not p.is_symlink()):
|
||||
yield f"{f} metaclass-boilerplate!skip"
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
def main():
|
||||
target_dir = Path('.')
|
||||
sanity_dir = target_dir / "tests" / "sanity"
|
||||
plugins = target_dir / "plugins"
|
||||
units = target_dir / "tests" / "unit"
|
||||
|
||||
for ansible, python in ANSIBLE_VERSIONS.items():
|
||||
with open(sanity_dir / f"ignore-{ansible}.txt", "w") as fp:
|
||||
ignores = itertools.chain(
|
||||
import_skips(*python),
|
||||
param_type_skips(),
|
||||
yaml_lint_skips(),
|
||||
shebang_skips(),
|
||||
return_syntax_skips(ansible),
|
||||
import_boilerplate(plugins, ansible),
|
||||
import_boilerplate(units, ansible),
|
||||
metaclass_boilerplate(plugins, ansible),
|
||||
metaclass_boilerplate(units, ansible))
|
||||
for f in filter(None, ignores):
|
||||
fp.write(f + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
44
tests/unit/conftest.py
Normal file
44
tests/unit/conftest.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import json
|
||||
import sys
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
import ansible.module_utils.basic
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def stdin(mocker, request):
|
||||
old_args = ansible.module_utils.basic._ANSIBLE_ARGS
|
||||
ansible.module_utils.basic._ANSIBLE_ARGS = None
|
||||
old_argv = sys.argv
|
||||
sys.argv = ["ansible_unittest"]
|
||||
|
||||
if isinstance(request.param, string_types):
|
||||
args = request.param
|
||||
elif isinstance(request.param, MutableMapping):
|
||||
if "ANSIBLE_MODULE_ARGS" not in request.param:
|
||||
request.param = {"ANSIBLE_MODULE_ARGS": request.param}
|
||||
if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]:
|
||||
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp"
|
||||
if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]:
|
||||
request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False
|
||||
args = json.dumps(request.param)
|
||||
else:
|
||||
raise Exception("Malformed data to the stdin pytest fixture")
|
||||
|
||||
fake_stdin = BytesIO(to_bytes(args, errors="surrogate_or_strict"))
|
||||
mocker.patch("ansible.module_utils.basic.sys.stdin", mocker.MagicMock())
|
||||
mocker.patch("ansible.module_utils.basic.sys.stdin.buffer", fake_stdin)
|
||||
|
||||
yield fake_stdin
|
||||
|
||||
ansible.module_utils.basic._ANSIBLE_ARGS = old_args
|
||||
sys.argv = old_argv
|
||||
34
tests/unit/module_utils/fixtures/definitions.yml
Normal file
34
tests/unit/module_utils/fixtures/definitions.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: test-1
|
||||
---
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pod-1
|
||||
namespace: test-1
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
---
|
||||
kind: PodList
|
||||
apiVersion: v1
|
||||
metadata: {}
|
||||
items:
|
||||
- kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: pod-1
|
||||
namespace: test-1
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
---
|
||||
kind: ConfigMapList
|
||||
apiVersion: v1
|
||||
metadata: {}
|
||||
items: []
|
||||
48
tests/unit/module_utils/fixtures/deployments.yml
Normal file
48
tests/unit/module_utils/fixtures/deployments.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: deploy-1
|
||||
namespace: test-1
|
||||
generation: 1
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: foo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: foo
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
status:
|
||||
availableReplicas: 2
|
||||
replicas: 2
|
||||
observedGeneration: 1
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: deploy-2
|
||||
namespace: test-1
|
||||
generation: 1
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: foo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: foo
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
status:
|
||||
availableReplicas: 1
|
||||
replicas: 2
|
||||
observedGeneration: 1
|
||||
63
tests/unit/module_utils/fixtures/pods.yml
Normal file
63
tests/unit/module_utils/fixtures/pods.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
namespace: test-1
|
||||
name: pod-1
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
status:
|
||||
containerStatuses:
|
||||
- name: busybox
|
||||
ready: true
|
||||
conditions:
|
||||
- type: "www.example.com/gate"
|
||||
status: "True"
|
||||
---
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
namespace: test-1
|
||||
name: pod-2
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
---
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
namespace: test-1
|
||||
name: pod-3
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
status:
|
||||
phase: Pending
|
||||
conditions:
|
||||
- type: "www.example.com/gate"
|
||||
status: "Unknown"
|
||||
containerStatuses:
|
||||
- name: busybox
|
||||
ready: true
|
||||
---
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
namespace: test-1
|
||||
name: pod-4
|
||||
spec:
|
||||
containers:
|
||||
- image: busybox
|
||||
name: busybox
|
||||
status:
|
||||
phase: Pending
|
||||
conditions:
|
||||
- type: "www.example.com/other"
|
||||
status: "Unknown"
|
||||
containerStatuses:
|
||||
- name: busybox
|
||||
ready: true
|
||||
162
tests/unit/module_utils/test_client.py
Normal file
162
tests/unit/module_utils/test_client.py
Normal file
@@ -0,0 +1,162 @@
|
||||
import os
|
||||
import base64
|
||||
import tempfile
|
||||
import yaml
|
||||
import mock
|
||||
from mock import MagicMock
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
_create_auth_spec,
|
||||
_create_configuration,
|
||||
)
|
||||
|
||||
TEST_HOST = "test-host"
|
||||
TEST_SSL_HOST = "https://test-host"
|
||||
TEST_CLIENT_CERT = "/dev/null"
|
||||
TEST_CLIENT_KEY = "/dev/null"
|
||||
TEST_CERTIFICATE_AUTH = "/dev/null"
|
||||
TEST_DATA = "test-data"
|
||||
TEST_BEARER_TOKEN = "Bearer %s" % base64.standard_b64encode(TEST_DATA.encode()).decode()
|
||||
TEST_KUBE_CONFIG = {
|
||||
"current-context": "federal-context",
|
||||
"contexts": [
|
||||
{
|
||||
"name": "simple_token",
|
||||
"context": {"cluster": "default", "user": "simple_token"},
|
||||
}
|
||||
],
|
||||
"clusters": [{"name": "default", "cluster": {"server": TEST_HOST}}],
|
||||
"users": [
|
||||
{
|
||||
"name": "ssl-no_file",
|
||||
"user": {
|
||||
"token": TEST_BEARER_TOKEN,
|
||||
"client-certificate": TEST_CLIENT_CERT,
|
||||
"client-key": TEST_CLIENT_KEY,
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
_temp_files = []
|
||||
|
||||
|
||||
def _remove_temp_file():
|
||||
for f in _temp_files:
|
||||
try:
|
||||
os.remove(f)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
def _create_temp_file(content=""):
|
||||
handler, name = tempfile.mkstemp()
|
||||
_temp_files.append(name)
|
||||
os.write(handler, str.encode(content))
|
||||
os.close(handler)
|
||||
return name
|
||||
|
||||
|
||||
def test_create_auth_spec_ssl_no_options():
|
||||
module = MagicMock()
|
||||
module.params = {}
|
||||
actual_auth_spec = _create_auth_spec(module)
|
||||
|
||||
assert "proxy_headers" in actual_auth_spec
|
||||
|
||||
|
||||
def test_create_auth_spec_ssl_options():
|
||||
ssl_options = {
|
||||
"host": TEST_SSL_HOST,
|
||||
"token": TEST_BEARER_TOKEN,
|
||||
"client_cert": TEST_CLIENT_CERT,
|
||||
"client_key": TEST_CLIENT_KEY,
|
||||
"ca_cert": TEST_CERTIFICATE_AUTH,
|
||||
"validate_certs": True,
|
||||
}
|
||||
expected_auth_spec = {
|
||||
"host": TEST_SSL_HOST,
|
||||
"cert_file": TEST_CLIENT_CERT,
|
||||
"key_file": TEST_CLIENT_KEY,
|
||||
"ssl_ca_cert": TEST_CERTIFICATE_AUTH,
|
||||
"verify_ssl": True,
|
||||
"proxy_headers": {},
|
||||
}
|
||||
|
||||
module = MagicMock()
|
||||
module.params = ssl_options
|
||||
actual_auth_spec = _create_auth_spec(module)
|
||||
|
||||
assert expected_auth_spec.items() <= actual_auth_spec.items()
|
||||
|
||||
|
||||
def test_create_auth_spec_ssl_options_no_verify():
|
||||
ssl_options = {
|
||||
"host": TEST_SSL_HOST,
|
||||
"token": TEST_BEARER_TOKEN,
|
||||
"client_cert": TEST_CLIENT_CERT,
|
||||
"client_key": TEST_CLIENT_KEY,
|
||||
"validate_certs": False,
|
||||
}
|
||||
|
||||
expected_auth_spec = {
|
||||
"host": TEST_SSL_HOST,
|
||||
"cert_file": TEST_CLIENT_CERT,
|
||||
"key_file": TEST_CLIENT_KEY,
|
||||
"verify_ssl": False,
|
||||
"proxy_headers": {},
|
||||
}
|
||||
|
||||
module = MagicMock()
|
||||
module.params = ssl_options
|
||||
actual_auth_spec = _create_auth_spec(module)
|
||||
|
||||
assert expected_auth_spec.items() <= actual_auth_spec.items()
|
||||
|
||||
|
||||
@mock.patch.dict(os.environ, {"K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH": "foo:bar"})
|
||||
@mock.patch.dict(os.environ, {"K8S_AUTH_PROXY_HEADERS_USER_AGENT": "foo/1.0"})
|
||||
@mock.patch.dict(os.environ, {"K8S_AUTH_CERT_FILE": TEST_CLIENT_CERT})
|
||||
def test_create_auth_spec_ssl_proxy():
|
||||
expected_auth_spec = {
|
||||
"kubeconfig": "~/.kube/customconfig",
|
||||
"verify_ssl": True,
|
||||
"cert_file": TEST_CLIENT_CERT,
|
||||
"proxy_headers": {"proxy_basic_auth": "foo:bar", "user_agent": "foo/1.0"},
|
||||
}
|
||||
module = MagicMock()
|
||||
options = {"validate_certs": True, "kubeconfig": "~/.kube/customconfig"}
|
||||
|
||||
module.params = options
|
||||
actual_auth_spec = _create_auth_spec(module)
|
||||
|
||||
assert expected_auth_spec.items() <= actual_auth_spec.items()
|
||||
|
||||
|
||||
def test_load_kube_config_from_file_path():
|
||||
config_file = _create_temp_file(yaml.safe_dump(TEST_KUBE_CONFIG))
|
||||
auth = {"kubeconfig": config_file, "context": "simple_token"}
|
||||
actual_configuration = _create_configuration(auth)
|
||||
|
||||
expected_configuration = {
|
||||
"host": TEST_HOST,
|
||||
"kubeconfig": config_file,
|
||||
"context": "simple_token",
|
||||
}
|
||||
|
||||
assert expected_configuration.items() <= actual_configuration.__dict__.items()
|
||||
_remove_temp_file()
|
||||
|
||||
|
||||
def test_load_kube_config_from_dict():
|
||||
auth_spec = {"kubeconfig": TEST_KUBE_CONFIG, "context": "simple_token"}
|
||||
actual_configuration = _create_configuration(auth_spec)
|
||||
|
||||
expected_configuration = {
|
||||
"host": TEST_HOST,
|
||||
"kubeconfig": TEST_KUBE_CONFIG,
|
||||
"context": "simple_token",
|
||||
}
|
||||
|
||||
assert expected_configuration.items() <= actual_configuration.__dict__.items()
|
||||
_remove_temp_file()
|
||||
91
tests/unit/module_utils/test_core.py
Normal file
91
tests/unit/module_utils/test_core.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import json
|
||||
|
||||
import kubernetes
|
||||
import pytest
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
AnsibleK8SModule,
|
||||
)
|
||||
|
||||
MINIMAL_K8S_VERSION = "12.0.0"
|
||||
UNSUPPORTED_K8S_VERSION = "11.0.0"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("stdin", [{}], indirect=["stdin"])
|
||||
def test_no_warn(monkeypatch, stdin, capfd):
|
||||
monkeypatch.setattr(kubernetes, "__version__", MINIMAL_K8S_VERSION)
|
||||
|
||||
module = AnsibleK8SModule(argument_spec={})
|
||||
with pytest.raises(SystemExit):
|
||||
module.exit_json()
|
||||
out, err = capfd.readouterr()
|
||||
|
||||
return_value = json.loads(out)
|
||||
|
||||
assert return_value.get("exception") is None
|
||||
assert return_value.get("warnings") is None
|
||||
assert return_value.get("failed") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("stdin", [{}], indirect=["stdin"])
|
||||
def test_warn_on_k8s_version(monkeypatch, stdin, capfd):
|
||||
monkeypatch.setattr(kubernetes, "__version__", UNSUPPORTED_K8S_VERSION)
|
||||
|
||||
module = AnsibleK8SModule(argument_spec={})
|
||||
with pytest.raises(SystemExit):
|
||||
module.exit_json()
|
||||
out, err = capfd.readouterr()
|
||||
|
||||
return_value = json.loads(out)
|
||||
|
||||
assert return_value.get("warnings") is not None
|
||||
warnings = return_value["warnings"]
|
||||
assert len(warnings) == 1
|
||||
assert "kubernetes" in warnings[0]
|
||||
assert MINIMAL_K8S_VERSION in warnings[0]
|
||||
|
||||
|
||||
dependencies = [
|
||||
["18.20.0", "12.0.1", False],
|
||||
["18.20.0", "18.20.0", True],
|
||||
["12.0.1", "18.20.0", True],
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stdin,desired,actual,result", [({}, *d) for d in dependencies], indirect=["stdin"]
|
||||
)
|
||||
def test_has_at_least(monkeypatch, stdin, desired, actual, result, capfd):
|
||||
monkeypatch.setattr(kubernetes, "__version__", actual)
|
||||
|
||||
module = AnsibleK8SModule(argument_spec={})
|
||||
|
||||
assert module.has_at_least("kubernetes", desired) is result
|
||||
|
||||
|
||||
dependencies = [
|
||||
["kubernetes", "18.20.0", "(kubernetes>=18.20.0)"],
|
||||
["foobar", "1.0.0", "(foobar>=1.0.0)"],
|
||||
["foobar", None, "(foobar)"],
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stdin,dependency,version,msg", [({}, *d) for d in dependencies], indirect=["stdin"]
|
||||
)
|
||||
def test_requires_fails_with_message(
|
||||
monkeypatch, stdin, dependency, version, msg, capfd
|
||||
):
|
||||
monkeypatch.setattr(kubernetes, "__version__", "12.0.0")
|
||||
module = AnsibleK8SModule(argument_spec={})
|
||||
with pytest.raises(SystemExit):
|
||||
module.requires(dependency, version)
|
||||
out, err = capfd.readouterr()
|
||||
return_value = json.loads(out)
|
||||
|
||||
assert return_value.get("failed")
|
||||
assert msg in return_value.get("msg")
|
||||
187
tests/unit/module_utils/test_resource.py
Normal file
187
tests/unit/module_utils/test_resource.py
Normal file
@@ -0,0 +1,187 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||
create_definitions,
|
||||
flatten_list_kind,
|
||||
from_file,
|
||||
from_yaml,
|
||||
merge_params,
|
||||
)
|
||||
|
||||
|
||||
def test_create_definitions_loads_from_definition():
|
||||
params = {
|
||||
"resource_definition": {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "foo", "namespace": "bar"},
|
||||
}
|
||||
}
|
||||
results = create_definitions(params)
|
||||
assert len(results) == 1
|
||||
assert results[0].kind == "Pod"
|
||||
assert results[0].api_version == "v1"
|
||||
assert results[0].name == "foo"
|
||||
assert results[0].namespace == "bar"
|
||||
|
||||
|
||||
def test_create_definitions_loads_from_file():
|
||||
current = Path(os.path.dirname(os.path.abspath(__file__)))
|
||||
params = {"src": current / "fixtures/definitions.yml"}
|
||||
results = create_definitions(params)
|
||||
assert len(results) == 3
|
||||
assert results[0].kind == "Namespace"
|
||||
assert results[1].kind == "Pod"
|
||||
|
||||
|
||||
def test_create_definitions_loads_from_params():
|
||||
params = {
|
||||
"kind": "Pod",
|
||||
"api_version": "v1",
|
||||
"name": "foo",
|
||||
"namespace": "foobar",
|
||||
}
|
||||
results = create_definitions(params)
|
||||
assert len(results) == 1
|
||||
assert results[0] == {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "foo", "namespace": "foobar"},
|
||||
}
|
||||
|
||||
|
||||
def test_create_definitions_loads_list_kind():
|
||||
params = {
|
||||
"resource_definition": {
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"items": [
|
||||
{"kind": "Pod", "metadata": {"name": "foo"}},
|
||||
{"kind": "Pod", "metadata": {"name": "bar"}},
|
||||
],
|
||||
}
|
||||
}
|
||||
results = create_definitions(params)
|
||||
assert len(results) == 2
|
||||
assert results[0].name == "foo"
|
||||
assert results[1].name == "bar"
|
||||
|
||||
|
||||
def test_merge_params_does_not_overwrite():
|
||||
definition = {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "foo", "namespace": "bar"},
|
||||
}
|
||||
params = {
|
||||
"kind": "Service",
|
||||
"api_version": "v2",
|
||||
"name": "baz",
|
||||
"namespace": "gaz",
|
||||
}
|
||||
result = merge_params(definition, params)
|
||||
assert result == definition
|
||||
|
||||
|
||||
def test_merge_params_adds_module_params():
|
||||
params = {
|
||||
"kind": "Pod",
|
||||
"api_version": "v1",
|
||||
"namespace": "bar",
|
||||
"generate_name": "foo-",
|
||||
}
|
||||
result = merge_params({}, params)
|
||||
assert result == {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"generateName": "foo-", "namespace": "bar"},
|
||||
}
|
||||
|
||||
|
||||
def test_from_yaml_loads_string_docs():
|
||||
definition = """
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: bar
|
||||
---
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: bar
|
||||
"""
|
||||
result = list(from_yaml(definition))
|
||||
assert result[0]["kind"] == "Pod"
|
||||
assert result[1]["kind"] == "ConfigMap"
|
||||
|
||||
|
||||
def test_from_yaml_loads_list():
|
||||
definition = [
|
||||
"""
|
||||
kind: Pod
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: bar
|
||||
""",
|
||||
"""
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: bar
|
||||
""",
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "baz", "namespace": "bar"},
|
||||
},
|
||||
]
|
||||
result = list(from_yaml(definition))
|
||||
assert len(result) == 3
|
||||
assert result[0]["kind"] == "Pod"
|
||||
assert result[1]["kind"] == "ConfigMap"
|
||||
assert result[2]["metadata"]["name"] == "baz"
|
||||
|
||||
|
||||
def test_from_yaml_loads_dictionary():
|
||||
definition = {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "foo", "namespace": "bar"},
|
||||
}
|
||||
result = list(from_yaml(definition))
|
||||
assert result[0]["kind"] == "Pod"
|
||||
|
||||
|
||||
def test_from_file_loads_definitions():
|
||||
current = Path(os.path.dirname(os.path.abspath(__file__)))
|
||||
result = list(from_file(current / "fixtures/definitions.yml"))
|
||||
assert result[0]["kind"] == "Namespace"
|
||||
assert result[1]["kind"] == "Pod"
|
||||
|
||||
|
||||
def test_flatten_list_kind_flattens():
|
||||
definition = {
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"items": [
|
||||
{"kind": "Pod", "metadata": {"name": "foo"}},
|
||||
{"kind": "Pod", "metadata": {"name": "bar"}},
|
||||
],
|
||||
}
|
||||
result = flatten_list_kind(definition, {"namespace": "foobar"})
|
||||
assert len(result) == 2
|
||||
|
||||
assert result[0]["kind"] == "Pod"
|
||||
assert result[0]["apiVersion"] == "v1"
|
||||
assert result[0]["metadata"]["name"] == "foo"
|
||||
assert result[0]["metadata"]["namespace"] == "foobar"
|
||||
|
||||
assert result[1]["kind"] == "Pod"
|
||||
assert result[1]["apiVersion"] == "v1"
|
||||
assert result[1]["metadata"]["name"] == "bar"
|
||||
assert result[1]["metadata"]["namespace"] == "foobar"
|
||||
135
tests/unit/module_utils/test_runner.py
Normal file
135
tests/unit/module_utils/test_runner.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import pytest
|
||||
from copy import deepcopy
|
||||
from unittest.mock import Mock
|
||||
|
||||
from kubernetes.dynamic.resource import ResourceInstance
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.runner import (
|
||||
perform_action,
|
||||
)
|
||||
|
||||
definition = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"name": "foo",
|
||||
"labels": {"environment": "production", "app": "nginx"},
|
||||
"namespace": "foo",
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx:1.14.2",
|
||||
"command": ["/bin/sh", "-c", "sleep 10"],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
modified_def = deepcopy(definition)
|
||||
modified_def["metadata"]["labels"]["environment"] = "testing"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"action, params, existing, instance, expected",
|
||||
[
|
||||
(
|
||||
"delete",
|
||||
{"state": "absent"},
|
||||
{},
|
||||
{},
|
||||
{"changed": False, "method": "delete", "result": {}},
|
||||
),
|
||||
(
|
||||
"delete",
|
||||
{"state": "absent"},
|
||||
definition,
|
||||
{"kind": "Status"},
|
||||
{"changed": True, "method": "delete", "result": {"kind": "Status"}},
|
||||
),
|
||||
(
|
||||
"apply",
|
||||
{"apply": "yes"},
|
||||
{},
|
||||
definition,
|
||||
{"changed": True, "method": "apply", "result": definition},
|
||||
),
|
||||
(
|
||||
"create",
|
||||
{"state": "patched"},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
"changed": False,
|
||||
"result": {},
|
||||
"warnings": [
|
||||
"resource 'kind=Pod,name=foo' was not found but will not be created as 'state' parameter has been set to 'patched'"
|
||||
],
|
||||
},
|
||||
),
|
||||
(
|
||||
"create",
|
||||
{},
|
||||
{},
|
||||
definition,
|
||||
{"changed": True, "method": "create", "result": definition},
|
||||
),
|
||||
(
|
||||
"replace",
|
||||
{"force": "yes"},
|
||||
definition,
|
||||
definition,
|
||||
{"changed": False, "method": "replace", "result": definition},
|
||||
),
|
||||
(
|
||||
"replace",
|
||||
{"force": "yes"},
|
||||
definition,
|
||||
modified_def,
|
||||
{"changed": True, "method": "replace", "result": modified_def},
|
||||
),
|
||||
(
|
||||
"update",
|
||||
{},
|
||||
definition,
|
||||
definition,
|
||||
{"changed": False, "method": "update", "result": definition},
|
||||
),
|
||||
(
|
||||
"update",
|
||||
{},
|
||||
definition,
|
||||
modified_def,
|
||||
{"changed": True, "method": "update", "result": modified_def},
|
||||
),
|
||||
(
|
||||
"create",
|
||||
{"label_selectors": ["app=foo"]},
|
||||
{},
|
||||
definition,
|
||||
{
|
||||
"changed": False,
|
||||
"msg": "resource 'kind=Pod,name=foo,namespace=foo' filtered by label_selectors.",
|
||||
},
|
||||
),
|
||||
(
|
||||
"create",
|
||||
{"label_selectors": ["app=nginx"]},
|
||||
{},
|
||||
definition,
|
||||
{"changed": True, "method": "create", "result": definition},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_perform_action(action, params, existing, instance, expected):
|
||||
svc = Mock()
|
||||
svc.find_resource.return_value = Mock(
|
||||
kind=definition["kind"], group_version=definition["apiVersion"]
|
||||
)
|
||||
svc.retrieve.return_value = ResourceInstance(None, existing) if existing else None
|
||||
spec = {action + ".return_value": instance}
|
||||
svc.configure_mock(**spec)
|
||||
|
||||
result = perform_action(svc, definition, params)
|
||||
assert expected.items() <= result.items()
|
||||
292
tests/unit/module_utils/test_service.py
Normal file
292
tests/unit/module_utils/test_service.py
Normal file
@@ -0,0 +1,292 @@
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from kubernetes.dynamic.resource import ResourceInstance, Resource
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||
K8sService,
|
||||
diff_objects,
|
||||
)
|
||||
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
|
||||
pod_definition = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"name": "foo",
|
||||
"labels": {"environment": "production", "app": "nginx"},
|
||||
"namespace": "foo",
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx:1.14.2",
|
||||
"command": ["/bin/sh", "-c", "sleep 10"],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
pod_definition_updated = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"name": "foo",
|
||||
"labels": {"environment": "testing", "app": "nginx"},
|
||||
"namespace": "bar",
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx:1.14.2",
|
||||
"command": ["/bin/sh", "-c", "sleep 10"],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def mock_pod_resource_instance():
|
||||
return ResourceInstance(None, pod_definition)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def mock_pod_updated_resource_instance():
|
||||
return ResourceInstance(None, pod_definition_updated)
|
||||
|
||||
|
||||
def test_diff_objects_no_diff():
|
||||
match, diff = diff_objects(pod_definition, pod_definition)
|
||||
|
||||
assert match is True
|
||||
assert diff == {}
|
||||
|
||||
|
||||
def test_diff_objects_meta_diff():
|
||||
match, diff = diff_objects(pod_definition, pod_definition_updated)
|
||||
|
||||
assert match is False
|
||||
assert diff["before"] == {
|
||||
"metadata": {"labels": {"environment": "production"}, "namespace": "foo"}
|
||||
}
|
||||
assert diff["after"] == {
|
||||
"metadata": {"labels": {"environment": "testing"}, "namespace": "bar"}
|
||||
}
|
||||
|
||||
|
||||
def test_diff_objects_spec_diff():
|
||||
pod_definition_updated = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"name": "foo",
|
||||
"labels": {"environment": "production", "app": "nginx"},
|
||||
"namespace": "foo",
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "busybox",
|
||||
"image": "busybox",
|
||||
"command": ["/bin/sh", "-c", "sleep 3600"],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
match, diff = diff_objects(pod_definition, pod_definition_updated)
|
||||
|
||||
assert match is False
|
||||
assert diff["before"]["spec"] == pod_definition["spec"]
|
||||
assert diff["after"]["spec"] == pod_definition_updated["spec"]
|
||||
|
||||
|
||||
def test_find_resource():
|
||||
mock_pod_resource = Resource(
|
||||
api_version="v1", kind="Pod", namespaced=False, preferred=True, prefix="api"
|
||||
)
|
||||
spec = {"resource.return_value": mock_pod_resource}
|
||||
client = Mock(**spec)
|
||||
svc = K8sService(client, Mock())
|
||||
resource = svc.find_resource("Pod", "v1")
|
||||
|
||||
assert isinstance(resource, Resource)
|
||||
assert resource.to_dict().items() <= mock_pod_resource.to_dict().items()
|
||||
|
||||
|
||||
def test_service_delete_existing_resource(mock_pod_resource_instance):
|
||||
spec = {"delete.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock(
|
||||
params={"delete_options": {"gracePeriodSeconds": 2}}, check_mode=False
|
||||
)
|
||||
resource = Mock()
|
||||
svc = K8sService(client, module)
|
||||
result = svc.delete(resource, pod_definition, mock_pod_resource_instance)
|
||||
|
||||
assert isinstance(result, dict)
|
||||
assert result == mock_pod_resource_instance.to_dict()
|
||||
client.delete.assert_called_with(
|
||||
resource,
|
||||
name=pod_definition["metadata"]["name"],
|
||||
namespace=pod_definition["metadata"]["namespace"],
|
||||
body={"apiVersion": "v1", "kind": "DeleteOptions", "gracePeriodSeconds": 2},
|
||||
)
|
||||
|
||||
|
||||
def test_service_delete_no_existing_resource():
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
client = Mock()
|
||||
client.delete.return_value = mock_pod_resource_instance
|
||||
svc = K8sService(client, module)
|
||||
result = svc.delete(Mock(), pod_definition)
|
||||
|
||||
assert result == {}
|
||||
client.delete.assert_not_called()
|
||||
|
||||
|
||||
def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance):
|
||||
module = Mock(params={}, check_mode=True)
|
||||
client = Mock(dry_run=False)
|
||||
client.delete.return_value = mock_pod_resource_instance
|
||||
svc = K8sService(client, module)
|
||||
result = svc.delete(Mock(), pod_definition, mock_pod_resource_instance)
|
||||
|
||||
assert result == {}
|
||||
client.delete.assert_not_called()
|
||||
|
||||
|
||||
def test_service_create_resource(mock_pod_resource_instance):
|
||||
spec = {"create.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
result = svc.create(Mock(), pod_definition)
|
||||
|
||||
assert result == mock_pod_resource_instance.to_dict()
|
||||
|
||||
|
||||
def test_service_create_resource_check_mode():
|
||||
client = Mock(dry_run=False)
|
||||
client.create.return_value = mock_pod_resource_instance
|
||||
module = Mock(params={}, check_mode=True)
|
||||
svc = K8sService(client, module)
|
||||
result = svc.create(Mock(), pod_definition)
|
||||
|
||||
assert result == pod_definition
|
||||
client.create.assert_not_called()
|
||||
|
||||
|
||||
def test_service_retrieve_existing_resource(mock_pod_resource_instance):
|
||||
spec = {"get.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
svc = K8sService(client, module)
|
||||
results = svc.retrieve(Mock(), pod_definition)
|
||||
|
||||
assert isinstance(results, ResourceInstance)
|
||||
assert results.to_dict() == pod_definition
|
||||
|
||||
|
||||
def test_service_retrieve_no_existing_resource():
|
||||
spec = {"get.side_effect": [NotFoundError(Mock())]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
svc = K8sService(client, module)
|
||||
results = svc.retrieve(Mock(), pod_definition)
|
||||
|
||||
assert results is None
|
||||
|
||||
|
||||
def test_create_project_request():
|
||||
project_definition = {
|
||||
"apiVersion": "v1",
|
||||
"kind": "ProjectRequest",
|
||||
"metadata": {"name": "test"},
|
||||
}
|
||||
spec = {"create.side_effect": [ResourceInstance(None, project_definition)]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.check_mode = False
|
||||
module.params = {"state": "present"}
|
||||
svc = K8sService(client, module)
|
||||
results = svc.create_project_request(project_definition)
|
||||
|
||||
assert isinstance(results, dict)
|
||||
assert results["changed"] is True
|
||||
assert results["result"] == project_definition
|
||||
|
||||
|
||||
def test_service_apply_existing_resource(mock_pod_resource_instance):
|
||||
spec = {"apply.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {"apply": True}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
result = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
|
||||
|
||||
assert result == mock_pod_resource_instance.to_dict()
|
||||
|
||||
|
||||
def test_service_replace_existing_resource(mock_pod_resource_instance):
|
||||
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
||||
|
||||
assert result == mock_pod_resource_instance.to_dict()
|
||||
|
||||
|
||||
def test_service_update_existing_resource(mock_pod_resource_instance):
|
||||
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
||||
|
||||
assert result == mock_pod_resource_instance.to_dict()
|
||||
|
||||
|
||||
def test_service_find(mock_pod_resource_instance):
|
||||
spec = {"get.side_effect": [mock_pod_resource_instance]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
results = svc.find("Pod", "v1", name="foo", namespace="foo")
|
||||
|
||||
assert isinstance(results, dict)
|
||||
assert results["api_found"] is True
|
||||
assert results["resources"] is not []
|
||||
assert len(results["resources"]) == 1
|
||||
assert results["resources"][0] == pod_definition
|
||||
|
||||
|
||||
def test_service_find_error():
|
||||
spec = {"get.side_effect": [NotFoundError(Mock())]}
|
||||
client = Mock(**spec)
|
||||
module = Mock()
|
||||
module.params = {}
|
||||
module.check_mode = False
|
||||
svc = K8sService(client, module)
|
||||
results = svc.find("Pod", "v1", name="foo", namespace="foo")
|
||||
|
||||
assert isinstance(results, dict)
|
||||
assert results["api_found"] is True
|
||||
assert results["resources"] == []
|
||||
122
tests/unit/module_utils/test_waiter.py
Normal file
122
tests/unit/module_utils/test_waiter.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from kubernetes.dynamic.resource import ResourceInstance
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
clock,
|
||||
custom_condition,
|
||||
deployment_ready,
|
||||
DummyWaiter,
|
||||
exists,
|
||||
get_waiter,
|
||||
pod_ready,
|
||||
resource_absent,
|
||||
Waiter,
|
||||
)
|
||||
|
||||
|
||||
def resources(filepath):
|
||||
current = Path(os.path.dirname(os.path.abspath(__file__)))
|
||||
with open(current / filepath) as fp:
|
||||
return [ResourceInstance(None, d) for d in yaml.safe_load_all(fp)]
|
||||
|
||||
|
||||
RESOURCES = resources("fixtures/definitions.yml")
|
||||
PODS = resources("fixtures/pods.yml")
|
||||
DEPLOYMENTS = resources("fixtures/deployments.yml")
|
||||
|
||||
|
||||
def test_clock_times_out():
|
||||
start = time.monotonic()
|
||||
for x in clock(5, 1):
|
||||
pass
|
||||
elapsed = int(time.monotonic() - start)
|
||||
assert x == 5
|
||||
assert 5 <= elapsed <= 6
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"resource,expected",
|
||||
zip(RESOURCES + [None, {}], [True, True, True, False, False, False]),
|
||||
)
|
||||
def test_exists_and_absent_checks_for_existence(resource, expected):
|
||||
assert exists(resource) is expected
|
||||
assert resource_absent(resource) is not expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pod,expected", zip(PODS, [True, False, True, True]))
|
||||
def test_pod_ready_checks_readiness(pod, expected):
|
||||
assert pod_ready(pod) is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pod,expected", zip(PODS, [True, False, False, False]))
|
||||
def test_custom_condition_checks_readiness(pod, expected):
|
||||
condition = {"type": "www.example.com/gate", "status": "True"}
|
||||
assert custom_condition(condition, pod) is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("deployment,expected", zip(DEPLOYMENTS, [True, False]))
|
||||
def test_deployment_ready_checks_readiness(deployment, expected):
|
||||
assert deployment_ready(deployment) is expected
|
||||
|
||||
|
||||
def test_dummywaiter_returns_resource_immediately():
|
||||
resource = {
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {"name": "foopod", "namespace": "foobar"},
|
||||
}
|
||||
result, instance, elapsed = DummyWaiter().wait(resource, 10, 100)
|
||||
assert result is True
|
||||
assert instance == resource
|
||||
assert elapsed == 0
|
||||
|
||||
|
||||
def test_waiter_waits_for_missing_resource():
|
||||
spec = {"get.side_effect": NotFoundError(Mock())}
|
||||
client = Mock(**spec)
|
||||
resource = Mock()
|
||||
result, instance, elapsed = Waiter(client, resource, exists).wait(
|
||||
timeout=3,
|
||||
sleep=1,
|
||||
name=RESOURCES[0]["metadata"].get("name"),
|
||||
namespace=RESOURCES[0]["metadata"].get("namespace"),
|
||||
)
|
||||
assert result is False
|
||||
assert instance == {}
|
||||
assert abs(elapsed - 3) <= 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize("resource,expected", zip(RESOURCES, [True, True, True, False]))
|
||||
def test_waiter_waits_for_resource_to_exist(resource, expected):
|
||||
result = resource.to_dict()
|
||||
spec = {"get.side_effect": [NotFoundError(Mock()), resource, resource, resource]}
|
||||
client = Mock(**spec)
|
||||
success, instance, elapsed = Waiter(client, Mock(), exists).wait(
|
||||
timeout=3,
|
||||
sleep=1,
|
||||
name=result["metadata"].get("name"),
|
||||
namespace=result["metadata"].get("namespace"),
|
||||
)
|
||||
assert success is expected
|
||||
assert instance == result
|
||||
assert abs(elapsed - 2) <= 1
|
||||
|
||||
|
||||
def test_get_waiter_returns_correct_waiter():
|
||||
assert get_waiter(Mock(), PODS[0]).predicate == pod_ready
|
||||
waiter = get_waiter(Mock(), PODS[0], check_mode=True)
|
||||
assert isinstance(waiter, DummyWaiter)
|
||||
assert get_waiter(Mock(), PODS[0], state="absent").predicate == resource_absent
|
||||
assert (
|
||||
get_waiter(
|
||||
Mock(), PODS[0], condition={"type": "Ready", "status": "True"}
|
||||
).predicate.func
|
||||
== custom_condition
|
||||
)
|
||||
Reference in New Issue
Block a user