diff --git a/openshift/dynamic/client.py b/openshift/dynamic/client.py index e66a7bb6..adc7e0a7 100755 --- a/openshift/dynamic/client.py +++ b/openshift/dynamic/client.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import copy import json from functools import partial @@ -24,6 +25,7 @@ 'DynamicClient', 'ResourceInstance', 'Resource', + 'ResourceList', 'Subresource', 'ResourceContainer', 'ResourceField', @@ -141,6 +143,7 @@ def get_resources_for_api_version(self, prefix, group, version, preferred): subresources=subresources.get(resource['name']), **resource ) + resources['{}List'.format(resource['kind'])] = ResourceList(resources[resource['kind']]) return resources def ensure_namespace(self, resource, namespace, body): @@ -329,7 +332,7 @@ def group_version(self): return self.api_version def __repr__(self): - return '<{}({}/{}>)'.format(self.__class__.__name__, self.group_version, self.name) + return '<{}({}/{})>'.format(self.__class__.__name__, self.group_version, self.name) @property def urls(self): @@ -360,6 +363,54 @@ def __getattr__(self, name): return partial(getattr(self.client, name), self) +class ResourceList(Resource): + """ Represents a list of API objects """ + + def __init__(self, resource): + self.resource = resource + self.kind = '{}List'.format(resource.kind) + + def get(self, body=None, **kwargs): + if body is None: + return self.resource.get(**kwargs) + response = copy.deepcopy(body) + namespace = kwargs.pop('namespace', None) + response['items'] = [ + self.resource.get(name=item['metadata']['name'], namespace=item['metadata'].get('namespace', namespace), **kwargs) + for item in body['items'] + ] + return ResourceInstance(self, response) + + def delete(self, body=None, *args, **kwargs): + response = copy.deepcopy(body) + namespace = kwargs.pop('namespace', None) + response['items'] = [ + self.resource.delete(name=item['metadata']['name'], namespace=item['metadata'].get('namespace', namespace), **kwargs) + for item in body['items'] + ] + return ResourceInstance(self, response) + + def verb_mapper(self, verb, body=None, **kwargs): + response = copy.deepcopy(body) + response['items'] = [ + getattr(self.resource, verb)(body=item, **kwargs) + for item in body['items'] + ] + return ResourceInstance(self, response) + + def create(self, *args, **kwargs): + return self.verb_mapper('create', *args, **kwargs) + + def replace(self, *args, **kwargs): + return self.verb_mapper('replace', *args, **kwargs) + + def patch(self, *args, **kwargs): + return self.verb_mapper('patch', *args, **kwargs) + + def __getattr__(self, name): + return getattr(self.resource, name) + + class Subresource(Resource): """ Represents a subresource of an API resource. This generally includes operations like scale, as well as status objects for an instantiated resource @@ -544,6 +595,8 @@ def __serialize(self, field): } elif isinstance(field, (list, tuple)): return [self.__serialize(item) for item in field] + elif isinstance(field, ResourceInstance): + return field.to_dict() else: return field @@ -572,18 +625,21 @@ def __dir__(self): def main(): config.load_kube_config() client = DynamicClient(ApiClient()) - ret = {} + ret = [] for resource in client.resources: - if resource.namespaced: - key = resource.urls['namespaced_full'] + key = '{}.{}'.format(resource.group_version, resource.kind) + item = {} + item[key] = {k: v for k, v in resource.__dict__.items() if k not in ('client', 'subresources', 'resource')} + if isinstance(resource, ResourceList): + item[key]["resource"] = '{}.{}'.format(resource.resource.group_version, resource.resource.kind) else: - key = resource.urls['full'] - ret[key] = {k: v for k, v in resource.__dict__.items() if k not in ('client', 'subresources')} - ret[key]['subresources'] = {} - for name, value in resource.subresources.items(): - ret[key]['subresources'][name] = {k: v for k, v in value.__dict__.items() if k != 'parent'} + item[key]['subresources'] = {} + for name, value in resource.subresources.items(): + item[key]['subresources'][name] = {k: v for k, v in value.__dict__.items() if k != 'parent'} + item[key]['urls'] = resource.urls + ret.append(item) - print(yaml.safe_dump(ret)) + print(yaml.safe_dump(sorted(ret, key=lambda x: x.keys()[0].replace('List', '1')), default_flow_style=False)) return 0 diff --git a/test/functional/dynamic/conftest.py b/test/functional/dynamic/conftest.py index ff37cd0f..bfd9531a 100644 --- a/test/functional/dynamic/conftest.py +++ b/test/functional/dynamic/conftest.py @@ -1,5 +1,4 @@ import os -import copy import time import yaml @@ -13,11 +12,10 @@ import kubernetes -from openshift.dynamic import DynamicClient, exceptions +from openshift.dynamic import DynamicClient, ResourceList, exceptions -@pytest.fixture -def object_contains(): +def object_contains(obj, subset): def dict_is_subset(obj, subset): return all([mapping.get(type(obj[k]), mapping['default'])(obj[k], v) for (k, v) in subset.items()]) @@ -34,19 +32,18 @@ def values_match(obj, subset): 'default': values_match } - return dict_is_subset + return dict_is_subset(obj, subset) -@pytest.fixture -def definition_loader(group_version, kind): +def load_definition(filename): + path = os.path.join(os.path.dirname(__file__), filename) + with open(path, 'r') as f: + return yaml.load(f.read()) - def inner(name): - filename = '_'.join([group_version, kind, name]).replace('/', '_') + '.yaml' - path = os.path.join(os.path.dirname(__file__), 'definitions', filename) - with open(path, 'r') as f: - return yaml.load(f.read()) - return inner +@pytest.fixture +def definition(filename): + return load_definition(filename) @pytest.fixture @@ -55,20 +52,12 @@ def context(): return state -@given(parsers.parse('. does not exist in ')) -def ensure_resource_not_in_namespace(admin_client, group_version, kind, name, namespace): - """. does not exist in .""" - resource = admin_client.resources.get(api_version=group_version, kind=kind) - try: - resource.delete(name, namespace) - except exceptions.NotFoundError: - pass - - def ensure_resource(resource, body, namespace): try: return resource.create(body=body, namespace=namespace) except exceptions.ConflictError: + if isinstance(resource, ResourceList): + return resource.get(body=body, namespace=namespace) return resource.get(name=body['metadata']['name'], namespace=namespace) except exceptions.InternalServerError as e: error = yaml.load(e.body) @@ -77,50 +66,56 @@ def ensure_resource(resource, body, namespace): raise time.sleep(retry_after_seconds) return resource.create(body=body, namespace=namespace) + except Exception: + # TODO: Sometimes we hit a timing issue, for now I'll just sleep + time.sleep(3) + return resource.create(body=body, namespace=namespace) + + +@given(parsers.parse('The content of does not exist in ')) +def ensure_resource_not_in_namespace(admin_client, namespace, definition): + resource = admin_client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + try: + if isinstance(resource, ResourceList): + resource.delete(body=definition, namespace=namespace) + else: + resource.delete(definition['metadata']['name'], namespace) + except exceptions.NotFoundError: + pass -@given(parsers.parse('. exists in ')) -def ensure_resource_in_namespace(admin_client, group_version, kind, name, namespace, definition_loader): - """. exists in .""" - resource = admin_client.resources.get(api_version=group_version, kind=kind) - instance = ensure_resource(resource, definition_loader(name), namespace) +@given(parsers.parse('The content of exists in ')) +def ensure_resource_in_namespace(admin_client, namespace, definition): + resource = admin_client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + instance = ensure_resource(resource, definition, namespace) assert instance is not None -@given(parsers.parse('I have created . in ')) -def ensure_user_resource_in_namespace(client, group_version, kind, name, namespace, definition_loader): - """. exists in .""" - resource = client.resources.get(api_version=group_version, kind=kind) - instance = ensure_resource(resource, definition_loader(name), namespace) +@given(parsers.parse('I have created in ')) +def ensure_user_resource_in_namespace(client, namespace, definition): + """I have created in .""" + resource = client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + instance = ensure_resource(resource, definition, namespace) assert instance is not None -@when(parsers.parse('I {action} . in ')) -def perform_action_in_namespace(context, client, action, group_version, kind, name, namespace): - """I ___.yaml.""" - fail = not action.startswith('try to ') - action = action.replace('try to ', '') - resource = client.resources.get(api_version=group_version, kind=kind) +def ensure_namespace(admin_client, namespace): + v1_projects = admin_client.resources.get(api_version='project.openshift.io/v1', kind="Project") try: - if action == 'create': - context["instance"] = resource.create(body=definition_loader(name), namespace=namespace) - elif action == 'delete': - context["instance"] = resource.delete(name=name, namespace=namespace) - elif action == 'get': - context["instance"] = resource.get(name=name, namespace=namespace) - else: - raise ValueError("Unable to {action} resource!".format(action)) - except Exception as e: - context['exc'] = e - if fail: - raise + project = v1_projects.get(name=namespace) + except exceptions.NotFoundError: + project = v1_projects.create({"apiVersion": "project.openshift.io/v1", "kind": "Project", "metadata": {"name": namespace}}) + if project.metadata.DeletionTimestamp: + # Wait up to 5 minutes for project to terminate + for _ in range(300): + try: + project = v1_projects.get(name=namespace) + except exceptions.NotFoundError: + project = v1_projects.create({"apiVersion": "project.openshift.io/v1", "kind": "Project", "metadata": {"name": namespace}}) + return project + return project -@then(parsers.parse('It throws a {error}')) -def it_throws_an_error(context, error): - """It throws an error""" - assert isinstance(context['exc'], getattr(exceptions, error)) - @given(parsers.parse('I have {clusterrole} permissions in ')) def client(clusterrole, namespace, kubeconfig, port, admin_client): @@ -129,8 +124,9 @@ def client(clusterrole, namespace, kubeconfig, port, admin_client): if needs_admin: return admin_client + ensure_namespace(admin_client, namespace) + k8s_client = kubernetes.config.new_client_from_config(str(kubeconfig)) - # k8s_client.configuration.verify_ssl = False k8s_client.configuration.host = 'https://localhost:{}'.format(port) v1_tkr = admin_client.resources.get(api_version='authentication.k8s.io/v1', kind='TokenReview') @@ -143,11 +139,6 @@ def client(clusterrole, namespace, kubeconfig, port, admin_client): } }).status.user.username - v1_projects = admin_client.resources.get(api_version='project.openshift.io/v1', kind="Project") - try: - v1_projects.create({"apiVersion": "project.openshift.io/v1", "kind": "Project", "metadata": {"name": namespace}}) - except exceptions.ConflictError: - pass role_binding = { "kind": "RoleBinding", @@ -174,3 +165,111 @@ def client(clusterrole, namespace, kubeconfig, port, admin_client): pass return DynamicClient(k8s_client) + + +@when(parsers.parse('I {action} with in ')) +def perform_update_action_in_namespace(context, client, action, namespace, definition, update): + + def set_resource_version(r, resource): + try: + r['metadata']['resourceVersion'] = resource.get(r['metadata']['name'], namespace=namespace).metadata.resourceVersion + except exceptions.NotFoundError: + r['metadata']['resourceVersion'] = "0" + return r + + fail = not action.startswith('try to ') + action = action.replace('try to ', '') + resource = client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + try: + if action == 'replace': + replace = load_definition(update) + if isinstance(resource, ResourceList): + replace['items'] = [set_resource_version(item, resource.resource) for item in replace['items']] + else: + replace = set_resource_version(replace, resource) + context['instance'] = resource.replace(body=replace, namespace=namespace) + elif action == 'patch': + patch = load_definition(update) + context['instance'] = resource.patch(body=patch, namespace=namespace) + else: + fail = True + raise ValueError('Unable to {action} resource!'.format(action)) + except Exception as e: + context['exc'] = e + if fail: + raise + + +@when(parsers.parse('I {action} in ')) +def perform_action_in_namespace(context, client, action, namespace, definition): + fail = not action.startswith('try to ') + action = action.replace('try to ', '') + resource = client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + try: + if action == 'create': + context['instance'] = resource.create(body=definition, namespace=namespace) + elif action == 'delete': + if isinstance(resource, ResourceList): + context['instance'] = resource.delete(body=definition, namespace=namespace) + else: + context['instance'] = resource.delete(name=definition['metadata']['name'], namespace=namespace) + elif action == 'get': + if isinstance(resource, ResourceList): + context['instance'] = resource.get(body=definition, namespace=namespace) + else: + context['instance'] = resource.get(name=definition['metadata']['name'], namespace=namespace) + else: + fail = True + raise ValueError('Unable to {action} resource!'.format(action)) + except Exception as e: + context['exc'] = e + if fail: + raise + + +@then(parsers.parse('It throws a {error}')) +def it_throws_an_error(context, error): + """It throws an error""" + assert isinstance(context['exc'], getattr(exceptions, error)) + + +@then('The resources in in should match the content of ') +def resource_should_match_update(admin_client, namespace, update, definition): + update = load_definition(update) + resource = admin_client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + if isinstance(resource, ResourceList): + cluster_instance = resource.get(body=definition, namespace=namespace).to_dict() + else: + cluster_instance = resource.get(name=definition['metadata']['name'], namespace=namespace).to_dict() + assert object_contains(cluster_instance, update) + + +@then(parsers.parse('The content of does not exist in ')) +def resource_not_in_namespace(admin_client, namespace, definition): + + def assert_resource_does_not_exist(resource, resource_definition, namespace): + with pytest.raises(exceptions.NotFoundError): + resource.get(resource_definition['metadata']['name'], namespace) + + resource = admin_client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + if isinstance(resource, ResourceList): + for item in definition['items']: + assert_resource_does_not_exist(resource.resource, item, namespace) + else: + assert_resource_does_not_exist(resource, definition, namespace) + + +@then(parsers.parse('The content of exists in ')) +def resource_in_namespace(admin_client, namespace, definition): + + def assert_resource_exists(resource, resource_definition, namespace): + instance = resource.get(resource_definition['metadata']['name'], namespace) + assert instance.metadata.name == resource_definition['metadata']['name'] + assert instance.metadata.namespace == namespace + + resource = admin_client.resources.get(api_version=definition['apiVersion'], kind=definition['kind']) + if isinstance(resource, ResourceList): + for item in definition['items']: + assert_resource_exists(resource.resource, item, namespace) + else: + assert_resource_exists(resource, definition, namespace) diff --git a/test/functional/dynamic/create.feature b/test/functional/dynamic/create.feature index 8e6b0c8b..8c6ea5f4 100644 --- a/test/functional/dynamic/create.feature +++ b/test/functional/dynamic/create.feature @@ -1,17 +1,19 @@ Feature: Create Examples: - | group_version | kind | namespace | name | - | v1 | Pod | test | test | + | filename | namespace | + | definitions/v1_Pod_test.yaml | test | + | definitions/v1_PodList_test.yaml | test2 | + Scenario Outline: Create a resource for the first time Given I have edit permissions in - And . does not exist in - When I create . in - Then . exists in + And The content of does not exist in + When I create in + Then The content of exists in Scenario Outline: Create a resource again Given I have edit permissions in - And I have created . in - When I try to create . in + And I have created in + When I try to create in Then It throws a ConflictError diff --git a/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test.yaml b/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test.yaml new file mode 100644 index 00000000..c3502bd6 --- /dev/null +++ b/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test.yaml @@ -0,0 +1,17 @@ + +--- +apiVersion: route.openshift.io/v1 +kind: RouteList +items: +- metadata: + name: test-route + spec: + to: + name: test + kind: Service +- metadata: + name: test-route2 + spec: + to: + name: test2 + kind: Service diff --git a/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test_replace.yaml b/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test_replace.yaml new file mode 100644 index 00000000..3c94253f --- /dev/null +++ b/test/functional/dynamic/definitions/route.openshift.io_v1_RouteList_test_replace.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: route.openshift.io/v1 +kind: RouteList +items: +- metadata: + name: test-route + spec: + to: + name: test3 + kind: Service +- metadata: + name: test-route2 + spec: + to: + name: test4 + kind: Service diff --git a/test/functional/dynamic/definitions/v1_PodList_test.yaml b/test/functional/dynamic/definitions/v1_PodList_test.yaml new file mode 100644 index 00000000..eb72f582 --- /dev/null +++ b/test/functional/dynamic/definitions/v1_PodList_test.yaml @@ -0,0 +1,33 @@ +apiVersion: v1 +items: +- apiVersion: v1 + kind: Pod + metadata: + name: example-app2 + spec: + containers: + - args: + - "3600" + command: + - sleep + image: busybox:latest + imagePullPolicy: Always + name: example-app + resources: {} + restartPolicy: Always +- apiVersion: v1 + kind: Pod + metadata: + name: example-app + spec: + containers: + - args: + - "3600" + command: + - sleep + image: busybox:latest + imagePullPolicy: Always + name: example-app + resources: {} + restartPolicy: Always +kind: PodList diff --git a/test/functional/dynamic/definitions/v1_PodList_test_patch.yaml b/test/functional/dynamic/definitions/v1_PodList_test_patch.yaml new file mode 100644 index 00000000..e03e5c29 --- /dev/null +++ b/test/functional/dynamic/definitions/v1_PodList_test_patch.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +items: +- metadata: + name: example-app2 + spec: + containers: + - image: busybox:1 + name: example-app +- metadata: + name: example-app + spec: + containers: + - image: busybox:2 + name: example-app +kind: PodList diff --git a/test/functional/dynamic/definitions/v1_Pod_test_patch.yaml b/test/functional/dynamic/definitions/v1_Pod_test_patch.yaml index a5c0172c..8ed5fd61 100644 --- a/test/functional/dynamic/definitions/v1_Pod_test_patch.yaml +++ b/test/functional/dynamic/definitions/v1_Pod_test_patch.yaml @@ -1,3 +1,5 @@ +metadata: + name: test spec: containers: - image: busybox:1 diff --git a/test/functional/dynamic/delete.feature b/test/functional/dynamic/delete.feature index 6d54b07d..2286ae43 100644 --- a/test/functional/dynamic/delete.feature +++ b/test/functional/dynamic/delete.feature @@ -1,17 +1,18 @@ Feature: Delete Examples: - | group_version | kind | namespace | name | - | v1 | Pod | test | test | + | filename | namespace | + | definitions/v1_Pod_test.yaml | test | + | definitions/v1_PodList_test.yaml | test2 | Scenario Outline: Delete a resource that exists Given I have edit permissions in - And . exists in - When I delete . in - Then . does not exist in + And The content of exists in + When I delete in + Then The content of does not exist in Scenario Outline: Delete a resource that does not exist Given I have edit permissions in - And . does not exist in - When I try to delete . in + And The content of does not exist in + When I try to delete in Then It throws a NotFoundError diff --git a/test/functional/dynamic/patch.feature b/test/functional/dynamic/patch.feature index 8d7033d7..73c84e84 100644 --- a/test/functional/dynamic/patch.feature +++ b/test/functional/dynamic/patch.feature @@ -1,17 +1,18 @@ Feature: Patch Examples: - | group_version | kind | namespace | name | update | - | v1 | Pod | test-patch | test | test_patch | + | filename | namespace | update | + | definitions/v1_Pod_test.yaml | test-patch | definitions/v1_Pod_test_patch.yaml | + | definitions/v1_PodList_test.yaml | test-patch2 | definitions/v1_PodList_test_patch.yaml | Scenario Outline: Patch a resource that does not exist Given I have edit permissions in - And . does not exist in - When I try to patch . in with + And The content of does not exist in + When I try to patch with in Then It throws a NotFoundError Scenario Outline: Patch a resource that exists Given I have edit permissions in - And I have created . in - When I patch . in with - Then . in should match the content of + And I have created in + When I patch with in + Then The resources in in should match the content of diff --git a/test/functional/dynamic/replace.feature b/test/functional/dynamic/replace.feature index 44763ad6..bdf30d06 100644 --- a/test/functional/dynamic/replace.feature +++ b/test/functional/dynamic/replace.feature @@ -1,17 +1,18 @@ Feature: Replace Examples: - | group_version | kind | namespace | name | update | - | route.openshift.io/v1 | Route | test-replace | test | test_replace | + | filename | namespace | update | + | definitions/route.openshift.io_v1_Route_test.yaml | test-replace | definitions/route.openshift.io_v1_Route_test_replace.yaml | + | definitions/route.openshift.io_v1_RouteList_test.yaml | test-replace | definitions/route.openshift.io_v1_RouteList_test_replace.yaml | Scenario Outline: Replace a resource that does not exist Given I have edit permissions in - And . does not exist in - When I try to replace . in with + And The content of does not exist in + When I try to replace with in Then It throws a NotFoundError Scenario Outline: Replace a resource that exists Given I have edit permissions in - And I have created . in - When I replace . in with - Then . in should match the content of + And I have created in + When I replace with in + Then The resources in in should match the content of diff --git a/test/functional/dynamic/test_create.py b/test/functional/dynamic/test_create.py index da7d39ca..944a4abe 100644 --- a/test/functional/dynamic/test_create.py +++ b/test/functional/dynamic/test_create.py @@ -1,4 +1,9 @@ -from pytest_bdd import scenario, then, when, parsers +# coding=utf-8 +"""create feature tests. +All step implementations are in conftest.py +""" + +from pytest_bdd import scenario @scenario('create.feature', 'Create a resource again') @@ -11,29 +16,3 @@ def test_create_a_resource_again(): def test_create_a_resource_for_the_first_time(): """Create a resource for the first time.""" pass - - -@then(parsers.parse('. exists in ')) -def resource_in_namespace(admin_client, group_version, kind, name, namespace): - """. exists in .""" - resource = admin_client.resources.get(api_version=group_version, kind=kind) - instance = resource.get(name, namespace) - assert instance.metadata.name == name - assert instance.metadata.namespace == namespace - - -@when(parsers.parse('I create . in ')) -def create_resource_in_namespace(context, client, group_version, kind, name, namespace, definition_loader): - """I create ___.yaml.""" - resource = client.resources.get(api_version=group_version, kind=kind) - context["instance"] = resource.create(body=definition_loader(name), namespace=namespace) - - -@when(parsers.parse('I try to create . in ')) -def attempt_create_resource_in_namespace(context, client, group_version, kind, name, namespace, definition_loader): - """I ___.yaml.""" - resource = client.resources.get(api_version=group_version, kind=kind) - try: - context["instance"] = resource.create(body=definition_loader(name), namespace=namespace) - except Exception as e: - context['exc'] = e diff --git a/test/functional/dynamic/test_delete.py b/test/functional/dynamic/test_delete.py index 725fed0c..726f4584 100644 --- a/test/functional/dynamic/test_delete.py +++ b/test/functional/dynamic/test_delete.py @@ -1,7 +1,9 @@ -import pytest -from pytest_bdd import scenario, then, parsers +# coding=utf-8 +"""delete feature tests. +All step implementations are in conftest.py +""" -from openshift.dynamic import exceptions +from pytest_bdd import scenario @scenario('delete.feature', 'Delete a resource that exists') @@ -14,11 +16,3 @@ def test_delete_a_resource_that_exists(): def test_delete_a_resource_that_does_not_exist(): """Delete a resource that does not exist""" pass - - -@then(parsers.parse('. does not exist in ')) -def resource_not_in_namespace(admin_client, group_version, kind, name, namespace): - """. does not exist in .""" - resource = admin_client.resources.get(api_version=group_version, kind=kind) - with pytest.raises(exceptions.NotFoundError): - resource.get(name, namespace) diff --git a/test/functional/dynamic/test_patch.py b/test/functional/dynamic/test_patch.py index 615b4cde..1e9fa6be 100644 --- a/test/functional/dynamic/test_patch.py +++ b/test/functional/dynamic/test_patch.py @@ -1,11 +1,9 @@ # coding=utf-8 -"""Patch feature tests.""" +"""Patch feature tests. +All step implementations are in conftest.py +""" -from pytest_bdd import ( - scenario, - then, - when, -) +from pytest_bdd import scenario @scenario('patch.feature', 'Patch a resource that does not exist') @@ -18,31 +16,3 @@ def test_patch_a_resource_that_does_not_exist(): def test_patch_a_resource_that_exists(): """Patch a resource that exists.""" pass - - -@when('I patch . in with ') -def patch_resource_in_namespace(context, client, group_version, kind, name, namespace, update, definition_loader): - """I patch . in with .""" - patch = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - context['instance'] = resource.patch(body=patch, name=name, namespace=namespace) - - -@when('I try to patch . in with ') -def attempt_patch_resource_in_namespace(context, client, group_version, kind, name, namespace, update, definition_loader): - """I try to patch . in with .""" - patch = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - try: - context['instance'] = resource.patch(body=patch, name=name, namespace=namespace) - except Exception as e: - context['exc'] = e - - -@then('. in should match the content of ') -def resource_should_match_update(context, client, group_version, kind, name, namespace, update, definition_loader, object_contains): - """. in should match the content of .""" - patch = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - cluster_instance = resource.get(name=name, namespace=namespace).to_dict() - assert object_contains(cluster_instance, patch) diff --git a/test/functional/dynamic/test_replace.py b/test/functional/dynamic/test_replace.py index eafb1d73..1c650a4c 100644 --- a/test/functional/dynamic/test_replace.py +++ b/test/functional/dynamic/test_replace.py @@ -1,13 +1,9 @@ # coding=utf-8 -"""replace feature tests.""" +"""replace feature tests. +All step implementations are in conftest.py +""" -from pytest_bdd import ( - scenario, - then, - when, -) - -from openshift.dynamic.exceptions import NotFoundError +from pytest_bdd import scenario @scenario('replace.feature', 'Replace a resource that does not exist') @@ -20,37 +16,3 @@ def test_replace_a_resource_that_does_not_exist(): def test_replace_a_resource_that_exists(): """replace a resource that exists.""" pass - - -@when('I replace . in with ') -def replace_resource_in_namespace(context, client, group_version, kind, name, namespace, update, definition_loader): - """I replace . in with .""" - replace = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - replace['metadata']['resourceVersion'] = resource.get(replace['metadata']['name'], namespace).metadata.resourceVersion - - context['instance'] = resource.replace(body=replace, namespace=namespace) - - -@when('I try to replace . in with ') -def attempt_replace_resource_in_namespace(context, client, group_version, kind, name, namespace, update, definition_loader): - """I try to replace . in with .""" - replace = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - try: - replace['metadata']['resourceVersion'] = resource.get(replace['metadata']['name'], namespace).metadata.resourceVersion - except NotFoundError: - replace['metadata']['resourceVersion'] = "0" - try: - context['instance'] = resource.replace(body=replace, namespace=namespace) - except Exception as e: - context['exc'] = e - - -@then('. in should match the content of ') -def resource_should_match_update(context, client, group_version, kind, name, namespace, update, definition_loader, object_contains): - """. in should match the content of .""" - replace = definition_loader(update) - resource = client.resources.get(api_version=group_version, kind=kind) - cluster_instance = resource.get(name=name, namespace=namespace).to_dict() - assert object_contains(cluster_instance, replace)