mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-06 13:02:37 +00:00
refactoring for ansible_module.turbo integration (#313)
* refactoring for ansible_module.turbo integration This refactoring prepares the integration of `ansible_module.turbo` - Delay the loading of `common.py`, move the shared structure in `args_common`. - Avoid the use of one single object per module, this to increase the amount of Python structure that we can cache. - Cache the Kubernetes client. See: https://github.com/ansible-collections/community.kubernetes/pull/270 Co-authored-by: Jill Rouleau <jill.rouleau@bespokess.com>
This commit is contained in:
@@ -263,74 +263,68 @@ result:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, COMMON_ARG_SPEC, NAME_ARG_SPEC, RESOURCE_ARG_SPEC, AUTH_ARG_SPEC,
|
||||
WAIT_ARG_SPEC, DELETE_OPTS_ARG_SPEC)
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, WAIT_ARG_SPEC, NAME_ARG_SPEC, COMMON_ARG_SPEC, RESOURCE_ARG_SPEC, DELETE_OPTS_ARG_SPEC)
|
||||
|
||||
|
||||
class KubernetesModule(K8sAnsibleMixin):
|
||||
def validate_spec():
|
||||
return dict(
|
||||
fail_on_error=dict(type='bool'),
|
||||
version=dict(),
|
||||
strict=dict(type='bool', default=True)
|
||||
)
|
||||
|
||||
@property
|
||||
def validate_spec(self):
|
||||
return dict(
|
||||
fail_on_error=dict(type='bool'),
|
||||
version=dict(),
|
||||
strict=dict(type='bool', default=True)
|
||||
)
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
argument_spec = copy.deepcopy(COMMON_ARG_SPEC)
|
||||
argument_spec.update(copy.deepcopy(NAME_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(RESOURCE_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||
argument_spec['merge_type'] = dict(type='list', elements='str', choices=['json', 'merge', 'strategic-merge'])
|
||||
argument_spec['validate'] = dict(type='dict', default=None, options=self.validate_spec)
|
||||
argument_spec['append_hash'] = dict(type='bool', default=False)
|
||||
argument_spec['apply'] = dict(type='bool', default=False)
|
||||
argument_spec['template'] = dict(type='raw', default=None)
|
||||
argument_spec['delete_options'] = dict(type='dict', default=None, options=copy.deepcopy(DELETE_OPTS_ARG_SPEC))
|
||||
return argument_spec
|
||||
def argspec():
|
||||
argument_spec = copy.deepcopy(COMMON_ARG_SPEC)
|
||||
argument_spec.update(copy.deepcopy(NAME_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(RESOURCE_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
|
||||
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||
argument_spec['merge_type'] = dict(type='list', elements='str', choices=['json', 'merge', 'strategic-merge'])
|
||||
argument_spec['validate'] = dict(type='dict', default=None, options=validate_spec())
|
||||
argument_spec['append_hash'] = dict(type='bool', default=False)
|
||||
argument_spec['apply'] = dict(type='bool', default=False)
|
||||
argument_spec['template'] = dict(type='raw', default=None)
|
||||
argument_spec['delete_options'] = dict(type='dict', default=None, options=copy.deepcopy(DELETE_OPTS_ARG_SPEC))
|
||||
return argument_spec
|
||||
|
||||
def __init__(self, k8s_kind=None, *args, **kwargs):
|
||||
mutually_exclusive = [
|
||||
('resource_definition', 'src'),
|
||||
('merge_type', 'apply'),
|
||||
('template', 'resource_definition'),
|
||||
('template', 'src'),
|
||||
]
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
mutually_exclusive=mutually_exclusive,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
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.warnings = []
|
||||
|
||||
self.module = module
|
||||
self.check_mode = self.module.check_mode
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
self.fail = self.module.fail_json
|
||||
self.exit_json = self.module.exit_json
|
||||
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.namespace = k8s_ansible_mixin.params.get('namespace')
|
||||
|
||||
super(KubernetesModule, self).__init__(*args, **kwargs)
|
||||
|
||||
self.client = None
|
||||
self.warnings = []
|
||||
|
||||
self.kind = k8s_kind or self.params.get('kind')
|
||||
self.api_version = self.params.get('api_version')
|
||||
self.name = self.params.get('name')
|
||||
self.namespace = self.params.get('namespace')
|
||||
|
||||
self.check_library_version()
|
||||
self.set_resource_definitions()
|
||||
k8s_ansible_mixin.check_library_version()
|
||||
k8s_ansible_mixin.set_resource_definitions(module)
|
||||
k8s_ansible_mixin.execute_module()
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesModule().execute_module()
|
||||
mutually_exclusive = [
|
||||
('resource_definition', 'src'),
|
||||
('merge_type', 'apply'),
|
||||
('template', 'resource_definition'),
|
||||
('template', 'src'),
|
||||
]
|
||||
module = AnsibleModule(argument_spec=argspec(), mutually_exclusive=mutually_exclusive, supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -159,88 +159,60 @@ apis:
|
||||
|
||||
|
||||
import copy
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import K8sAnsibleMixin, AUTH_ARG_SPEC
|
||||
|
||||
try:
|
||||
try:
|
||||
from openshift import __version__ as version
|
||||
# >=0.10
|
||||
from openshift.dynamic.resource import ResourceList
|
||||
except ImportError:
|
||||
# <0.10
|
||||
from openshift.dynamic.client import ResourceList
|
||||
HAS_K8S_INSTANCE_HELPER = True
|
||||
k8s_import_exception = None
|
||||
except ImportError:
|
||||
HAS_K8S_INSTANCE_HELPER = False
|
||||
k8s_import_exception = traceback.format_exc()
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (AUTH_ARG_SPEC)
|
||||
|
||||
|
||||
class KubernetesInfoModule(K8sAnsibleMixin):
|
||||
|
||||
def __init__(self):
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
self.module = module
|
||||
self.params = self.module.params
|
||||
|
||||
if not HAS_K8S_INSTANCE_HELPER:
|
||||
self.module.fail_json(msg=missing_required_lib("openshift >= 0.6.2", reason="for merge_type"),
|
||||
exception=k8s_import_exception)
|
||||
|
||||
super(KubernetesInfoModule, self).__init__()
|
||||
|
||||
def execute_module(self):
|
||||
self.client = self.get_api_client()
|
||||
invalidate_cache = boolean(self.module.params.get('invalidate_cache', True), strict=False)
|
||||
if invalidate_cache:
|
||||
self.client.resources.invalidate_cache()
|
||||
results = {}
|
||||
for resource in list(self.client.resources):
|
||||
resource = resource[0]
|
||||
if isinstance(resource, ResourceList):
|
||||
continue
|
||||
results[resource.group] = {
|
||||
'api_version': resource.group_version,
|
||||
'categories': resource.categories if resource.categories else [],
|
||||
'kind': resource.kind,
|
||||
'name': resource.name,
|
||||
'namespaced': resource.namespaced,
|
||||
'preferred': resource.preferred,
|
||||
'short_names': resource.short_names if resource.short_names else [],
|
||||
'singular_name': resource.singular_name,
|
||||
}
|
||||
configuration = self.client.configuration
|
||||
connection = {
|
||||
'cert_file': configuration.cert_file,
|
||||
'host': configuration.host,
|
||||
'password': configuration.password,
|
||||
'proxy': configuration.proxy,
|
||||
'ssl_ca_cert': configuration.ssl_ca_cert,
|
||||
'username': configuration.username,
|
||||
'verify_ssl': configuration.verify_ssl,
|
||||
def execute_module(module, client):
|
||||
invalidate_cache = boolean(module.params.get('invalidate_cache', True), strict=False)
|
||||
if invalidate_cache:
|
||||
client.resources.invalidate_cache()
|
||||
results = {}
|
||||
from openshift.dynamic.resource import ResourceList
|
||||
for resource in list(client.resources):
|
||||
resource = resource[0]
|
||||
if isinstance(resource, ResourceList):
|
||||
continue
|
||||
results[resource.group] = {
|
||||
'api_version': resource.group_version,
|
||||
'categories': resource.categories if resource.categories else [],
|
||||
'kind': resource.kind,
|
||||
'name': resource.name,
|
||||
'namespaced': resource.namespaced,
|
||||
'preferred': resource.preferred,
|
||||
'short_names': resource.short_names if resource.short_names else [],
|
||||
'singular_name': resource.singular_name,
|
||||
}
|
||||
version_info = {
|
||||
'client': version,
|
||||
'server': self.client.version,
|
||||
}
|
||||
self.module.exit_json(changed=False, apis=results, connection=connection, version=version_info)
|
||||
configuration = client.configuration
|
||||
connection = {
|
||||
'cert_file': configuration.cert_file,
|
||||
'host': configuration.host,
|
||||
'password': configuration.password,
|
||||
'proxy': configuration.proxy,
|
||||
'ssl_ca_cert': configuration.ssl_ca_cert,
|
||||
'username': configuration.username,
|
||||
'verify_ssl': configuration.verify_ssl,
|
||||
}
|
||||
from openshift import __version__ as version
|
||||
version_info = {
|
||||
'client': version,
|
||||
'server': client.version,
|
||||
}
|
||||
module.exit_json(changed=False, apis=results, connection=connection, version=version_info)
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
spec['invalidate_cache'] = dict(type='bool', default=True)
|
||||
return spec
|
||||
|
||||
def argspec():
|
||||
spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
spec['invalidate_cache'] = dict(type='bool', default=True)
|
||||
return spec
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesInfoModule().execute_module()
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import get_api_client
|
||||
execute_module(module, client=get_api_client(module=module))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -118,10 +118,10 @@ except ImportError:
|
||||
# ImportError are managed by the common module already.
|
||||
pass
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC
|
||||
AUTH_ARG_SPEC
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -132,75 +132,72 @@ except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class KubernetesExecCommand(K8sAnsibleMixin):
|
||||
def argspec():
|
||||
spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
spec['namespace'] = dict(type='str', required=True)
|
||||
spec['pod'] = dict(type='str', required=True)
|
||||
spec['container'] = dict(type='str')
|
||||
spec['command'] = dict(type='str', required=True)
|
||||
return spec
|
||||
|
||||
def __init__(self):
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
self.module = module
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
super(KubernetesExecCommand, self).__init__()
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
spec['namespace'] = dict(type='str', required=True)
|
||||
spec['pod'] = dict(type='str', required=True)
|
||||
spec['container'] = dict(type='str')
|
||||
spec['command'] = dict(type='str', required=True)
|
||||
return spec
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
|
||||
def execute_module(self):
|
||||
# Load kubernetes.client.Configuration
|
||||
self.get_api_client()
|
||||
api = core_v1_api.CoreV1Api()
|
||||
# Load kubernetes.client.Configuration
|
||||
api = core_v1_api.CoreV1Api()
|
||||
|
||||
# hack because passing the container as None breaks things
|
||||
optional_kwargs = {}
|
||||
if self.params.get('container'):
|
||||
optional_kwargs['container'] = self.params['container']
|
||||
try:
|
||||
resp = stream(
|
||||
api.connect_get_namespaced_pod_exec,
|
||||
self.params["pod"],
|
||||
self.params["namespace"],
|
||||
command=shlex.split(self.params["command"]),
|
||||
stdout=True,
|
||||
stderr=True,
|
||||
stdin=False,
|
||||
tty=False,
|
||||
_preload_content=False, **optional_kwargs)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Failed to execute on pod %s"
|
||||
" due to : %s" % (self.params.get('pod'), to_native(e)))
|
||||
stdout, stderr, rc = [], [], 0
|
||||
while resp.is_open():
|
||||
resp.update(timeout=1)
|
||||
if resp.peek_stdout():
|
||||
stdout.append(resp.read_stdout())
|
||||
if resp.peek_stderr():
|
||||
stderr.append(resp.read_stderr())
|
||||
err = resp.read_channel(3)
|
||||
err = yaml.safe_load(err)
|
||||
if err['status'] == 'Success':
|
||||
rc = 0
|
||||
else:
|
||||
rc = int(err['details']['causes'][0]['message'])
|
||||
# hack because passing the container as None breaks things
|
||||
optional_kwargs = {}
|
||||
if module.params.get('container'):
|
||||
optional_kwargs['container'] = module.params['container']
|
||||
try:
|
||||
resp = stream(
|
||||
api.connect_get_namespaced_pod_exec,
|
||||
module.params["pod"],
|
||||
module.params["namespace"],
|
||||
command=shlex.split(module.params["command"]),
|
||||
stdout=True,
|
||||
stderr=True,
|
||||
stdin=False,
|
||||
tty=False,
|
||||
_preload_content=False, **optional_kwargs)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to execute on pod %s"
|
||||
" due to : %s" % (module.params.get('pod'), to_native(e)))
|
||||
stdout, stderr, rc = [], [], 0
|
||||
while resp.is_open():
|
||||
resp.update(timeout=1)
|
||||
if resp.peek_stdout():
|
||||
stdout.append(resp.read_stdout())
|
||||
if resp.peek_stderr():
|
||||
stderr.append(resp.read_stderr())
|
||||
err = resp.read_channel(3)
|
||||
err = yaml.safe_load(err)
|
||||
if err['status'] == 'Success':
|
||||
rc = 0
|
||||
else:
|
||||
rc = int(err['details']['causes'][0]['message'])
|
||||
|
||||
self.module.exit_json(
|
||||
# Some command might change environment, but ultimately failing at end
|
||||
changed=True,
|
||||
stdout="".join(stdout),
|
||||
stderr="".join(stderr),
|
||||
return_code=rc
|
||||
)
|
||||
module.exit_json(
|
||||
# Some command might change environment, but ultimately failing at end
|
||||
changed=True,
|
||||
stdout="".join(stdout),
|
||||
stderr="".join(stderr),
|
||||
return_code=rc
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesExecCommand().execute_module()
|
||||
module = AnsibleModule(
|
||||
argument_spec=argspec(),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -148,58 +148,50 @@ resources:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC, WAIT_ARG_SPEC)
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (AUTH_ARG_SPEC, WAIT_ARG_SPEC)
|
||||
|
||||
|
||||
class KubernetesInfoModule(K8sAnsibleMixin):
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
facts = k8s_ansible_mixin.kubernetes_facts(
|
||||
module.params["kind"],
|
||||
module.params["api_version"],
|
||||
name=module.params["name"],
|
||||
namespace=module.params["namespace"],
|
||||
label_selectors=module.params["label_selectors"],
|
||||
field_selectors=module.params["field_selectors"],
|
||||
wait=module.params["wait"],
|
||||
wait_sleep=module.params["wait_sleep"],
|
||||
wait_timeout=module.params["wait_timeout"],
|
||||
condition=module.params["wait_condition"],
|
||||
)
|
||||
module.exit_json(changed=False, **facts)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
|
||||
def argspec():
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(WAIT_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
kind=dict(required=True),
|
||||
api_version=dict(default='v1', aliases=['api', 'version']),
|
||||
name=dict(),
|
||||
namespace=dict(),
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
field_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
self.module = module
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
self.exit_json = self.module.exit_json
|
||||
super(KubernetesInfoModule, self).__init__()
|
||||
|
||||
def execute_module(self):
|
||||
self.client = self.get_api_client()
|
||||
|
||||
self.exit_json(changed=False,
|
||||
**self.kubernetes_facts(self.params['kind'],
|
||||
self.params['api_version'],
|
||||
name=self.params['name'],
|
||||
namespace=self.params['namespace'],
|
||||
label_selectors=self.params['label_selectors'],
|
||||
field_selectors=self.params['field_selectors'],
|
||||
wait=self.params['wait'],
|
||||
wait_sleep=self.params['wait_sleep'],
|
||||
wait_timeout=self.params['wait_timeout'],
|
||||
condition=self.params['wait_condition']))
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(WAIT_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
kind=dict(required=True),
|
||||
api_version=dict(default='v1', aliases=['api', 'version']),
|
||||
name=dict(),
|
||||
namespace=dict(),
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
field_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
)
|
||||
return args
|
||||
)
|
||||
return args
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesInfoModule().execute_module()
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -111,116 +111,101 @@ log_lines:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible.module_utils.six import PY2
|
||||
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC, NAME_ARG_SPEC)
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (AUTH_ARG_SPEC, NAME_ARG_SPEC)
|
||||
|
||||
|
||||
class KubernetesLogModule(K8sAnsibleMixin):
|
||||
|
||||
def __init__(self):
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
def argspec():
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(NAME_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
kind=dict(type='str', default='Pod'),
|
||||
container=dict(),
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
self.module = module
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
self.fail = self.module.fail_json
|
||||
self.exit_json = self.module.exit_json
|
||||
super(KubernetesLogModule, self).__init__()
|
||||
)
|
||||
return args
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(NAME_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
kind=dict(type='str', default='Pod'),
|
||||
container=dict(),
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
)
|
||||
return args
|
||||
|
||||
def execute_module(self):
|
||||
name = self.params.get('name')
|
||||
namespace = self.params.get('namespace')
|
||||
label_selector = ','.join(self.params.get('label_selectors', {}))
|
||||
if name and label_selector:
|
||||
self.fail(msg='Only one of name or label_selectors can be provided')
|
||||
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', {}))
|
||||
if name and label_selector:
|
||||
module.fail(msg='Only one of name or label_selectors can be provided')
|
||||
|
||||
self.client = self.get_api_client()
|
||||
resource = self.find_resource(self.params['kind'], self.params['api_version'], fail=True)
|
||||
v1_pods = self.find_resource('Pod', 'v1', fail=True)
|
||||
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)
|
||||
|
||||
if 'log' not in resource.subresources:
|
||||
if not name:
|
||||
self.fail(msg='name must be provided for resources that do not support the log subresource')
|
||||
instance = resource.get(name=name, namespace=namespace)
|
||||
label_selector = ','.join(self.extract_selectors(instance))
|
||||
resource = v1_pods
|
||||
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')
|
||||
instance = resource.get(name=name, namespace=namespace)
|
||||
label_selector = ','.join(extract_selectors(module, instance))
|
||||
resource = v1_pods
|
||||
|
||||
if label_selector:
|
||||
instances = v1_pods.get(namespace=namespace, label_selector=label_selector)
|
||||
if not instances.items:
|
||||
self.fail(msg='No pods in namespace {0} matched selector {1}'.format(namespace, label_selector))
|
||||
# This matches the behavior of kubectl when logging pods via a selector
|
||||
name = instances.items[0].metadata.name
|
||||
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(namespace, label_selector))
|
||||
# This matches the behavior of kubectl when logging pods via a selector
|
||||
name = instances.items[0].metadata.name
|
||||
resource = v1_pods
|
||||
|
||||
kwargs = {}
|
||||
if self.params.get('container'):
|
||||
kwargs['query_params'] = dict(container=self.params['container'])
|
||||
kwargs = {}
|
||||
if module.params.get('container'):
|
||||
kwargs['query_params'] = dict(container=module.params['container'])
|
||||
|
||||
log = serialize_log(resource.log.get(
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
serialize=False,
|
||||
**kwargs
|
||||
))
|
||||
log = serialize_log(resource.log.get(
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
serialize=False,
|
||||
**kwargs
|
||||
))
|
||||
|
||||
self.exit_json(changed=False, log=log, log_lines=log.split('\n'))
|
||||
module.exit_json(changed=False, log=log, log_lines=log.split('\n'))
|
||||
|
||||
def extract_selectors(self, 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:
|
||||
self.fail(msg='{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))
|
||||
|
||||
if not (instance.spec.selector.matchLabels or instance.spec.selector.matchExpressions):
|
||||
# A few resources (like DeploymentConfigs) just use a simple key:value style instead of supporting expressions
|
||||
for k, v in dict(instance.spec.selector).items():
|
||||
selectors.append('{0}={1}'.format(k, v))
|
||||
return selectors
|
||||
|
||||
if instance.spec.selector.matchLabels:
|
||||
for k, v in dict(instance.spec.selector.matchLabels).items():
|
||||
selectors.append('{0}={1}'.format(k, v))
|
||||
|
||||
if instance.spec.selector.matchExpressions:
|
||||
for expression in instance.spec.selector.matchExpressions:
|
||||
operator = expression.operator
|
||||
|
||||
if operator == 'Exists':
|
||||
selectors.append(expression.key)
|
||||
elif operator == 'DoesNotExist':
|
||||
selectors.append('!{0}'.format(expression.key))
|
||||
elif operator in ['In', 'NotIn']:
|
||||
selectors.append('{key} {operator} {values}'.format(
|
||||
key=expression.key,
|
||||
operator=operator.lower(),
|
||||
values='({0})'.format(', '.join(expression.values))
|
||||
))
|
||||
else:
|
||||
self.fail(msg='The k8s_log module does not support the {0} matchExpression operator'.format(operator.lower()))
|
||||
def extract_selectors(module, 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(
|
||||
'/'.join(instance.group, instance.apiVersion), instance.kind))
|
||||
|
||||
if not (instance.spec.selector.matchLabels or instance.spec.selector.matchExpressions):
|
||||
# A few resources (like DeploymentConfigs) just use a simple key:value style instead of supporting expressions
|
||||
for k, v in dict(instance.spec.selector).items():
|
||||
selectors.append('{0}={1}'.format(k, v))
|
||||
return selectors
|
||||
|
||||
if instance.spec.selector.matchLabels:
|
||||
for k, v in dict(instance.spec.selector.matchLabels).items():
|
||||
selectors.append('{0}={1}'.format(k, v))
|
||||
|
||||
if instance.spec.selector.matchExpressions:
|
||||
for expression in instance.spec.selector.matchExpressions:
|
||||
operator = expression.operator
|
||||
|
||||
if operator == 'Exists':
|
||||
selectors.append(expression.key)
|
||||
elif operator == 'DoesNotExist':
|
||||
selectors.append('!{0}'.format(expression.key))
|
||||
elif operator in ['In', 'NotIn']:
|
||||
selectors.append('{key} {operator} {values}'.format(
|
||||
key=expression.key,
|
||||
operator=operator.lower(),
|
||||
values='({0})'.format(', '.join(expression.values))
|
||||
))
|
||||
else:
|
||||
module.fail(msg='The k8s_log module does not support the {0} matchExpression operator'.format(operator.lower()))
|
||||
|
||||
return selectors
|
||||
|
||||
|
||||
def serialize_log(response):
|
||||
if PY2:
|
||||
@@ -229,7 +214,13 @@ def serialize_log(response):
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesLogModule().execute_module()
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -78,127 +78,117 @@ rollback_info:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC, NAME_ARG_SPEC)
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, NAME_ARG_SPEC)
|
||||
|
||||
|
||||
class KubernetesRollbackModule(K8sAnsibleMixin):
|
||||
def get_managed_resource(module):
|
||||
managed_resource = {}
|
||||
|
||||
def __init__(self):
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
supports_check_mode=True,
|
||||
kind = module.params['kind']
|
||||
if kind == "DaemonSet":
|
||||
managed_resource['kind'] = "ControllerRevision"
|
||||
managed_resource['api_version'] = "apps/v1"
|
||||
elif kind == "Deployment":
|
||||
managed_resource['kind'] = "ReplicaSet"
|
||||
managed_resource['api_version'] = "apps/v1"
|
||||
else:
|
||||
module.fail(msg="Cannot perform rollback on resource of kind {0}".format(kind))
|
||||
return managed_resource
|
||||
|
||||
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
results = []
|
||||
|
||||
resources = k8s_ansible_mixin.kubernetes_facts(
|
||||
module.params['kind'],
|
||||
module.params['api_version'],
|
||||
module.params['name'],
|
||||
module.params['namespace'],
|
||||
module.params['label_selectors'],
|
||||
module.params['field_selectors'])
|
||||
|
||||
for resource in resources['resources']:
|
||||
result = perform_action(module, k8s_ansible_mixin, resource)
|
||||
results.append(result)
|
||||
|
||||
module.exit_json(**{
|
||||
'changed': True,
|
||||
'rollback_info': results
|
||||
})
|
||||
|
||||
|
||||
def perform_action(module, k8s_ansible_mixin, resource):
|
||||
if module.params['kind'] == "DaemonSet":
|
||||
current_revision = resource['metadata']['generation']
|
||||
elif module.params['kind'] == "Deployment":
|
||||
current_revision = resource['metadata']['annotations']['deployment.kubernetes.io/revision']
|
||||
|
||||
managed_resource = get_managed_resource(module)
|
||||
managed_resources = k8s_ansible_mixin.kubernetes_facts(
|
||||
managed_resource['kind'],
|
||||
managed_resource['api_version'],
|
||||
'',
|
||||
module.params['namespace'],
|
||||
resource['spec']
|
||||
['selector']
|
||||
['matchLabels'],
|
||||
'')
|
||||
|
||||
prev_managed_resource = get_previous_revision(managed_resources['resources'],
|
||||
current_revision)
|
||||
|
||||
if module.params['kind'] == "Deployment":
|
||||
del prev_managed_resource['spec']['template']['metadata']['labels']['pod-template-hash']
|
||||
|
||||
resource_patch = [{
|
||||
"op": "replace",
|
||||
"path": "/spec/template",
|
||||
"value": prev_managed_resource['spec']['template']
|
||||
}, {
|
||||
"op": "replace",
|
||||
"path": "/metadata/annotations",
|
||||
"value": {
|
||||
"deployment.kubernetes.io/revision": prev_managed_resource['metadata']['annotations']['deployment.kubernetes.io/revision']
|
||||
}
|
||||
}]
|
||||
|
||||
api_target = 'deployments'
|
||||
content_type = 'application/json-patch+json'
|
||||
elif module.params['kind'] == "DaemonSet":
|
||||
resource_patch = prev_managed_resource["data"]
|
||||
|
||||
api_target = 'daemonsets'
|
||||
content_type = 'application/strategic-merge-patch+json'
|
||||
|
||||
rollback = k8s_ansible_mixin.client.request(
|
||||
"PATCH",
|
||||
"/apis/{0}/namespaces/{1}/{2}/{3}"
|
||||
.format(module.params['api_version'],
|
||||
module.params['namespace'],
|
||||
api_target,
|
||||
module.params['name']),
|
||||
body=resource_patch,
|
||||
content_type=content_type)
|
||||
|
||||
result = {'changed': True}
|
||||
result['method'] = 'patch'
|
||||
result['body'] = resource_patch
|
||||
result['resources'] = rollback.to_dict()
|
||||
return result
|
||||
|
||||
|
||||
def argspec():
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(NAME_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
field_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
self.module = module
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
self.fail = self.module.fail_json
|
||||
self.exit_json = self.module.exit_json
|
||||
super(KubernetesRollbackModule, self).__init__()
|
||||
|
||||
self.kind = self.params['kind']
|
||||
self.api_version = self.params['api_version']
|
||||
self.name = self.params['name']
|
||||
self.namespace = self.params['namespace']
|
||||
self.managed_resource = {}
|
||||
|
||||
if self.kind == "DaemonSet":
|
||||
self.managed_resource['kind'] = "ControllerRevision"
|
||||
self.managed_resource['api_version'] = "apps/v1"
|
||||
elif self.kind == "Deployment":
|
||||
self.managed_resource['kind'] = "ReplicaSet"
|
||||
self.managed_resource['api_version'] = "apps/v1"
|
||||
else:
|
||||
self.fail(msg="Cannot perform rollback on resource of kind {0}".format(self.kind))
|
||||
|
||||
def execute_module(self):
|
||||
results = []
|
||||
self.client = self.get_api_client()
|
||||
|
||||
resources = self.kubernetes_facts(self.kind,
|
||||
self.api_version,
|
||||
self.name,
|
||||
self.namespace,
|
||||
self.params['label_selectors'],
|
||||
self.params['field_selectors'])
|
||||
|
||||
for resource in resources['resources']:
|
||||
result = self.perform_action(resource)
|
||||
results.append(result)
|
||||
|
||||
self.exit_json(**{
|
||||
'changed': True,
|
||||
'rollback_info': results
|
||||
})
|
||||
|
||||
def perform_action(self, resource):
|
||||
if self.kind == "DaemonSet":
|
||||
current_revision = resource['metadata']['generation']
|
||||
elif self.kind == "Deployment":
|
||||
current_revision = resource['metadata']['annotations']['deployment.kubernetes.io/revision']
|
||||
|
||||
managed_resources = self.kubernetes_facts(self.managed_resource['kind'],
|
||||
self.managed_resource['api_version'],
|
||||
'',
|
||||
self.namespace,
|
||||
resource['spec']
|
||||
['selector']
|
||||
['matchLabels'],
|
||||
'')
|
||||
|
||||
prev_managed_resource = get_previous_revision(managed_resources['resources'],
|
||||
current_revision)
|
||||
|
||||
if self.kind == "Deployment":
|
||||
del prev_managed_resource['spec']['template']['metadata']['labels']['pod-template-hash']
|
||||
|
||||
resource_patch = [{
|
||||
"op": "replace",
|
||||
"path": "/spec/template",
|
||||
"value": prev_managed_resource['spec']['template']
|
||||
}, {
|
||||
"op": "replace",
|
||||
"path": "/metadata/annotations",
|
||||
"value": {
|
||||
"deployment.kubernetes.io/revision": prev_managed_resource['metadata']['annotations']['deployment.kubernetes.io/revision']
|
||||
}
|
||||
}]
|
||||
|
||||
api_target = 'deployments'
|
||||
content_type = 'application/json-patch+json'
|
||||
elif self.kind == "DaemonSet":
|
||||
resource_patch = prev_managed_resource["data"]
|
||||
|
||||
api_target = 'daemonsets'
|
||||
content_type = 'application/strategic-merge-patch+json'
|
||||
|
||||
rollback = self.client.request("PATCH",
|
||||
"/apis/{0}/namespaces/{1}/{2}/{3}"
|
||||
.format(self.api_version,
|
||||
self.namespace,
|
||||
api_target,
|
||||
self.name),
|
||||
body=resource_patch,
|
||||
content_type=content_type)
|
||||
|
||||
result = {'changed': True}
|
||||
result['method'] = 'patch'
|
||||
result['body'] = resource_patch
|
||||
result['resources'] = rollback.to_dict()
|
||||
return result
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
args = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
args.update(NAME_ARG_SPEC)
|
||||
args.update(
|
||||
dict(
|
||||
label_selectors=dict(type='list', elements='str', default=[]),
|
||||
field_selectors=dict(type='list', elements='str', default=[]),
|
||||
)
|
||||
)
|
||||
return args
|
||||
)
|
||||
return args
|
||||
|
||||
|
||||
def get_previous_revision(all_resources, current_revision):
|
||||
@@ -217,7 +207,12 @@ def get_previous_revision(all_resources, current_revision):
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesRollbackModule().execute_module()
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -118,11 +118,129 @@ result:
|
||||
sample: 48
|
||||
'''
|
||||
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.scale import KubernetesAnsibleScaleModule
|
||||
import copy
|
||||
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, RESOURCE_ARG_SPEC, NAME_ARG_SPEC)
|
||||
|
||||
|
||||
SCALE_ARG_SPEC = {
|
||||
'replicas': {'type': 'int', 'required': True},
|
||||
'current_replicas': {'type': 'int'},
|
||||
'resource_version': {},
|
||||
'wait': {'type': 'bool', 'default': True},
|
||||
'wait_timeout': {'type': 'int', 'default': 20},
|
||||
}
|
||||
|
||||
|
||||
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']
|
||||
current_replicas = module.params.get('current_replicas')
|
||||
replicas = module.params.get('replicas')
|
||||
resource_version = module.params.get('resource_version')
|
||||
|
||||
wait = module.params.get('wait')
|
||||
wait_time = module.params.get('wait_timeout')
|
||||
existing = None
|
||||
existing_count = None
|
||||
return_attributes = dict(changed=False, result=dict(), diff=dict())
|
||||
if wait:
|
||||
return_attributes['duration'] = 0
|
||||
|
||||
resource = k8s_ansible_mixin.find_resource(kind, api_version, fail=True)
|
||||
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import NotFoundError
|
||||
|
||||
try:
|
||||
existing = resource.get(name=name, namespace=namespace)
|
||||
return_attributes['result'] = existing.to_dict()
|
||||
except NotFoundError as exc:
|
||||
module.fail_json(msg='Failed to retrieve requested object: {0}'.format(exc),
|
||||
error=exc.value.get('status'))
|
||||
|
||||
if module.params['kind'] == 'job':
|
||||
existing_count = existing.spec.parallelism
|
||||
elif hasattr(existing.spec, 'replicas'):
|
||||
existing_count = existing.spec.replicas
|
||||
|
||||
if existing_count is None:
|
||||
module.fail_json(msg='Failed to retrieve the available count for the requested object.')
|
||||
|
||||
if resource_version and resource_version != existing.metadata.resourceVersion:
|
||||
module.exit_json(**return_attributes)
|
||||
|
||||
if current_replicas is not None and existing_count != current_replicas:
|
||||
module.exit_json(**return_attributes)
|
||||
|
||||
if existing_count != replicas:
|
||||
return_attributes['changed'] = True
|
||||
if not module.check_mode:
|
||||
if module.params['kind'] == 'job':
|
||||
existing.spec.parallelism = replicas
|
||||
return_attributes['result'] = resource.patch(existing.to_dict()).to_dict()
|
||||
else:
|
||||
return_attributes = scale(module, k8s_ansible_mixin, resource, existing, replicas, wait, wait_time)
|
||||
|
||||
module.exit_json(**return_attributes)
|
||||
|
||||
|
||||
def argspec():
|
||||
args = copy.deepcopy(SCALE_ARG_SPEC)
|
||||
args.update(RESOURCE_ARG_SPEC)
|
||||
args.update(NAME_ARG_SPEC)
|
||||
args.update(AUTH_ARG_SPEC)
|
||||
return args
|
||||
|
||||
|
||||
def scale(module, k8s_ansible_mixin, resource, existing_object, replicas, wait, wait_time):
|
||||
name = existing_object.metadata.name
|
||||
namespace = existing_object.metadata.namespace
|
||||
kind = existing_object.kind
|
||||
|
||||
if not hasattr(resource, 'scale'):
|
||||
module.fail_json(
|
||||
msg="Cannot perform scale on resource of kind {0}".format(resource.kind)
|
||||
)
|
||||
|
||||
scale_obj = {'kind': kind, 'metadata': {'name': name, 'namespace': namespace}, 'spec': {'replicas': replicas}}
|
||||
|
||||
existing = resource.get(name=name, namespace=namespace)
|
||||
|
||||
try:
|
||||
resource.scale.patch(body=scale_obj)
|
||||
except Exception as exc:
|
||||
module.fail_json(msg="Scale request failed: {0}".format(exc))
|
||||
|
||||
k8s_obj = resource.get(name=name, namespace=namespace).to_dict()
|
||||
match, diffs = k8s_ansible_mixin.diff_objects(existing.to_dict(), k8s_obj)
|
||||
result = dict()
|
||||
result['result'] = k8s_obj
|
||||
result['changed'] = not match
|
||||
result['diff'] = diffs
|
||||
|
||||
if wait:
|
||||
success, result['result'], result['duration'] = k8s_ansible_mixin.wait(resource, scale_obj, 5, wait_time)
|
||||
if not success:
|
||||
module.fail_json(msg="Resource scaling timed out", **result)
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
KubernetesAnsibleScaleModule().execute_module()
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -145,14 +145,12 @@ result:
|
||||
'''
|
||||
|
||||
import copy
|
||||
import traceback
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.common import (
|
||||
K8sAnsibleMixin, AUTH_ARG_SPEC, COMMON_ARG_SPEC, RESOURCE_ARG_SPEC)
|
||||
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.community.kubernetes.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_SPEC, COMMON_ARG_SPEC, RESOURCE_ARG_SPEC)
|
||||
|
||||
SERVICE_ARG_SPEC = {
|
||||
'apply': {
|
||||
@@ -173,100 +171,69 @@ SERVICE_ARG_SPEC = {
|
||||
}
|
||||
|
||||
|
||||
class KubernetesService(K8sAnsibleMixin):
|
||||
def __init__(self, *args, **kwargs):
|
||||
mutually_exclusive = [
|
||||
('resource_definition', 'src'),
|
||||
('merge_type', 'apply'),
|
||||
]
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.argspec,
|
||||
mutually_exclusive=mutually_exclusive,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
self.module = module
|
||||
self.check_mode = self.module.check_mode
|
||||
self.params = self.module.params
|
||||
self.fail_json = self.module.fail_json
|
||||
self.fail = self.module.fail_json
|
||||
self.exit_json = self.module.exit_json
|
||||
|
||||
super(KubernetesService, self).__init__(*args, **kwargs)
|
||||
|
||||
self.client = None
|
||||
self.warnings = []
|
||||
|
||||
self.kind = self.params.get('kind')
|
||||
self.api_version = self.params.get('api_version')
|
||||
self.name = self.params.get('name')
|
||||
self.namespace = self.params.get('namespace')
|
||||
|
||||
self.check_library_version()
|
||||
self.set_resource_definitions()
|
||||
|
||||
@staticmethod
|
||||
def merge_dicts(x, y):
|
||||
for k in set(x.keys()).union(y.keys()):
|
||||
if k in x and k in y:
|
||||
if isinstance(x[k], dict) and isinstance(y[k], dict):
|
||||
yield (k, dict(KubernetesService.merge_dicts(x[k], y[k])))
|
||||
else:
|
||||
yield (k, y[k])
|
||||
elif k in x:
|
||||
yield (k, x[k])
|
||||
def merge_dicts(x, y):
|
||||
for k in set(x.keys()).union(y.keys()):
|
||||
if k in x and k in y:
|
||||
if isinstance(x[k], dict) and isinstance(y[k], dict):
|
||||
yield (k, dict(merge_dicts(x[k], y[k])))
|
||||
else:
|
||||
yield (k, y[k])
|
||||
elif k in x:
|
||||
yield (k, x[k])
|
||||
else:
|
||||
yield (k, y[k])
|
||||
|
||||
@property
|
||||
def argspec(self):
|
||||
""" argspec property builder """
|
||||
argument_spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
argument_spec.update(COMMON_ARG_SPEC)
|
||||
argument_spec.update(RESOURCE_ARG_SPEC)
|
||||
argument_spec.update(SERVICE_ARG_SPEC)
|
||||
return argument_spec
|
||||
|
||||
def execute_module(self):
|
||||
""" Module execution """
|
||||
self.client = self.get_api_client()
|
||||
def argspec():
|
||||
""" argspec property builder """
|
||||
argument_spec = copy.deepcopy(AUTH_ARG_SPEC)
|
||||
argument_spec.update(COMMON_ARG_SPEC)
|
||||
argument_spec.update(RESOURCE_ARG_SPEC)
|
||||
argument_spec.update(SERVICE_ARG_SPEC)
|
||||
return argument_spec
|
||||
|
||||
api_version = 'v1'
|
||||
selector = self.params.get('selector')
|
||||
service_type = self.params.get('type')
|
||||
ports = self.params.get('ports')
|
||||
|
||||
definition = defaultdict(defaultdict)
|
||||
def execute_module(module, k8s_ansible_mixin):
|
||||
""" Module execution """
|
||||
k8s_ansible_mixin.set_resource_definitions(module)
|
||||
|
||||
definition['kind'] = 'Service'
|
||||
definition['apiVersion'] = api_version
|
||||
api_version = 'v1'
|
||||
selector = module.params.get('selector')
|
||||
service_type = module.params.get('type')
|
||||
ports = module.params.get('ports')
|
||||
|
||||
def_spec = definition['spec']
|
||||
def_spec['type'] = service_type
|
||||
def_spec['ports'] = ports
|
||||
def_spec['selector'] = selector
|
||||
definition = defaultdict(defaultdict)
|
||||
|
||||
def_meta = definition['metadata']
|
||||
def_meta['name'] = self.params.get('name')
|
||||
def_meta['namespace'] = self.params.get('namespace')
|
||||
definition['kind'] = 'Service'
|
||||
definition['apiVersion'] = api_version
|
||||
|
||||
# 'resource_definition:' has lower priority than module parameters
|
||||
definition = dict(self.merge_dicts(self.resource_definitions[0], definition))
|
||||
def_spec = definition['spec']
|
||||
def_spec['type'] = service_type
|
||||
def_spec['ports'] = ports
|
||||
def_spec['selector'] = selector
|
||||
|
||||
resource = self.find_resource('Service', api_version, fail=True)
|
||||
definition = self.set_defaults(resource, definition)
|
||||
result = self.perform_action(resource, definition)
|
||||
def_meta = definition['metadata']
|
||||
def_meta['name'] = module.params.get('name')
|
||||
def_meta['namespace'] = module.params.get('namespace')
|
||||
|
||||
self.exit_json(**result)
|
||||
# 'resource_definition:' has lower priority than module parameters
|
||||
definition = dict(merge_dicts(k8s_ansible_mixin.resource_definitions[0], definition))
|
||||
|
||||
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)
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
def main():
|
||||
module = KubernetesService()
|
||||
try:
|
||||
module.execute_module()
|
||||
except Exception as e:
|
||||
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||
module = AnsibleModule(argument_spec=argspec(), supports_check_mode=True)
|
||||
from ansible_collections.community.kubernetes.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user