merge with main branch

This commit is contained in:
abikouo
2021-05-17 16:58:27 +02:00
47 changed files with 1548 additions and 506 deletions

View File

@@ -24,7 +24,7 @@ options:
kubeconfig:
description:
- Path to an existing Kubernetes config file. If not provided, and no other connection
options are provided, the openshift client will attempt to load the default
options are provided, the Kubernetes client will attempt to load the default
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG environment
variable.
type: path
@@ -110,9 +110,6 @@ options:
- "The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169"
type: bool
notes:
- "The OpenShift Python client wraps the K8s Python client, providing full access to
all of the APIS and models available on both platforms. For API version details and
additional information visit https://github.com/openshift/openshift-restclient-python"
- "To avoid SSL certificate validation errors when C(validate_certs) is I(True), the full
certificate chain for the API server must be provided via C(ca_cert) or in the
kubeconfig file."

View File

@@ -6,18 +6,14 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
try:
from openshift.helper.hashes import generate_hash
HAS_GENERATE_HASH = True
except ImportError:
HAS_GENERATE_HASH = False
from ansible.errors import AnsibleFilterError
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import generate_hash
def k8s_config_resource_name(resource):
if not HAS_GENERATE_HASH:
raise AnsibleFilterError("k8s_config_resource_name requires openshift>=0.7.2")
"""
Generate resource name for the given resource of type ConfigMap, Secret
"""
try:
return resource['metadata']['name'] + '-' + generate_hash(resource)
except KeyError:
@@ -26,6 +22,9 @@ def k8s_config_resource_name(resource):
# ---- Ansible filters ----
class FilterModule(object):
"""
"""
def filters(self):
return {

View File

@@ -37,7 +37,7 @@ DOCUMENTATION = '''
kubeconfig:
description:
- Path to an existing Kubernetes config file. If not provided, and no other connection
options are provided, the OpenShift client will attempt to load the default
options are provided, the Kubernetes client will attempt to load the default
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG
environment variable.
context:
@@ -86,8 +86,8 @@ DOCUMENTATION = '''
to access.
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
'''
@@ -121,7 +121,7 @@ from ansible_collections.kubernetes.core.plugins.module_utils.common import K8sA
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
try:
from openshift.dynamic.exceptions import DynamicApiError
from kubernetes.dynamic.exceptions import DynamicApiError
except ImportError:
pass
@@ -158,7 +158,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable, K8sAnsibleM
if not HAS_K8S_MODULE_HELPER:
raise K8sInventoryException(
"This module requires the OpenShift Python client. Try `pip install openshift`. Detail: {0}".format(k8s_import_exception)
"This module requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(k8s_import_exception)
)
source_data = None

View File

@@ -30,7 +30,7 @@ DOCUMENTATION = '''
- Fabian von Feilitzsch <@fabianvf>
description:
- Uses the OpenShift Python client to fetch a specific object by name, all matching objects within a
- Uses the Kubernetes Python client to fetch a specific object by name, all matching objects within a
namespace, or all matching objects for all namespaces, as well as information about the cluster.
- Provides access the full range of K8s APIs.
- Enables authentication via config file, certificates, password or token.
@@ -85,7 +85,7 @@ DOCUMENTATION = '''
kubeconfig:
description:
- Path to an existing Kubernetes config file. If not provided, and no other connection
options are provided, the openshift client will attempt to load the default
options are provided, the Kubernetes client will attempt to load the default
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG environment
variable.
context:
@@ -124,14 +124,9 @@ DOCUMENTATION = '''
aliases: [ verify_ssl ]
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
notes:
- "The OpenShift Python client wraps the K8s Python client, providing full access to
all of the APIS and models available on both platforms. For API version details and
additional information visit https://github.com/openshift/openshift-restclient-python"
'''
EXAMPLES = """
@@ -206,7 +201,7 @@ from ansible_collections.kubernetes.core.plugins.module_utils.common import K8sA
try:
from openshift.dynamic.exceptions import NotFoundError
from kubernetes.dynamic.exceptions import NotFoundError
HAS_K8S_MODULE_HELPER = True
k8s_import_exception = None
except ImportError as e:
@@ -220,7 +215,7 @@ class KubernetesLookup(K8sAnsibleMixin):
if not HAS_K8S_MODULE_HELPER:
raise Exception(
"Requires the OpenShift Python client. Try `pip install openshift`. Detail: {0}".format(k8s_import_exception)
"Requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(k8s_import_exception)
)
self.kind = None

View File

@@ -1,55 +0,0 @@
# Copyright [2017] [Red Hat, Inc.]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
from ansible.module_utils.six import PY3
def get_user():
if hasattr(os, 'getlogin'):
try:
user = os.getlogin()
if user:
return str(user)
except OSError:
pass
if hasattr(os, 'getuid'):
try:
user = os.getuid()
if user:
return str(user)
except OSError:
pass
user = os.environ.get("USERNAME")
if user:
return str(user)
return None
def get_default_cache_id(client):
user = get_user()
if user:
cache_id = "{0}-{1}".format(client.configuration.host, user)
else:
cache_id = client.configuration.host
if PY3:
return cache_id.encode('utf-8')
return cache_id

View File

@@ -0,0 +1,154 @@
# Copyright [2017] [Red Hat, Inc.]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
from collections import defaultdict
import hashlib
import tempfile
import kubernetes.dynamic
import kubernetes.dynamic.discovery
from kubernetes import __version__
from kubernetes.dynamic.exceptions import ServiceUnavailableError
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import ResourceList
class Discoverer(kubernetes.dynamic.discovery.Discoverer):
def __init__(self, client, cache_file):
self.client = client
default_cache_file_name = 'k8srcp-{0}.json'.format(hashlib.sha256(self.__get_default_cache_id()).hexdigest())
self.__cache_file = cache_file or os.path.join(tempfile.gettempdir(), default_cache_file_name)
self.__init_cache()
def __get_default_cache_id(self):
user = self.__get_user()
if user:
cache_id = "{0}-{1}".format(self.client.configuration.host, user)
else:
cache_id = self.client.configuration.host
return cache_id.encode('utf-8')
def __get_user(self):
# This is intended to provide a portable method for getting a username.
# It could, and maybe should, be replaced by getpass.getuser() but, due
# to a lack of portability testing the original code is being left in
# place.
if hasattr(os, 'getlogin'):
try:
user = os.getlogin()
if user:
return str(user)
except OSError:
pass
if hasattr(os, 'getuid'):
try:
user = os.getuid()
if user:
return str(user)
except OSError:
pass
user = os.environ.get("USERNAME")
if user:
return str(user)
return None
def __init_cache(self, refresh=False):
if refresh or not os.path.exists(self.__cache_file):
self._cache = {'library_version': __version__}
refresh = True
else:
try:
with open(self.__cache_file, 'r') as f:
self._cache = json.load(f, cls=CacheDecoder(self.client))
if self._cache.get('library_version') != __version__:
# Version mismatch, need to refresh cache
self.invalidate_cache()
except Exception:
self.invalidate_cache()
self._load_server_info()
self.discover()
if refresh:
self._write_cache()
def get_resources_for_api_version(self, prefix, group, version, preferred):
""" returns a dictionary of resources associated with provided (prefix, group, version)"""
resources = defaultdict(list)
subresources = defaultdict(dict)
path = '/'.join(filter(None, [prefix, group, version]))
try:
resources_response = self.client.request('GET', path).resources or []
except ServiceUnavailableError:
resources_response = []
resources_raw = list(filter(lambda resource: '/' not in resource['name'], resources_response))
subresources_raw = list(filter(lambda resource: '/' in resource['name'], resources_response))
for subresource in subresources_raw:
resource, name = subresource['name'].split('/')
subresources[resource][name] = subresource
for resource in resources_raw:
# Prevent duplicate keys
for key in ('prefix', 'group', 'api_version', 'client', 'preferred'):
resource.pop(key, None)
resourceobj = kubernetes.dynamic.Resource(
prefix=prefix,
group=group,
api_version=version,
client=self.client,
preferred=preferred,
subresources=subresources.get(resource['name']),
**resource
)
resources[resource['kind']].append(resourceobj)
resource_lookup = {
'prefix': prefix,
'group': group,
'api_version': version,
'kind': resourceobj.kind,
'name': resourceobj.name
}
resource_list = ResourceList(self.client, group=group, api_version=version, base_kind=resource['kind'], base_resource_lookup=resource_lookup)
resources[resource_list.kind].append(resource_list)
return resources
class LazyDiscoverer(Discoverer, kubernetes.dynamic.LazyDiscoverer):
def __init__(self, client, cache_file):
Discoverer.__init__(self, client, cache_file)
self.__update_cache = False
class CacheDecoder(json.JSONDecoder):
def __init__(self, client, *args, **kwargs):
self.client = client
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, obj):
if '_type' not in obj:
return obj
_type = obj.pop('_type')
if _type == 'Resource':
return kubernetes.dynamic.Resource(client=self.client, **obj)
elif _type == 'ResourceList':
return ResourceList(self.client, **obj)
elif _type == 'ResourceGroup':
return kubernetes.dynamic.discovery.ResourceGroup(obj['preferred'], resources=self.object_hook(obj['resources']))
return obj

View File

@@ -0,0 +1,49 @@
# Copyright [2017] [Red Hat, Inc.]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import kubernetes.dynamic
class ResourceList(kubernetes.dynamic.resource.ResourceList):
def __init__(self, client, group='', api_version='v1', base_kind='', kind=None, base_resource_lookup=None):
self.client = client
self.group = group
self.api_version = api_version
self.kind = kind or '{0}List'.format(base_kind)
self.base_kind = base_kind
self.base_resource_lookup = base_resource_lookup
self.__base_resource = None
def base_resource(self):
if self.__base_resource:
return self.__base_resource
elif self.base_resource_lookup:
self.__base_resource = self.client.resources.get(**self.base_resource_lookup)
return self.__base_resource
return None
def to_dict(self):
return {
'_type': 'ResourceList',
'group': self.group,
'api_version': self.api_version,
'kind': self.kind,
'base_kind': self.base_kind,
'base_resource_lookup': self.base_resource_lookup
}

View File

@@ -23,14 +23,12 @@ import time
import os
import traceback
import sys
import tempfile
import hashlib
from datetime import datetime
from distutils.version import LooseVersion
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.hashes import generate_hash
from ansible_collections.kubernetes.core.plugins.module_utils.cache import get_default_cache_id
from ansible.module_utils.basic import missing_required_lib
from ansible.module_utils.six import iteritems, string_types
@@ -42,10 +40,10 @@ from ansible.errors import AnsibleError
K8S_IMP_ERR = None
try:
import kubernetes
import openshift
from kubernetes.dynamic.exceptions import (
NotFoundError, ResourceNotFoundError, ResourceNotUniqueError, DynamicApiError,
ConflictError, ForbiddenError, MethodNotAllowedError, BadRequestError
ConflictError, ForbiddenError, MethodNotAllowedError, BadRequestError,
KubernetesValidateMissing
)
HAS_K8S_MODULE_HELPER = True
k8s_import_exception = None
@@ -57,6 +55,7 @@ except ImportError as e:
IMP_K8S_CLIENT = None
try:
from ansible_collections.kubernetes.core.plugins.module_utils.k8sdynamicclient import K8SDynamicClient
from ansible_collections.kubernetes.core.plugins.module_utils.client.discovery import LazyDiscoverer
IMP_K8S_CLIENT = True
except ImportError as e:
IMP_K8S_CLIENT = False
@@ -71,14 +70,6 @@ except ImportError:
YAML_IMP_ERR = traceback.format_exc()
HAS_YAML = False
K8S_CONFIG_HASH_IMP_ERR = None
try:
from kubernetes.dynamic.exceptions import KubernetesValidateMissing
HAS_K8S_CONFIG_HASH = True
except ImportError:
K8S_CONFIG_HASH_IMP_ERR = traceback.format_exc()
HAS_K8S_CONFIG_HASH = False
HAS_K8S_APPLY = None
try:
from ansible_collections.kubernetes.core.plugins.module_utils.apply import apply_object
@@ -114,6 +105,17 @@ except ImportError as e:
HAS_JSONPATH_RW = False
jsonpath_import_exception = e
JSON_PATCH_IMP_ERR = None
try:
import jsonpatch
HAS_JSON_PATCH = True
jsonpatch_import_exception = None
except ImportError as e:
HAS_JSON_PATCH = False
jsonpatch_import_exception = e
JSON_PATCH_IMP_ERR = traceback.format_exc()
def configuration_digest(configuration):
m = hashlib.sha256()
for k in AUTH_ARG_MAP:
@@ -211,15 +213,8 @@ def get_api_client(module=None, **kwargs):
client = get_api_client._pool[digest]
return client
def generate_cache_file(kubeclient):
cache_file_name = 'k8srcp-{0}.json'.format(hashlib.sha256(get_default_cache_id(kubeclient)).hexdigest())
return os.path.join(tempfile.gettempdir(), cache_file_name)
kubeclient = kubernetes.client.ApiClient(configuration)
cache_file = generate_cache_file(kubeclient)
try:
client = K8SDynamicClient(kubeclient, cache_file)
client = K8SDynamicClient(kubernetes.client.ApiClient(configuration), discoverer=LazyDiscoverer)
except Exception as err:
_raise_or_fail(err, 'Failed to get client due to %s')
@@ -234,9 +229,9 @@ class K8sAnsibleMixin(object):
def __init__(self, module, *args, **kwargs):
if not HAS_K8S_MODULE_HELPER:
module.fail_json(msg=missing_required_lib('openshift'), exception=K8S_IMP_ERR,
module.fail_json(msg=missing_required_lib('kubernetes'), exception=K8S_IMP_ERR,
error=to_native(k8s_import_exception))
self.openshift_version = openshift.__version__
self.kubernetes_version = kubernetes.__version__
if not HAS_YAML:
module.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
@@ -514,21 +509,8 @@ class K8sAnsibleMixin(object):
self.resource_definitions = [implicit_definition]
def check_library_version(self):
validate = self.params.get('validate')
if validate and LooseVersion(self.openshift_version) < LooseVersion("0.8.0"):
self.fail_json(msg="openshift >= 0.8.0 is required for validate")
self.append_hash = self.params.get('append_hash')
if self.append_hash and not HAS_K8S_CONFIG_HASH:
self.fail_json(msg=missing_required_lib("openshift >= 0.7.2", reason="for append_hash"),
exception=K8S_CONFIG_HASH_IMP_ERR)
if self.params['merge_type'] and LooseVersion(self.openshift_version) < LooseVersion("0.6.2"):
self.fail_json(msg=missing_required_lib("openshift >= 0.6.2", reason="for merge_type"))
self.apply = self.params.get('apply', False)
if self.apply and not HAS_K8S_APPLY:
self.fail_json(msg=missing_required_lib("openshift >= 0.9.2", reason="for apply"))
wait = self.params.get('wait', False)
if wait and not HAS_K8S_INSTANCE_HELPER:
self.fail_json(msg=missing_required_lib("openshift >= 0.4.0", reason="for wait"))
if LooseVersion(self.kubernetes_version) < LooseVersion("12.0.0"):
self.fail_json(msg="kubernetes >= 12.0.0 is required")
def flatten_list_kind(self, list_resource, definitions):
flattened = []
@@ -609,6 +591,8 @@ class K8sAnsibleMixin(object):
return definition
def perform_action(self, resource, definition):
append_hash = self.params.get('append_hash', False)
apply = self.params.get('apply', False)
delete_options = self.params.get('delete_options')
result = {'changed': False, 'result': {}}
state = self.params.get('state', None)
@@ -633,7 +617,7 @@ class K8sAnsibleMixin(object):
try:
# ignore append_hash for resources other than ConfigMap and Secret
if self.append_hash and definition['kind'] in ['ConfigMap', 'Secret']:
if append_hash and definition['kind'] in ['ConfigMap', 'Secret']:
name = '%s-%s' % (name, generate_hash(definition))
definition['metadata']['name'] = name
params = dict(name=name)
@@ -710,7 +694,7 @@ class K8sAnsibleMixin(object):
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
return result
else:
if self.apply:
if apply:
if self.check_mode:
ignored, patch = apply_object(resource, _encode_stringdata(definition))
if existing:
@@ -806,7 +790,7 @@ class K8sAnsibleMixin(object):
k8s_obj = _encode_stringdata(definition)
else:
try:
k8s_obj = resource.replace(definition, name=name, namespace=namespace, append_hash=self.append_hash).to_dict()
k8s_obj = resource.replace(definition, name=name, namespace=namespace, append_hash=append_hash).to_dict()
except DynamicApiError as exc:
msg = "Failed to replace object: {0}".format(exc.body)
if self.warnings:
@@ -839,15 +823,11 @@ class K8sAnsibleMixin(object):
if self.check_mode:
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
else:
if LooseVersion(self.openshift_version) < LooseVersion("0.6.2"):
for merge_type in self.params['merge_type'] or ['strategic-merge', 'merge']:
k8s_obj, error = self.patch_resource(resource, definition, existing, name,
namespace)
else:
for merge_type in self.params['merge_type'] or ['strategic-merge', 'merge']:
k8s_obj, error = self.patch_resource(resource, definition, existing, name,
namespace, merge_type=merge_type)
if not error:
break
namespace, merge_type=merge_type)
if not error:
break
if error:
if continue_on_error:
result['error'] = error
@@ -874,12 +854,42 @@ class K8sAnsibleMixin(object):
self.fail_json(msg=msg, **result)
return result
def json_patch(self, existing, definition, merge_type):
if merge_type == "json":
if not HAS_JSON_PATCH:
error = {
"msg": missing_required_lib('jsonpatch'),
"exception": JSON_PATCH_IMP_ERR,
"error": to_native(jsonpatch_import_exception)
}
return None, error
try:
patch = jsonpatch.JsonPatch([definition])
result_patch = patch.apply(existing.to_dict())
return result_patch, None
except jsonpatch.InvalidJsonPatch as e:
error = {
"msg": "invalid json patch",
"error": to_native(e)
}
return None, error
except jsonpatch.JsonPatchConflict as e:
error = {
"msg": "patch could not be applied due to conflict situation",
"error": to_native(e)
}
return None, error
return definition, None
def patch_resource(self, resource, definition, existing, name, namespace, merge_type=None):
try:
params = dict(name=name, namespace=namespace)
if merge_type:
params['content_type'] = 'application/{0}-patch+json'.format(merge_type)
k8s_obj = resource.patch(definition, **params).to_dict()
patch_data, error = self.json_patch(existing, definition, merge_type)
if error is not None:
return None, error
k8s_obj = resource.patch(patch_data, **params).to_dict()
match, diffs = self.diff_objects(existing.to_dict(), k8s_obj)
error = {}
return k8s_obj, {}

View File

@@ -20,13 +20,6 @@ requirements:
description:
- Manages Helm plugins.
options:
# TODO: (akasurde) Remove this in version 2.0
release_namespace:
description:
- Kubernetes namespace where the helm plugin should be installed.
type: str
aliases: [ namespace ]
#Helm options
state:
description:
@@ -108,7 +101,6 @@ def main():
module = AnsibleModule(
argument_spec=dict(
binary_path=dict(type='path'),
release_namespace=dict(type='str', aliases=['namespace']),
state=dict(type='str', default='present', choices=['present', 'absent']),
plugin_path=dict(type='str',),
plugin_name=dict(type='str',),

View File

@@ -20,13 +20,6 @@ requirements:
description:
- Gather information about Helm plugins installed in namespace.
options:
# TODO: (akasurde) Remove this in version 2.0
release_namespace:
description:
- Kubernetes namespace where the helm plugins are installed.
type: str
aliases: [ namespace ]
#Helm options
plugin_name:
description:
@@ -88,7 +81,6 @@ def main():
module = AnsibleModule(
argument_spec=dict(
binary_path=dict(type='path'),
release_namespace=dict(type='str', aliases=['namespace']),
plugin_name=dict(type='str',),
# Helm options
context=dict(type='str', aliases=['kube_context'], fallback=(env_fallback, ['K8S_AUTH_CONTEXT'])),

View File

@@ -21,7 +21,7 @@ author:
- "Fabian von Feilitzsch (@fabianvf)"
description:
- Use the OpenShift Python client to perform CRUD operations on K8s objects.
- Use the Kubernetes Python client to perform CRUD operations on K8s objects.
- Pass the object definition from a source file or inline. See examples for reading
files and using Jinja templates or vault-encrypted files.
- Access to the full range of K8s APIs.
@@ -37,13 +37,6 @@ extends_documentation_fragment:
- kubernetes.core.k8s_wait_options
- kubernetes.core.k8s_delete_options
notes:
- If your OpenShift Python library is not 0.9.0 or newer and you are trying to
remove an item from an associative array/dictionary, for example a label or
an annotation, you will need to explicitly set the value of the item to be
removed to `null`. Simply deleting the entry in the dictionary will not
remove it from openshift or kubernetes.
options:
merge_type:
description:
@@ -52,11 +45,9 @@ options:
- For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may
want to use C(merge) if you see "strategic merge patch format is not supported"
- See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)
- Requires openshift >= 0.6.2
- If more than one merge_type is given, the merge_types will be tried in order
- If openshift >= 0.6.2, this defaults to C(['strategic-merge', 'merge']), which is ideal for using the same parameters
on resource kinds that combine Custom Resources and built-in resources. For openshift < 0.6.2, the default
is simply C(strategic-merge).
- If more than one C(merge_type) is given, the merge_types will be tried in order. This defaults to
C(['strategic-merge', 'merge']), which is ideal for using the same parameters on resource kinds that
combine Custom Resources and built-in resources.
- mutually exclusive with C(apply)
choices:
- json
@@ -67,7 +58,7 @@ options:
validate:
description:
- how (if at all) to validate the resource definition against the kubernetes schema.
Requires the kubernetes-validate python module and openshift >= 0.8.0
Requires the kubernetes-validate python module.
suboptions:
fail_on_error:
description: whether to fail on validation errors.
@@ -88,7 +79,6 @@ options:
- The full definition of an object is needed to generate the hash - this means that deleting an object created with append_hash
will only work if the same object is passed with state=absent (alternatively, just use state=absent with the name including
the generated hash and append_hash=no)
- Requires openshift >= 0.7.2
default: False
type: bool
apply:
@@ -96,7 +86,6 @@ options:
- C(apply) compares the desired resource definition with the previously supplied resource definition,
ignoring properties that are automatically generated
- C(apply) works better with Services than 'force=yes'
- Requires openshift >= 0.9.2
- mutually exclusive with C(merge_type)
default: False
type: bool
@@ -133,10 +122,10 @@ options:
version_added: 2.0.0
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
- "jsonpath-rw"
- "jsonpatch"
'''
EXAMPLES = r'''

View File

@@ -18,7 +18,7 @@ author:
- Abhijeet Kasurde (@Akasurde)
description:
- Use the OpenShift Python client to perform read operations on K8s objects.
- Use the Kubernetes Python client to perform read operations on K8s objects.
- Authenticate using either a config file, certificates, password or token.
- Supports check mode.
@@ -33,8 +33,8 @@ extends_documentation_fragment:
- kubernetes.core.k8s_auth_options
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
'''
@@ -140,19 +140,29 @@ apis:
import copy
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import AnsibleModule
from ansible.module_utils.parsing.convert_bool import boolean
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (AUTH_ARG_SPEC)
import traceback
from collections import defaultdict
HAS_K8S = False
try:
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import ResourceList
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.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:
client.resources.invalidate_cache()
results = defaultdict(dict)
from openshift.dynamic.resource import ResourceList
for resource in list(client.resources):
resource = resource[0]
if isinstance(resource, ResourceList):
@@ -176,7 +186,7 @@ def execute_module(module, client):
'username': configuration.username,
'verify_ssl': configuration.verify_ssl,
}
from openshift import __version__ as version
from kubernetes import __version__ as version
version_info = {
'client': version,
'server': client.version,
@@ -192,6 +202,9 @@ 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 get_api_client
execute_module(module, client=get_api_client(module=module))

View File

@@ -26,8 +26,8 @@ extends_documentation_fragment:
- kubernetes.core.k8s_auth_options
requirements:
- "python >= 2.7"
- "openshift == 0.4.3"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
notes:

View File

@@ -18,7 +18,7 @@ author:
- "Will Thames (@willthames)"
description:
- Use the OpenShift Python client to perform read operations on K8s objects.
- Use the Kubernetes Python client to perform read operations on K8s objects.
- Access to the full range of K8s APIs.
- Authenticate using either a config file, certificates, password or token.
- Supports check mode.
@@ -49,8 +49,8 @@ extends_documentation_fragment:
- kubernetes.core.k8s_wait_options
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
- "jsonpath-rw"
'''

View File

@@ -20,7 +20,7 @@ author:
- "Fabian von Feilitzsch (@fabianvf)"
description:
- Use the OpenShift Python client to perform read operations on K8s log endpoints.
- Use the Kubernetes Python client to perform read operations on K8s log endpoints.
- Authenticate using either a config file, certificates, password or token.
- Supports check mode.
- Analogous to `kubectl logs` or `oc logs`
@@ -56,8 +56,8 @@ options:
type: str
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
'''

View File

@@ -15,7 +15,7 @@ version_added: "1.0.0"
author:
- "Julien Huon (@julienhuon)"
description:
- Use the OpenShift Python client to perform the Rollback.
- Use the Kubernetes Python client to perform the Rollback.
- Authenticate using either a config file, certificates, password or token.
- Similar to the C(kubectl rollout undo) command.
options:
@@ -31,8 +31,8 @@ extends_documentation_fragment:
- kubernetes.core.k8s_auth_options
- kubernetes.core.k8s_name_options
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
- "jsonpath-rw"
'''

View File

@@ -31,8 +31,8 @@ extends_documentation_fragment:
- kubernetes.core.k8s_scale_options
requirements:
- "python >= 2.7"
- "openshift >= 0.6"
- "python >= 3.6"
- "kubernetes >= 12.0.0"
- "PyYAML >= 3.11"
'''

View File

@@ -18,7 +18,7 @@ short_description: Manage Services on Kubernetes
author: KubeVirt Team (@kubevirt)
description:
- Use Openshift Python SDK to manage Services on Kubernetes
- Use Kubernetes Python SDK to manage Services on Kubernetes
extends_documentation_fragment:
- kubernetes.core.k8s_auth_options
@@ -33,11 +33,9 @@ options:
- For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may
want to use C(merge) if you see "strategic merge patch format is not supported"
- See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)
- Requires openshift >= 0.6.2
- If more than one merge_type is given, the merge_types will be tried in order
- If openshift >= 0.6.2, this defaults to C(['strategic-merge', 'merge']), which is ideal for using the same parameters
on resource kinds that combine Custom Resources and built-in resources. For openshift < 0.6.2, the default
is simply C(strategic-merge).
- If more than one C(merge_type) is given, the merge_types will be tried in order
- This defaults to C(['strategic-merge', 'merge']), which is ideal for using the same parameters
on resource kinds that combine Custom Resources and built-in resources.
choices:
- json
- merge
@@ -85,8 +83,8 @@ options:
type: bool
requirements:
- python >= 2.7
- openshift >= 0.6.2
- python >= 3.6
- kubernetes >= 12.0.0
'''
EXAMPLES = r'''