diff --git a/openshift/ansiblegen/cli.py b/openshift/ansiblegen/cli.py index 297664b4..9dec06b3 100644 --- a/openshift/ansiblegen/cli.py +++ b/openshift/ansiblegen/cli.py @@ -31,7 +31,7 @@ 'openshift': { 'handlers': ['console'], 'level': 'INFO', - 'propagate': False + 'propagate': True }, }, 'root': { diff --git a/openshift/ansiblegen/docstrings.py b/openshift/ansiblegen/docstrings.py index d3bdb9ff..fb4201fa 100644 --- a/openshift/ansiblegen/docstrings.py +++ b/openshift/ansiblegen/docstrings.py @@ -18,6 +18,7 @@ logger = logging.getLogger(__name__) + # Once the modules land in Ansible core, this should not change ANSIBLE_VERSION_ADDED = "2.3.0" @@ -92,7 +93,7 @@ def add_option(pname, pdict, descr=None): if pdict.get('type') and pdict.get('type') != 'str': doc_string['options'][pname]['type'] = pdict['type'] - for param_name in sorted(self.helper.argspec.keys()): + for param_name in sorted([x for x, _ in self.helper.argspec.items()]): param_dict = self.helper.argspec[param_name] if param_name.endswith('params'): descr = [self.__params_descr(param_name)] diff --git a/openshift/ansiblegen/examples/v1_route.yml b/openshift/ansiblegen/examples/v1_route.yml index 6a2cafd9..56a7a82f 100644 --- a/openshift/ansiblegen/examples/v1_route.yml +++ b/openshift/ansiblegen/examples/v1_route.yml @@ -56,8 +56,7 @@ -----BEGIN CERTIFICATE----- ca_certificate_contents -----END CERTIFICATE----- - tls_destination_ca_certificate: - name: Create route + name: Replace route - remove: name: myroute diff --git a/openshift/helper/__init__.py b/openshift/helper/__init__.py index 95da7abd..71853d40 100644 --- a/openshift/helper/__init__.py +++ b/openshift/helper/__init__.py @@ -12,6 +12,8 @@ from logging import config as logging_config +from dictdiffer import diff + from kubernetes import config, watch from kubernetes.client.rest import ApiException from kubernetes.config.config_exception import ConfigException @@ -114,25 +116,25 @@ def enable_debug(reset_logfile=True): def get_object(self, name, namespace=None): k8s_obj = None + method_name = 'list' if self.kind.endswith('list') else 'read' try: - get_method = self.lookup_method('read', namespace) - if namespace is None: + get_method = self.lookup_method(method_name, namespace) + if name and namespace is None: k8s_obj = get_method(name) + elif namespace and not name: + k8s_obj = get_method(namespace) else: k8s_obj = get_method(name, namespace) - except ApiException as ex: - if ex.status != 404: - if self.base_model_name == 'Project'and ex.status == 403: + except ApiException as exc: + if exc.status != 404: + if self.base_model_name == 'Project'and exc.status == 403: pass else: - if ex.body: - msg = json.loads(ex.body).get('message', ex.reason) - else: - msg = str(ex) - raise OpenShiftException(msg, status=ex.status) + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body + raise OpenShiftException(msg, status=exc.status) return k8s_obj - def patch_object(self, name, namespace, k8s_obj, wait=False, timeout=60): + def patch_object(self, name, namespace, k8s_obj): empty_status = self.properties['status']['class']() k8s_obj.status = empty_status k8s_obj.metadata.resource_version = None @@ -142,11 +144,11 @@ def patch_object(self, name, namespace, k8s_obj, wait=False, timeout=60): try: patch_method = self.lookup_method('patch', namespace) if namespace: - return_obj = patch_method(name, namespace, k8s_obj) + patch_method(name, namespace, k8s_obj) else: - return_obj = patch_method(name, k8s_obj) + patch_method(name, k8s_obj) except ApiException as exc: - msg = json.loads(exc.body).get('message', exc.reason) + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body raise OpenShiftException(msg, status=exc.status) #return_obj = self.__read_stream(w, stream, 'patch', name, namespace) return_obj = self.__wait_for_response(name, namespace, 'patch') @@ -157,24 +159,41 @@ def create_project(self, metadata, display_name=None, description=None): try: proj_req = client.V1ProjectRequest(metadata=metadata, display_name=display_name, description=description) client.OapiApi().create_project_request(proj_req) - except ApiException as ex: - msg = json.loads(ex.body).get('message', ex.reason) + except ApiException as exc: + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body raise OpenShiftException(msg, status=ex.status) return_obj = self.__wait_for_response(metadata.name, None, 'create') return return_obj - def create_object(self, namespace, k8s_obj): + def create_object(self, namespace, k8s_obj=None, body=None): + """ + Send a POST request to the API. Pass either k8s_obj or body. + :param namespace: namespace value or None + :param k8s_obj: optional k8s object model + :param body: optional JSON dict + :return: new object returned from the API + """ #w, stream = self.__create_stream(namespace) + if k8s_obj: + name = k8s_obj.metadata.name + elif body: + name = body.get('metadata', {}).get('name', None) try: create_method = self.lookup_method('create', namespace) - if namespace is None: - create_method(k8s_obj) + if namespace: + if k8s_obj: + create_method(namespace, k8s_obj) + else: + create_method(namespace, body=body) else: - create_method(namespace, k8s_obj) + if k8s_obj: + create_method(k8s_obj) + else: + create_method(body=body) except ApiException as exc: - msg = json.loads(exc.body).get('message', exc.reason) + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body raise OpenShiftException(msg, status=exc.status) #return_obj = self.__read_stream(w, stream, 'create', k8s_obj.metadata.name, namespace) @@ -182,7 +201,7 @@ def create_object(self, namespace, k8s_obj): if isinstance(k8s_obj, client.models.V1Namespace): time.sleep(1) - return_obj = self.__wait_for_response(k8s_obj.metadata.name, namespace, 'create') + return_obj = self.__wait_for_response(name, namespace, 'create') return return_obj def delete_object(self, name, namespace): @@ -204,38 +223,60 @@ def delete_object(self, name, namespace): else: delete_method(name, namespace) except ApiException as exc: - msg = json.loads(exc.body).get('message', exc.reason) + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body raise OpenShiftException(msg, status=exc.status) #self.__read_stream(w, stream, 'delete', name, namespace) self.__wait_for_response(name, namespace, 'delete') - def replace_object(self, name, namespace, k8s_obj): - empty_status = self.properties['status']['class']() - k8s_obj.status = empty_status - self.__remove_creation_timestamps(k8s_obj) + def replace_object(self, name, namespace, k8s_obj=None, body=None): + """ Replace an existing object. Pass in a model object or request dict(). + Will first lookup the existing object to get the resource version and + update the request. + """ + existing_obj = self.get_object(name, namespace) + if not existing_obj: + msg = "Error: Replacing object. Unable to find {}".format(name) + msg += " in namespace {}".format(namespace) if namespace else "" + raise OpenShiftException(msg) + if k8s_obj: + k8s_obj.status = self.properties['status']['class']() + self.__remove_creation_timestamps(k8s_obj) + k8s_obj.metadata.resource_version = existing_obj.metadata.resource_version + elif body: + body['metadata']['resourceVersion'] = existing_obj.metadata.resource_version #w, stream = self.__create_stream(namespace) try: replace_method = self.lookup_method('replace', namespace) - if namespace is None: - return_obj = replace_method(name, k8s_obj) + if k8s_obj: + if namespace is None: + replace_method(name, k8s_obj) + else: + replace_method(name, namespace, k8s_obj) else: - return_obj = replace_method(name, namespace, k8s_obj) + if namespace is None: + replace_method(name, body=body) + else: + replace_method(name, namespace, body=body) except ApiException as exc: - msg = json.loads(exc.body).get('message', exc.reason) + msg = json.loads(exc.body).get('message', exc.reason) if exc.body.startswith('{') else exc.body raise OpenShiftException(msg, status=exc.status) - #retur_obj = self.__read_stream(w, stream, 'replace', name, namespace) + #return_obj = self.__read_stream(w, stream, 'replace', name, namespace) return_obj = self.__wait_for_response(name, namespace, 'replace') return return_obj def objects_match(self, obj_a, obj_b): - """ Test the equality of two objects. """ + """ Test the equality of two objects. Returns bool, diff object. Use list(diff object) to + log or iterate over differences """ if obj_a is None and obj_b is None: return True if not obj_a or not obj_b: return False if type(obj_a).__name__ != type(obj_b).__name__: return False - return obj_a == obj_b + dict_a = obj_a.to_dict() + dict_b = obj_b.to_dict() + diff_result = diff(dict_a, dict_b) + return obj_a == obj_b, diff_result @classmethod def properties_from_model_obj(cls, model_obj): @@ -285,7 +326,7 @@ def lookup_method(self, operation, namespace=None): method_name = operation method_name += '_namespaced_' if namespace else '_' - method_name += self.kind + method_name += self.kind.replace('_list', '') if self.kind.endswith('_list') else self.kind apis = [x for x in dir(client.apis) if VERSION_RX.search(x)] apis.append('OapiApi') diff --git a/openshift/helper/ansible.py b/openshift/helper/ansible.py index a9e2e8ab..01056add 100644 --- a/openshift/helper/ansible.py +++ b/openshift/helper/ansible.py @@ -123,28 +123,31 @@ def argspec(self): argument_spec.update(self.__transform_properties(self.properties)) - if not self.has_delete_method: + if not self.has_method('delete'): # if no delete method, then we likely don't need a state attribute argument_spec.pop('state') self._argspec_cache = argument_spec - logger.debug(self.__log_argspec()) + self.log_argspec() return self._argspec_cache - @property - def has_delete_method(self): - """ Determine if the object has a delete method """ - delete_method = None + def has_method(self, method_action): + """ + Determine if the object has a particular method. + + :param method_action: string. one of 'create', 'update', 'delete', 'patch', 'list' + """ + method = None try: - delete_method = self.lookup_method('delete') + method = self.lookup_method(method_action) except: pass - if not delete_method: + if not method: try: - delete_method = self.lookup_method('delete', namespace='namespace') + method = self.lookup_method(method_action, namespace='namespace') except: pass - return delete_method is not None + return method is not None def object_from_params(self, module_params, obj=None): """ @@ -161,13 +164,69 @@ def object_from_params(self, module_params, obj=None): obj.api_version = self.api_version.lower() for param_name, param_value in module_params.items(): spec = self.find_arg_spec(param_name) - if spec.get('property_path'): + if param_value is not None and spec.get('property_path'): prop_path = copy.copy(spec['property_path']) self.__set_obj_attribute(obj, prop_path, param_value, param_name) logger.debug("Object from params:") logger.debug(json.dumps(obj.to_dict(), indent=4)) return obj + def request_body_from_params(self, module_params): + request = { + 'kind': self.base_model_name, + 'apiVersion': self.api_version.lower() + } + for param_name, param_value in module_params.items(): + spec = self.find_arg_spec(param_name) + if spec and spec.get('property_path') and param_value is not None: + self.__add_path_to_dict(request, param_name, param_value, spec['property_path']) + logger.debug('request_body:') + logger.debug(json.dumps(request, indent=4)) + return request + + def __add_path_to_dict(self, request_dict, param_name, param_value, path): + local_path = copy.copy(path) + spec = self.find_arg_spec(param_name) + while len(local_path): + p = local_path.pop(0) + if len(local_path): + if request_dict.get(p, None) is None: + request_dict[p] = {} + self.__add_path_to_dict(request_dict[p], param_name, param_value, local_path) + break + else: + param_type = spec.get('type', 'str') + if param_type == 'dict': + request_dict[p] = self.__dict_keys_to_camel(param_value) + elif param_type == 'list': + request_dict[p] = self.__list_keys_to_camel(param_value) + else: + request_dict[p] = param_value + + def __dict_keys_to_camel(self, param_dict): + result = {} + for item, value in param_dict.items(): + camel_name = string_utils.snake_case_to_camel(item) + key_name = camel_name[:1].lower() + camel_name[1:] + key_name = key_name[1:] if key_name.startswith('_') else key_name + if value: + if isinstance(value, list): + result[key_name] = self.__list_keys_to_camel(value) + elif isinstance(value, dict): + result[key_name] = self.__dict_keys_to_camel(value) + else: + result[key_name] = value + return result + + def __list_keys_to_camel(self, param_list): + result = [] + if isinstance(param_list[0], dict): + for item in param_list: + result.append(self.__dict_keys_to_camel(item)) + else: + result = param_list + return result + def find_arg_spec(self, module_param_name): """For testing, allow the param_name value to be an alias""" if self.argspec.get(module_param_name): @@ -234,6 +293,11 @@ def __set_obj_attribute(self, obj, property_path, param_value, param_name): setattr(obj, prop_name, self.__set_obj_attribute(sub_obj, property_path, param_value, param_name)) return obj + @staticmethod + def log(msg): + """ Allow Ansible module to add debug messages to the log """ + logger.debug(msg) + @staticmethod def __compare_list(src_values, request_values, param_name): """ @@ -426,14 +490,10 @@ def __update_object_properties(self, obj, item): return obj - def __log_argspec(self): - """ - Safely logs the argspec by not including any params with the no_log attribute. - - :return: None - """ + def log_argspec(self): + """ Safely logs the argspec by not including any params with the no_log attribute. """ logger.debug("arg_spec:") - tmp_arg_spec = copy.deepcopy(self.argspec) + tmp_arg_spec = copy.deepcopy(self._argspec_cache) pop_keys = [] for key, value in tmp_arg_spec.items(): if value.get('no_log'): @@ -453,7 +513,7 @@ def snake_case(name): choices[x] = snake_case(x) return choices - def __transform_properties(self, properties, prefix='', path=None, alternate_prefix='', hidden=False): + def __transform_properties(self, properties, prefix='', path=None, alternate_prefix=''): """ Convert a list of properties to an argument_spec dictionary @@ -478,17 +538,22 @@ def add_meta(prop_name, prop_prefix, prop_alt_prefix): prop_paths.append('metadata') prop_paths.append(prop_name) args[prop_prefix + prop_name]['property_path'] = prop_paths - if hidden: - args[prop_prefix + prop_name]['hide_from_module'] = True for prop, prop_attributes in properties.items(): - if prop in ('api_version', 'status', 'kind') and not prefix: + if prop in ('api_version', 'status', 'kind', 'items') and not prefix: # Don't expose these properties continue elif prop_attributes['immutable']: # Property cannot be set by the user continue - elif prop == 'metadata': + elif prop == 'metadata' and prop_attributes['class'].__name__ == 'UnversionedListMeta': + args['namespace'] = { + 'description': [ + 'Namespaces provide a scope for names. Names of resources need to be unique within a ' + 'namespace, but not across namespaces. Provide the namespace for the object.' + ] + } + elif prop == 'metadata' and prop_attributes['class'].__name__ != 'UnversionedListMeta': meta_prefix = prefix + '_metadata_' if prefix else '' meta_alt_prefix = alternate_prefix + '_metadata_' if alternate_prefix else '' if 'labels' in dir(prop_attributes['class']): @@ -546,22 +611,16 @@ def add_meta(prop_name, prop_prefix, prop_alt_prefix): p += '_' + label if p else label if alternate_label != self.base_model_name and alternate_label not in a: a += '_' + alternate_label if a else alternate_label - #sub_is_hidden = hidden if prop.endswith('params') and 'type' in properties: - # If the object contains a 'type' field (e.g. v1_deployment_trigger_policy), - # then '_params' objects should not be picked up by the Ansible module. - #sub_is_hidden = True sub_props = {} sub_props[prop] = { 'class': dict, 'immutable': False } - args.update(self.__transform_properties(sub_props, prefix=p, path=paths, alternate_prefix=a, - hidden=False)) + args.update(self.__transform_properties(sub_props, prefix=p, path=paths, alternate_prefix=a)) else: sub_props = self.properties_from_model_obj(prop_attributes['class']()) - args.update(self.__transform_properties(sub_props, prefix=p, path=paths, alternate_prefix=a, - hidden=False)) + args.update(self.__transform_properties(sub_props, prefix=p, path=paths, alternate_prefix=a)) else: # Adds a primitive property arg_prefix = prefix + '_' if prefix else '' @@ -577,9 +636,6 @@ def add_meta(prop_name, prop_prefix, prop_alt_prefix): if prop.endswith('params') and 'type' in properties: args[arg_prefix + prop]['type'] = 'dict' - if hidden: - args[arg_prefix + prop]['hide_from_module'] = True - # Use the alternate prefix to construct a human-friendly alias if arg_alt_prefix and arg_prefix != arg_alt_prefix: args[arg_prefix + prop]['aliases'] = [arg_alt_prefix + prop] diff --git a/requirements.txt b/requirements.txt index f67d8d95..9b2a18d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ kubernetes ~= 1.0.0 python-string-utils ruamel.yaml jinja2 +dictdiffer diff --git a/test-requirements.txt b/test-requirements.txt index 5f70d68c..322aa5de 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,4 +3,5 @@ docker ~= 2.1.0 flake8 pytest pytest-cov -PyYAML \ No newline at end of file +PyYAML +dictdiffer diff --git a/test/functional/conftest.py b/test/functional/conftest.py index 272b2a6f..4b99f979 100644 --- a/test/functional/conftest.py +++ b/test/functional/conftest.py @@ -14,7 +14,6 @@ import pytest import requests -from openshift.helper import KubernetesObjectHelper from openshift.client import models from openshift.helper.ansible import AnsibleModuleHelper @@ -44,7 +43,7 @@ def openshift_container(request): # Wait for the api server to be ready before continuing for _ in range(10): try: - resp = requests.head("https://127.0.0.1:8443/healthz/ready", verify=False) + requests.head("https://127.0.0.1:8443/healthz/ready", verify=False) except requests.RequestException: pass time.sleep(1) @@ -62,7 +61,7 @@ def kubeconfig(openshift_container, tmpdir_factory): # get_archive returns a stream of the tar archive containing the requested # files/directories, so we need use BytesIO as an intermediate step. if openshift_container is None: - return None + return None else: tar_stream, _ = openshift_container.get_archive('/var/lib/origin/openshift.local.config/master/admin.kubeconfig') tar_obj = tarfile.open(fileobj=io.BytesIO(tar_stream.read())) @@ -93,7 +92,8 @@ def compare_func(ansible_helper, k8s_obj, parameters): """ Assert that an object matches an expected object """ requested = copy.deepcopy(k8s_obj) ansible_helper.object_from_params(parameters, obj=requested) - assert ansible_helper.objects_match(k8s_obj, requested) + match, _ = ansible_helper.objects_match(k8s_obj, requested) + assert match return compare_func diff --git a/test/functional/test_v1_deployment_config.py b/test/functional/test_v1_deployment_config.py index d79a1d97..61bf5079 100644 --- a/test/functional/test_v1_deployment_config.py +++ b/test/functional/test_v1_deployment_config.py @@ -35,10 +35,10 @@ def replace_params(replace_tasks, project, object_name): @pytest.fixture() def deployment_config(ansible_helper, create_params): - new_obj = ansible_helper.object_from_params(create_params) + request_body = ansible_helper.request_body_from_params(create_params) namespace = create_params.get('namespace') name = create_params.get('name') - k8s_obj = ansible_helper.create_object(namespace, new_obj) + k8s_obj = ansible_helper.create_object(namespace, body=request_body) yield k8s_obj @@ -67,7 +67,7 @@ def test_patch_deployment(ansible_helper, deployment_config, patch_params, obj_c existing_obj = deployment_config updated_obj = copy.deepcopy(existing_obj) ansible_helper.object_from_params(patch_params, obj=updated_obj) - match = ansible_helper.objects_match(existing_obj, updated_obj) + match, _ = ansible_helper.objects_match(existing_obj, updated_obj) assert not match new_obj = ansible_helper.patch_object(name, namespace, updated_obj) assert new_obj is not None @@ -77,9 +77,8 @@ def test_patch_deployment(ansible_helper, deployment_config, patch_params, obj_c def test_replace_deployment(ansible_helper, deployment_config, replace_params, obj_compare): name = replace_params.get('name') namespace = replace_params.get('namespace') - existing_obj = deployment_config - ansible_helper.object_from_params(replace_params, obj=existing_obj) - k8s_obj = ansible_helper.replace_object(name, namespace, existing_obj) + request_body = ansible_helper.request_body_from_params(replace_params) + k8s_obj = ansible_helper.replace_object(name, namespace, body=request_body) obj_compare(ansible_helper, k8s_obj, replace_params) diff --git a/test/functional/test_v1_namespace.py b/test/functional/test_v1_namespace.py index 2a609f70..5a22b775 100644 --- a/test/functional/test_v1_namespace.py +++ b/test/functional/test_v1_namespace.py @@ -32,9 +32,9 @@ def replace_params(replace_tasks, object_name): @pytest.fixture() def k8s_namespace(ansible_helper, create_params): - new_obj = ansible_helper.object_from_params(create_params) + request_body = ansible_helper.request_body_from_params(create_params) name = create_params.get('name') - k8s_obj = ansible_helper.create_object(None, new_obj) + k8s_obj = ansible_helper.create_object(None, body=request_body) yield k8s_obj @@ -61,7 +61,7 @@ def test_patch_namespace(ansible_helper, k8s_namespace, patch_params, obj_compar existing_obj = k8s_namespace updated_obj = copy.deepcopy(existing_obj) ansible_helper.object_from_params(patch_params, obj=updated_obj) - match = ansible_helper.objects_match(existing_obj, updated_obj) + match, _ = ansible_helper.objects_match(existing_obj, updated_obj) assert not match new_obj = ansible_helper.patch_object(name, None, updated_obj) assert new_obj is not None @@ -70,9 +70,8 @@ def test_patch_namespace(ansible_helper, k8s_namespace, patch_params, obj_compar def test_replace_namespace(ansible_helper, k8s_namespace, replace_params, obj_compare): name = replace_params.get('name') - existing_obj = k8s_namespace - ansible_helper.object_from_params(replace_params, obj=existing_obj) - k8s_obj = ansible_helper.replace_object(name, None, existing_obj) + request_body = ansible_helper.request_body_from_params(replace_params) + k8s_obj = ansible_helper.replace_object(name, None, body=request_body) obj_compare(ansible_helper, k8s_obj, replace_params) diff --git a/test/functional/test_v1_route.py b/test/functional/test_v1_route.py index e32ad0b3..3ff3ec64 100644 --- a/test/functional/test_v1_route.py +++ b/test/functional/test_v1_route.py @@ -35,10 +35,10 @@ def replace_params(replace_tasks, project, object_name): @pytest.fixture() def route(ansible_helper, create_params): - new_obj = ansible_helper.object_from_params(create_params) + request_body = ansible_helper.request_body_from_params(create_params) namespace = create_params.get('namespace') name = create_params.get('name') - k8s_obj = ansible_helper.create_object(namespace, new_obj) + k8s_obj = ansible_helper.create_object(namespace, body=request_body) yield k8s_obj @@ -67,7 +67,7 @@ def test_patch_route(ansible_helper, route, patch_params, obj_compare): existing_obj = route updated_obj = copy.deepcopy(existing_obj) ansible_helper.object_from_params(patch_params, obj=updated_obj) - match = ansible_helper.objects_match(existing_obj, updated_obj) + match, _ = ansible_helper.objects_match(existing_obj, updated_obj) assert not match new_obj = ansible_helper.patch_object(name, namespace, updated_obj) assert new_obj is not None @@ -77,9 +77,8 @@ def test_patch_route(ansible_helper, route, patch_params, obj_compare): def test_replace_route(ansible_helper, route, replace_params, obj_compare): name = replace_params.get('name') namespace = replace_params.get('namespace') - existing_obj = route - ansible_helper.object_from_params(replace_params, obj=existing_obj) - k8s_obj = ansible_helper.replace_object(name, namespace, existing_obj) + request_body = ansible_helper.request_body_from_params(replace_params) + k8s_obj = ansible_helper.replace_object(name, namespace, body=request_body) obj_compare(ansible_helper, k8s_obj, replace_params) diff --git a/test/functional/test_v1_service.py b/test/functional/test_v1_service.py index df7efd5a..0051e596 100644 --- a/test/functional/test_v1_service.py +++ b/test/functional/test_v1_service.py @@ -35,10 +35,10 @@ def replace_params(replace_tasks, project, object_name): @pytest.fixture() def service(ansible_helper, create_params): - new_obj = ansible_helper.object_from_params(create_params) + request_body = ansible_helper.request_body_from_params(create_params) namespace = create_params.get('namespace') name = create_params.get('name') - k8s_obj = ansible_helper.create_object(namespace, new_obj) + k8s_obj = ansible_helper.create_object(namespace, body=request_body) yield k8s_obj @@ -66,8 +66,8 @@ def test_patch_service(ansible_helper, service, patch_params, obj_compare): namespace = patch_params.get('namespace') existing_obj = service updated_obj = copy.deepcopy(existing_obj) - ansible_helper.object_from_params(patch_params, obj=updated_obj) - match = ansible_helper.objects_match(existing_obj, updated_obj) + ansible_helper.object_from_params(parameters, obj=updated_obj) + match, _ = ansible_helper.objects_match(existing_obj, updated_obj) assert not match new_obj = ansible_helper.patch_object(name, namespace, updated_obj) assert new_obj is not None @@ -77,9 +77,8 @@ def test_patch_service(ansible_helper, service, patch_params, obj_compare): def test_replace_service(ansible_helper, service, replace_params, obj_compare): name = replace_params.get('name') namespace = replace_params.get('namespace') - existing_obj = service - ansible_helper.object_from_params(replace_params, obj=existing_obj) - k8s_obj = ansible_helper.replace_object(name, namespace, existing_obj) + request_body = ansible_helper.request_body_from_params(replace_params) + k8s_obj = ansible_helper.replace_object(name, namespace, body=request_body) obj_compare(ansible_helper, k8s_obj, replace_params)