diff --git a/.travis.yml b/.travis.yml index 58500761..fbdf59e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ python: env: - TEST_SUITE=lint - TEST_SUITE=functional OPENSHIFT_VERSION=latest + - TEST_SUITE=functional OPENSHIFT_VERSION=3.7 - TEST_SUITE=functional OPENSHIFT_VERSION=3.6 - TEST_SUITE=functional OPENSHIFT_VERSION=1.5 - TEST_SUITE=functional OPENSHIFT_VERSION=1.4 diff --git a/openshift/ansiblegen/docstrings.py b/openshift/ansiblegen/docstrings.py index f00715c1..8d7acaa8 100644 --- a/openshift/ansiblegen/docstrings.py +++ b/openshift/ansiblegen/docstrings.py @@ -272,7 +272,7 @@ def examples(self): if os.path.exists(example_path): logger.debug('parsing {}'.format(example_path)) yaml_examples = ruamel.yaml.load(open(example_path, 'r'), Loader=ruamel.yaml.RoundTripLoader) - for ex in yaml_examples: + for ex in yaml_examples['tasks']: new_example = CommentedMap() for key, value in ex.items(): if key == 'name': diff --git a/openshift/ansiblegen/examples/k8s_v1_horizontal_pod_autoscaler.yml b/openshift/ansiblegen/examples/k8s_v1_horizontal_pod_autoscaler.yml index 38623a8e..f0fdbe4b 100644 --- a/openshift/ansiblegen/examples/k8s_v1_horizontal_pod_autoscaler.yml +++ b/openshift/ansiblegen/examples/k8s_v1_horizontal_pod_autoscaler.yml @@ -1,6 +1,7 @@ # v1_horizontal_pod_autoscaler.yml --- +tasks: - create: name: test-scaler namespace: test diff --git a/openshift/ansiblegen/examples/k8s_v1_namespace.yml b/openshift/ansiblegen/examples/k8s_v1_namespace.yml index 1a22f394..a6e3ecc2 100644 --- a/openshift/ansiblegen/examples/k8s_v1_namespace.yml +++ b/openshift/ansiblegen/examples/k8s_v1_namespace.yml @@ -1,10 +1,12 @@ # v1_namespace.yml --- +admin: yes +tasks: - create: name: k8s-namespace name: Create a namespace - + - patch: name: k8s-namespace labels: @@ -13,7 +15,7 @@ annotations: domain: namespace.com.acmecorp name: Add labels and annotations - + - patch: name: k8s-namespace labels: @@ -24,11 +26,11 @@ domain: namespace.app.com.acmecorp monitoring_group: '1' name: Update labels and annotations - + - remove: name: k8s-namespace task_name: Delete a namespace - + - create: name: search-namespace labels: @@ -37,14 +39,14 @@ annotations: company: acme.com name: Create a namespace - + - patch: name: search-namespace labels: app: search type: web task_name: Update labels - + - replace: name: search-namespace labels: @@ -53,7 +55,8 @@ annotations: company: acme.com name: Replace namespace - + - remove: name: search-namespace name: Remove namespace + diff --git a/openshift/ansiblegen/examples/k8s_v1_persistent_volume.yml b/openshift/ansiblegen/examples/k8s_v1_persistent_volume.yml index 0a6b29b4..9bbb2776 100644 --- a/openshift/ansiblegen/examples/k8s_v1_persistent_volume.yml +++ b/openshift/ansiblegen/examples/k8s_v1_persistent_volume.yml @@ -1,6 +1,8 @@ # v1_persistent_volume.yml --- +admin: yes +tasks: - create: name: mypv capacity: diff --git a/openshift/ansiblegen/examples/k8s_v1_persistent_volume_claim.yml b/openshift/ansiblegen/examples/k8s_v1_persistent_volume_claim.yml index 09cd08d9..f32fb0db 100644 --- a/openshift/ansiblegen/examples/k8s_v1_persistent_volume_claim.yml +++ b/openshift/ansiblegen/examples/k8s_v1_persistent_volume_claim.yml @@ -1,6 +1,7 @@ # v1_persistent_volume_claim.yml --- +tasks: - create: name: mypvc namespace: demo_project diff --git a/openshift/ansiblegen/examples/k8s_v1_service.yml b/openshift/ansiblegen/examples/k8s_v1_service.yml index f4a67387..2ea242d2 100644 --- a/openshift/ansiblegen/examples/k8s_v1_service.yml +++ b/openshift/ansiblegen/examples/k8s_v1_service.yml @@ -1,6 +1,7 @@ # v1_service.yml --- +tasks: - create: name: myservice namespace: k8s-project @@ -26,7 +27,7 @@ - port: 8788 target_port: 8080 name: socket-port - type: NodePort + type: ClusterIP name: Patch service - create: @@ -67,5 +68,5 @@ - port: 8080 target_port: 8080 name: http - type: ClusterIP - name: Repace service \ No newline at end of file + type: NodePort + name: Repace service diff --git a/openshift/ansiblegen/examples/k8s_v1beta1_replica_set.yml b/openshift/ansiblegen/examples/k8s_v1beta1_replica_set.yml index ff024bfb..72fd0470 100644 --- a/openshift/ansiblegen/examples/k8s_v1beta1_replica_set.yml +++ b/openshift/ansiblegen/examples/k8s_v1beta1_replica_set.yml @@ -1,6 +1,7 @@ # v1beta1_replica_set.yml --- +tasks: - create: name: myreplicaset namespace: test diff --git a/openshift/ansiblegen/examples/k8s_v1beta1_stateful_set.yml b/openshift/ansiblegen/examples/k8s_v1beta1_stateful_set.yml index eb2cea97..bb59d24e 100644 --- a/openshift/ansiblegen/examples/k8s_v1beta1_stateful_set.yml +++ b/openshift/ansiblegen/examples/k8s_v1beta1_stateful_set.yml @@ -1,6 +1,10 @@ # v1beta1_stateful_set.yml --- +version_limits: + min: '1.5' + +tasks: - create: name: test labels: diff --git a/openshift/ansiblegen/examples/openshift_v1_deployment_config.yml b/openshift/ansiblegen/examples/openshift_v1_deployment_config.yml index 9e5434a2..dd2ffa2c 100644 --- a/openshift/ansiblegen/examples/openshift_v1_deployment_config.yml +++ b/openshift/ansiblegen/examples/openshift_v1_deployment_config.yml @@ -1,6 +1,7 @@ # v1_deployment_config.yml --- +tasks: - create: name: frontend namespace: k8s-project diff --git a/openshift/ansiblegen/examples/openshift_v1_project.yml b/openshift/ansiblegen/examples/openshift_v1_project.yml index 0f156818..83b8935c 100644 --- a/openshift/ansiblegen/examples/openshift_v1_project.yml +++ b/openshift/ansiblegen/examples/openshift_v1_project.yml @@ -1,6 +1,8 @@ # v1_project.yml --- +admin: yes +tasks: - create: name: example name: Create project @@ -15,4 +17,3 @@ - remove: name: example name: Remove project - diff --git a/openshift/ansiblegen/examples/openshift_v1_route.yml b/openshift/ansiblegen/examples/openshift_v1_route.yml index c79fc1ad..3fac9fb7 100644 --- a/openshift/ansiblegen/examples/openshift_v1_route.yml +++ b/openshift/ansiblegen/examples/openshift_v1_route.yml @@ -1,6 +1,7 @@ # v1_route.yml --- +tasks: - create: name: myroute namespace: k8s-project diff --git a/setup.cfg b/setup.cfg index 2e11ed61..716a8148 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,5 @@ norecursedirs = docs addopts = --cov=openshift - --cov-report=term --cov-report=html --cov-append diff --git a/test/functional/conftest.py b/test/functional/conftest.py index a64c3014..2fc0b2fd 100644 --- a/test/functional/conftest.py +++ b/test/functional/conftest.py @@ -2,6 +2,7 @@ from __future__ import absolute_import from __future__ import print_function +import re import copy import io import os @@ -96,67 +97,30 @@ def admin_kubeconfig(openshift_container, tmpdir_factory): return kubeconfig_file -@pytest.fixture(scope='module') -def k8s_ansible_helper(request, kubeconfig): - _, _, api_version, resource = request.module.__name__.split('_', 3) - auth = {} - if kubeconfig is not None: - auth = { - 'kubeconfig': str(kubeconfig), - 'host': 'https://localhost:8443', - 'verify_ssl': False - } - helper = KubernetesAnsibleModuleHelper(api_version, resource, debug=True, reset_logfile=False, **auth) - helper.api_client.config.debug = True - - return helper +def parse_test_name(name): + pieces = re.findall('[A-Z][a-z0-9]*', name) + api_version = pieces[1].lower() + resource = '_'.join(map(str.lower, pieces[2:])) + return api_version, resource -@pytest.fixture(scope='module') -def openshift_ansible_helper(request, kubeconfig): - _, _, api_version, resource = request.module.__name__.split('_', 3) +@pytest.fixture(scope='class') +def ansible_helper(request, kubeconfig, admin_kubeconfig): + api_version, resource = parse_test_name(request.node.name) + needs_admin = request.node.cls.tasks.get('admin') + config = admin_kubeconfig if needs_admin else kubeconfig auth = {} if kubeconfig is not None: auth = { - 'kubeconfig': str(kubeconfig), + 'kubeconfig': str(config), 'host': 'https://localhost:8443', 'verify_ssl': False } - helper = OpenShiftAnsibleModuleHelper(api_version, resource, debug=True, reset_logfile=False, **auth) - helper.api_client.config.debug = True - - return helper + try: + helper = KubernetesAnsibleModuleHelper(api_version, resource, debug=True, reset_logfile=False, **auth) + except Exception: + helper = OpenShiftAnsibleModuleHelper(api_version, resource, debug=True, reset_logfile=False, **auth) - -@pytest.fixture(scope='module') -def admin_k8s_ansible_helper(request, admin_kubeconfig): - _, _, api_version, resource = request.module.__name__.split('_', 3) - auth = {} - if admin_kubeconfig is not None: - auth = { - 'kubeconfig': str(admin_kubeconfig), - 'host': 'https://localhost:8443', - 'verify_ssl': False - } - helper = KubernetesAnsibleModuleHelper(api_version, resource, **auth) - helper.enable_debug(to_file=False) - helper.api_client.config.debug = True - - return helper - - -@pytest.fixture(scope='module') -def admin_openshift_ansible_helper(request, admin_kubeconfig): - _, _, api_version, resource = request.module.__name__.split('_', 3) - auth = {} - if admin_kubeconfig is not None: - auth = { - 'kubeconfig': str(admin_kubeconfig), - 'host': 'https://localhost:8443', - 'verify_ssl': False - } - helper = OpenShiftAnsibleModuleHelper(api_version, resource, **auth) - helper.enable_debug(to_file=False) helper.api_client.config.debug = True return helper @@ -192,7 +156,7 @@ def compare_func(ansible_helper, k8s_obj, parameters): return compare_func -@pytest.fixture(scope='module') +@pytest.fixture(scope='class') def namespace(kubeconfig): name = "test-{}".format(uuid.uuid4()) @@ -214,14 +178,12 @@ def namespace(kubeconfig): @pytest.fixture() -def object_name(): - # v1.3 services cannot be longer than 24 characters long - # truncate at 23 to avoid a trailing '-' - name = 'test-{}'.format(uuid.uuid4())[:23] - return name +def object_name(request): + action = request.function.__name__.split('_')[1] + return '{}-{}'.format(action, uuid.uuid4())[:22].strip('-') -@pytest.fixture(scope='module') +@pytest.fixture(scope='class') def project(kubeconfig): name = "test-{}".format(uuid.uuid4()) auth = {} @@ -247,21 +209,31 @@ def openshift_version(): @pytest.fixture(autouse=True) -def skip_by_version(request, openshift_version): - if request.node.get_marker('version_limit') and openshift_version: +def skip_empty(request): + api_version, resource = parse_test_name(request.node.cls._type) + action = request.function.__name__.split('_')[1] + tasks = list(filter(lambda x: x.get(action), request.node.cls.tasks['tasks'])) + if not tasks and action not in ['get', 'remove']: + pytest.skip('No example provided to {} {}'.format(action, resource)) - lowest_version = request.node.get_marker('version_limit').kwargs.get('lowest_version') - highest_version = request.node.get_marker('version_limit').kwargs.get('highest_version') - skip_latest = request.node.get_marker('version_limit').kwargs.get('skip_latest') - if openshift_version == 'latest' and skip_latest: - pytest.skip('This API is not supported in the latest openshift version') +@pytest.fixture(autouse=True) +def skip_by_version(request, openshift_version): + if request.node.cls.tasks.get('version_limits') and openshift_version: + lowest_version = request.node.cls.tasks['version_limits'].get('min') + highest_version = request.node.cls.tasks['version_limits'].get('max') + skip_latest = request.node.cls.tasks['version_limits'].get('latest') too_low = lowest_version and parse_version(lowest_version) > parse_version(openshift_version) too_high = highest_version and parse_version(highest_version) < parse_version(openshift_version) - if too_low or too_high: - pytest.skip('This API is not supported in openshift versions < {}'.format(openshift_version)) + if openshift_version == 'latest': + if skip_latest: + pytest.skip('This API is not supported in the latest openshift version') + elif too_low: + pytest.skip('This API is not supported in openshift versions > {}. You are using version {}'.format(lowest_version, openshift_version)) + elif too_high: + pytest.skip('This API is not supported in openshift versions < {}. You are using version {}'.format(highest_version, openshift_version)) def _get_id(argvalue): @@ -275,37 +247,3 @@ def _get_id(argvalue): elif argvalue.get('replace'): op_type = 'replace' return op_type + '_' + argvalue[op_type]['name'] + '_' + "{:0>3}".format(argvalue['seq']) - - -def pytest_generate_tests(metafunc): - _, api_version, resource = metafunc.module.__name__.split('_', 2) - yaml_name = api_version + '_' + resource + '.yml' - yaml_path = os.path.normpath(os.path.join(os.path.dirname(__file__), - '../../openshift/ansiblegen/examples', yaml_name)) - if not os.path.exists(yaml_path): - raise Exception("ansible_data: Unable to locate {}".format(yaml_path)) - with open(yaml_path, 'r') as f: - data = yaml.load(f) - seq = 0 - for task in data: - seq += 1 - task['seq'] = seq - - if 'create_tasks' in metafunc.fixturenames: - tasks = [x for x in data if x.get('create')] - metafunc.parametrize("create_tasks", tasks, False, _get_id) - if 'patch_tasks' in metafunc.fixturenames: - tasks = [x for x in data if x.get('patch')] - metafunc.parametrize("patch_tasks", tasks, False, _get_id) - if 'remove_tasks' in metafunc.fixturenames: - tasks = [x for x in data if x.get('remove')] - metafunc.parametrize("remove_tasks", tasks, False, _get_id) - if 'replace_tasks' in metafunc.fixturenames: - tasks = [x for x in data if x.get('replace')] - metafunc.parametrize("replace_tasks", tasks, False, _get_id) - if 'namespaces' in metafunc.fixturenames: - tasks = [x for x in data if x.get('create') and x['create'].get('namespace')] - unique_namespaces = dict() - for task in tasks: - unique_namespaces[task['create']['namespace']] = None - metafunc.parametrize("namespaces", list(unique_namespaces.keys())) diff --git a/test/functional/test_examples.py b/test/functional/test_examples.py new file mode 100644 index 00000000..8bea4e40 --- /dev/null +++ b/test/functional/test_examples.py @@ -0,0 +1,158 @@ +# -**- +from __future__ import absolute_import +from __future__ import print_function + +import os +import copy + +import yaml + +import pytest + +from openshift.helper.exceptions import KubernetesException + + +def get_tasks(): + """ Goes to the examples for the ansible docs and parses out tasks, resources and api versions """ + tasks = [] + example_dir = os.path.normpath(os.path.join( + os.path.dirname(__file__), '../../openshift/ansiblegen/examples/') + ) + yaml_names = os.listdir(example_dir) + for yaml_name in yaml_names: + _, api_version, resource = yaml_name.split('_', 2) + resource = resource[0:-4] + yaml_path = os.path.join(example_dir, yaml_name) + + with open(yaml_path, 'r') as f: + data = yaml.load(f) + + tasks.append(((api_version, resource), data)) + return tasks + + +class Example(object): + """ Contains the logic for testing create/get/patch/replace/remove on an openshift/k8s resource """ + + def test_create(self, ansible_helper, create_params, project, object_name, resources, obj_compare): + for params, resource in zip(create_params, resources): + obj_compare(ansible_helper, resource, params) + + def test_get(self, ansible_helper, resources): + for resource in resources: + name = resource.metadata.name + namespace = resource.metadata.namespace + k8s_obj = ansible_helper.get_object(name, namespace) + assert k8s_obj is not None + + def test_patch_resource(self, ansible_helper, resources, patch_params, obj_compare): + for i, resource in enumerate(resources): + for params in patch_params: + params['name'] = params['name'] + str(i) + name = params.get('name') + namespace = params.get('namespace') + existing_obj = resource + updated_obj = copy.deepcopy(existing_obj) + ansible_helper.object_from_params(params, 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 + obj_compare(ansible_helper, new_obj, params) + break + + def test_replace_resource(self, ansible_helper, resources, replace_params, obj_compare): + for i, resource in enumerate(resources): + for params in replace_params: + params['name'] = params['name'] + str(i) + name = params.get('name') + namespace = params.get('namespace') + existing = resource + request_body = ansible_helper.request_body_from_params(params) + if hasattr(existing.spec, 'cluster_ip'): + # can't change the cluster_ip value + request_body['spec']['clusterIP'] = existing.spec.cluster_ip + k8s_obj = ansible_helper.replace_object(name, namespace, body=request_body) + obj_compare(ansible_helper, k8s_obj, params) + break + + def test_remove_resource(self, ansible_helper, resources): + for resource in resources: + name = resource.metadata.name + namespace = resource.metadata.namespace + ansible_helper.delete_object(name, namespace) + k8s_obj = ansible_helper.get_object(name, namespace) + while k8s_obj and k8s_obj.status.phase == 'Terminating': + k8s_obj = ansible_helper.get_object(name, namespace) + assert k8s_obj is None + + @pytest.fixture() + def create_params(self, project, object_name): + create_tasks = list(filter(lambda x: x.get('create'), self.tasks['tasks'])) + parameters = list(map(lambda x: x['create'], create_tasks)) + for i, parameter in enumerate(parameters): + if parameter.get('namespace'): + parameter['namespace'] = project + parameter['name'] = object_name + str(i) + return parameters + + @pytest.fixture() + def patch_params(self, project, object_name): + patch_tasks = list(filter(lambda x: x.get('patch'), self.tasks['tasks'])) + parameters = list(map(lambda x: x['patch'], patch_tasks)) + for parameter in parameters: + if parameter.get('namespace'): + parameter['namespace'] = project + parameter['name'] = object_name + return parameters + + @pytest.fixture() + def replace_params(self, project, object_name): + replace_tasks = list(filter(lambda x: x.get('replace'), self.tasks['tasks'])) + parameters = list(map(lambda x: x['replace'], replace_tasks)) + for parameter in parameters: + if parameter.get('namespace'): + parameter['namespace'] = project + parameter['name'] = object_name + return parameters + + @pytest.fixture() + def resources(self, ansible_helper, create_params): + k8s_objs = [] + for create in create_params: + request_body = ansible_helper.request_body_from_params(create) + namespace = create.get('namespace') + name = create.get('name') + k8s_objs.append((name, namespace, ansible_helper.create_object(namespace, body=request_body))) + + try: + yield list(map(lambda x: x[2], k8s_objs)) + finally: + exceptions = [] + for name, namespace, k8s_obj in k8s_objs: + try: + ansible_helper.delete_object(name, namespace) + except KubernetesException as ex: + # Swallow exception if object is already removed + if ex.value.get('status') != 404: + exceptions.append(ex) + if exceptions: + raise exceptions[0] + + +# BEWARE: Here be disgusting meta-programming hacks +# Basically, for each resource we have examples for, generate a subclass of the Example class +# The type of this subclass will be the resource name +# Then inject that class into globals(), where pytest will be able to pick them up and run them +# If you find a better way to do this, please, please let me know + +def ClassFactory(name): + return type(name, (Example,), {}) + + +for ((apiversion, resource_type), tasks) in get_tasks(): + class_name = 'Test{}{}'.format(apiversion.capitalize(), ''.join(map(str.capitalize, resource_type.split('_')))) + globals()[class_name] = ClassFactory(resource_type) + globals()[class_name]._type = class_name + globals()[class_name].tasks = tasks diff --git a/test/functional/test_k8s_v1_horizontal_pod_autoscaler.py b/test/functional/test_k8s_v1_horizontal_pod_autoscaler.py deleted file mode 100644 index a1976217..00000000 --- a/test/functional/test_k8s_v1_horizontal_pod_autoscaler.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def horizontal_pod_autoscaler(k8s_ansible_helper, create_params): - request_body = k8s_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = k8s_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - k8s_ansible_helper.delete_object(name, namespace) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_horizontal_pod_autoscaler(k8s_ansible_helper, create_params, horizontal_pod_autoscaler, obj_compare): - obj_compare(k8s_ansible_helper, horizontal_pod_autoscaler, create_params) - - -def test_get_horizontal_pod_autoscaler(k8s_ansible_helper, horizontal_pod_autoscaler): - name = horizontal_pod_autoscaler.metadata.name - namespace = horizontal_pod_autoscaler.metadata.namespace - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_remove_horizontal_pod_autoscaler(k8s_ansible_helper, horizontal_pod_autoscaler): - name = horizontal_pod_autoscaler.metadata.name - namespace = horizontal_pod_autoscaler.metadata.namespace - k8s_ansible_helper.delete_object(name, namespace) - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1_namespace.py b/test/functional/test_k8s_v1_namespace.py deleted file mode 100644 index 6b2b0231..00000000 --- a/test/functional/test_k8s_v1_namespace.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -@pytest.fixture() -def create_params(create_tasks, object_name): - parameters = create_tasks['create'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, object_name): - parameters = patch_tasks['patch'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, object_name): - parameters = replace_tasks['replace'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def k8s_namespace(admin_k8s_ansible_helper, create_params): - request_body = admin_k8s_ansible_helper.request_body_from_params(create_params) - name = create_params.get('name') - k8s_obj = admin_k8s_ansible_helper.create_object(None, body=request_body) - - yield k8s_obj - - try: - admin_k8s_ansible_helper.delete_object(name, None) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_namespace(admin_k8s_ansible_helper, create_params, k8s_namespace, obj_compare): - obj_compare(admin_k8s_ansible_helper, k8s_namespace, create_params) - - -def test_get_namespace(admin_k8s_ansible_helper, k8s_namespace): - name = k8s_namespace.metadata.name - k8s_obj = admin_k8s_ansible_helper.get_object(name, None) - assert k8s_obj is not None - - -def test_patch_namespace(admin_k8s_ansible_helper, k8s_namespace, patch_params, obj_compare): - name = patch_params.get('name') - existing_obj = k8s_namespace - updated_obj = copy.deepcopy(existing_obj) - admin_k8s_ansible_helper.object_from_params(patch_params, obj=updated_obj) - match, _ = admin_k8s_ansible_helper.objects_match(existing_obj, updated_obj) - assert not match - new_obj = admin_k8s_ansible_helper.patch_object(name, None, updated_obj) - assert new_obj is not None - obj_compare(admin_k8s_ansible_helper, new_obj, patch_params) - - -def test_replace_namespace(admin_k8s_ansible_helper, k8s_namespace, replace_params, obj_compare): - name = replace_params.get('name') - request_body = admin_k8s_ansible_helper.request_body_from_params(replace_params) - k8s_obj = admin_k8s_ansible_helper.replace_object(name, None, body=request_body) - obj_compare(admin_k8s_ansible_helper, k8s_obj, replace_params) - - -def test_remove_namespace(admin_k8s_ansible_helper, k8s_namespace): - name = k8s_namespace.metadata.name - admin_k8s_ansible_helper.delete_object(name, None) - k8s_obj = admin_k8s_ansible_helper.get_object(name, None) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1_persistent_volume.py b/test/functional/test_k8s_v1_persistent_volume.py deleted file mode 100644 index 436d0440..00000000 --- a/test/functional/test_k8s_v1_persistent_volume.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import pytest - -from openshift.helper.exceptions import KubernetesException - -# TODO: Because of the way tests are run, pvs will always time out. -# need to find a way to mock this out better -@pytest.fixture() -def host_dir(tmpdir_factory): - host_dir = tmpdir_factory.mktemp('volume') - return host_dir.strpath - - -@pytest.fixture() -def create_params(create_tasks, project, object_name, host_dir): - parameters = create_tasks['create'] - parameters.update({ - "name": object_name, - "capacity": { - 'storage': '1Gi', - }, - "access_modes": ['ReadWriteOnce'], - "persistent_volume_reclaim_policy": 'Recycle', - "host_path_path": host_dir - }) - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, project, object_name): - parameters = patch_tasks['patch'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, project, object_name): - parameters = replace_tasks['replace'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def persistent_volume(admin_k8s_ansible_helper, create_params): - request_body = admin_k8s_ansible_helper.request_body_from_params(create_params) - name = create_params.get('name') - k8s_obj = admin_k8s_ansible_helper.create_object(None, body=request_body) - - yield k8s_obj - - try: - admin_k8s_ansible_helper.delete_object(name, None) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404 and ex.value.get('status') != 403: - raise - - -def test_create_persistent_volume(admin_k8s_ansible_helper, create_params, persistent_volume, obj_compare): - obj_compare(admin_k8s_ansible_helper, persistent_volume, create_params) - - -def test_get_persistent_volume(admin_k8s_ansible_helper, persistent_volume): - name = persistent_volume.metadata.name - k8s_obj = admin_k8s_ansible_helper.get_object(name, None) - assert k8s_obj is not None - - -def test_remove_persistent_volume(admin_k8s_ansible_helper, persistent_volume): - name = persistent_volume.metadata.name - admin_k8s_ansible_helper.delete_object(name, None) - k8s_obj = admin_k8s_ansible_helper.get_object(name, None) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1_persistent_volume_claim.py b/test/functional/test_k8s_v1_persistent_volume_claim.py deleted file mode 100644 index b63de67d..00000000 --- a/test/functional/test_k8s_v1_persistent_volume_claim.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -# TODO: Because of the way tests are run, pvcs will always time out. -# need to find a way to mock this out better -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters.update({ - "name": object_name, - "namespace": project, - "access_modes": ['ReadWriteOnce'], - "resources_requests": { - "storage": "1Gi" - } - }) - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, project, object_name): - parameters = patch_tasks['patch'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, project, object_name): - parameters = replace_tasks['replace'] - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def persistent_volume_claim(k8s_ansible_helper, create_params): - request_body = k8s_ansible_helper.request_body_from_params(create_params) - name = create_params.get('name') - namespace = create_params.get('namespace') - k8s_obj = k8s_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - k8s_ansible_helper.delete_object(name, namespace) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404 and ex.value.get('status') != 403: - raise - - -def test_create_persistent_volume_claim(k8s_ansible_helper, create_params, persistent_volume_claim, obj_compare): - obj_compare(k8s_ansible_helper, persistent_volume_claim, create_params) - - -def test_get_persistent_volume_claim(k8s_ansible_helper, persistent_volume_claim): - name = persistent_volume_claim.metadata.name - namespace = persistent_volume_claim.metadata.namespace - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_remove_persistent_volume_claim(k8s_ansible_helper, persistent_volume_claim): - name = persistent_volume_claim.metadata.name - namespace = persistent_volume_claim.metadata.namespace - k8s_ansible_helper.delete_object(name, namespace) - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1_service.py b/test/functional/test_k8s_v1_service.py deleted file mode 100644 index 22ac60e9..00000000 --- a/test/functional/test_k8s_v1_service.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, project, object_name): - parameters = patch_tasks['patch'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, project, object_name): - parameters = replace_tasks['replace'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def service(k8s_ansible_helper, create_params): - request_body = k8s_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = k8s_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - k8s_ansible_helper.delete_object(name, namespace) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_service(k8s_ansible_helper, create_params, service, obj_compare): - obj_compare(k8s_ansible_helper, service, create_params) - - -def test_get_service(k8s_ansible_helper, service): - name = service.metadata.name - namespace = service.metadata.namespace - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_patch_service(k8s_ansible_helper, service, patch_params, obj_compare): - name = patch_params.get('name') - namespace = patch_params.get('namespace') - existing_obj = service - updated_obj = copy.deepcopy(existing_obj) - k8s_ansible_helper.object_from_params(patch_params, obj=updated_obj) - match, _ = k8s_ansible_helper.objects_match(existing_obj, updated_obj) - assert not match - new_obj = k8s_ansible_helper.patch_object(name, namespace, updated_obj) - assert new_obj is not None - obj_compare(k8s_ansible_helper, new_obj, patch_params) - - -def test_replace_service(k8s_ansible_helper, service, replace_params, obj_compare): - name = replace_params.get('name') - namespace = replace_params.get('namespace') - existing = service - request_body = k8s_ansible_helper.request_body_from_params(replace_params) - if existing.spec.cluster_ip: - # can't change the cluster_ip value - request_body['spec']['clusterIP'] = existing.spec.cluster_ip - k8s_obj = k8s_ansible_helper.replace_object(name, namespace, body=request_body) - obj_compare(k8s_ansible_helper, k8s_obj, replace_params) - - -def test_remove_service(k8s_ansible_helper, service): - name = service.metadata.name - namespace = service.metadata.namespace - k8s_ansible_helper.delete_object(name, namespace) - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1beta1_replica_set.py b/test/functional/test_k8s_v1beta1_replica_set.py deleted file mode 100644 index 67f38c32..00000000 --- a/test/functional/test_k8s_v1beta1_replica_set.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replica_set(k8s_ansible_helper, create_params): - request_body = k8s_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = k8s_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - k8s_ansible_helper.delete_object(name, namespace) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_replica_set(k8s_ansible_helper, create_params, replica_set, obj_compare): - obj_compare(k8s_ansible_helper, replica_set, create_params) - - -def test_get_replica_set(k8s_ansible_helper, replica_set): - name = replica_set.metadata.name - namespace = replica_set.metadata.namespace - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_remove_replica_set(k8s_ansible_helper, replica_set): - name = replica_set.metadata.name - namespace = replica_set.metadata.namespace - k8s_ansible_helper.delete_object(name, namespace) - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_k8s_v1beta1_stateful_set.py b/test/functional/test_k8s_v1beta1_stateful_set.py deleted file mode 100644 index 82ad1680..00000000 --- a/test/functional/test_k8s_v1beta1_stateful_set.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import pytest - -from openshift.helper.exceptions import KubernetesException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def stateful_set(k8s_ansible_helper, create_params): - request_body = k8s_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = k8s_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - k8s_ansible_helper.delete_object(name, namespace) - except KubernetesException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -@pytest.mark.version_limit(lowest_version='1.5') -def test_create_stateful_set(k8s_ansible_helper, create_params, stateful_set, obj_compare): - obj_compare(k8s_ansible_helper, stateful_set, create_params) - - -@pytest.mark.version_limit(lowest_version='1.5') -def test_get_stateful_set(k8s_ansible_helper, stateful_set): - name = stateful_set.metadata.name - namespace = stateful_set.metadata.namespace - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -@pytest.mark.version_limit(lowest_version='1.5') -def test_remove_stateful_set(k8s_ansible_helper, stateful_set): - name = stateful_set.metadata.name - namespace = stateful_set.metadata.namespace - k8s_ansible_helper.delete_object(name, namespace) - k8s_obj = k8s_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_openshift_v1_deployment_config.py b/test/functional/test_openshift_v1_deployment_config.py deleted file mode 100644 index e818c467..00000000 --- a/test/functional/test_openshift_v1_deployment_config.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import OpenShiftException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, project, object_name): - parameters = patch_tasks['patch'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, project, object_name): - parameters = replace_tasks['replace'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def deployment_config(openshift_ansible_helper, create_params): - request_body = openshift_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = openshift_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - openshift_ansible_helper.delete_object(name, namespace) - except OpenShiftException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_deployment_config(openshift_ansible_helper, create_params, deployment_config, obj_compare): - obj_compare(openshift_ansible_helper, deployment_config, create_params) - - -def test_get_deployment(openshift_ansible_helper, deployment_config): - name = deployment_config.metadata.name - namespace = deployment_config.metadata.namespace - k8s_obj = openshift_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_patch_deployment(openshift_ansible_helper, deployment_config, patch_params, obj_compare): - name = patch_params['name'] - namespace = patch_params.get('namespace') - existing_obj = deployment_config - updated_obj = copy.deepcopy(existing_obj) - openshift_ansible_helper.object_from_params(patch_params, obj=updated_obj) - match, _ = openshift_ansible_helper.objects_match(existing_obj, updated_obj) - assert not match - new_obj = openshift_ansible_helper.patch_object(name, namespace, updated_obj) - assert new_obj is not None - obj_compare(openshift_ansible_helper, new_obj, patch_params) - - -def test_replace_deployment(openshift_ansible_helper, deployment_config, replace_params, obj_compare): - name = replace_params.get('name') - namespace = replace_params.get('namespace') - request_body = openshift_ansible_helper.request_body_from_params(replace_params) - k8s_obj = openshift_ansible_helper.replace_object(name, namespace, body=request_body) - obj_compare(openshift_ansible_helper, k8s_obj, replace_params) - - -def test_remove_deployment(openshift_ansible_helper, deployment_config): - namespace = deployment_config.metadata.namespace - name = deployment_config.metadata.name - openshift_ansible_helper.delete_object(name, namespace) - k8s_obj = openshift_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/test/functional/test_openshift_v1_project.py b/test/functional/test_openshift_v1_project.py deleted file mode 100644 index 29e50874..00000000 --- a/test/functional/test_openshift_v1_project.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import pytest - -from openshift.helper.exceptions import OpenShiftException - - -@pytest.fixture() -def create_params(create_tasks, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = None - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, object_name): - parameters = patch_tasks['patch'] - parameters['namespace'] = None - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, object_name): - parameters = replace_tasks['replace'] - parameters['namespace'] = None - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def openshift_project(openshift_ansible_helper, create_params): - new_obj = openshift_ansible_helper.object_from_params(create_params) - name = create_params.get('name') - k8s_obj = openshift_ansible_helper.create_project(metadata=new_obj.metadata) - - yield k8s_obj - - try: - openshift_ansible_helper.delete_object(name, None) - except OpenShiftException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404 and ex.value.get('status') != 403: - raise - - -def test_create_project(openshift_ansible_helper, create_params, openshift_project, obj_compare): - obj_compare(openshift_ansible_helper, openshift_project, create_params) - - -def test_get_project(openshift_ansible_helper, openshift_project): - name = openshift_project.metadata.name - k8s_obj = openshift_ansible_helper.get_object(name, None) - assert k8s_obj is not None - - -def test_remove_project(openshift_ansible_helper, openshift_project): - name = openshift_project.metadata.name - openshift_ansible_helper.delete_object(name, None) - k8s_obj = openshift_ansible_helper.get_object(name, None) - assert k8s_obj is None diff --git a/test/functional/test_openshift_v1_route.py b/test/functional/test_openshift_v1_route.py deleted file mode 100644 index ce16fa91..00000000 --- a/test/functional/test_openshift_v1_route.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import copy - -import pytest - -from openshift.helper.exceptions import OpenShiftException - - -@pytest.fixture() -def create_params(create_tasks, project, object_name): - parameters = create_tasks['create'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def patch_params(patch_tasks, project, object_name): - parameters = patch_tasks['patch'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def replace_params(replace_tasks, project, object_name): - parameters = replace_tasks['replace'] - parameters['namespace'] = project - parameters['name'] = object_name - return parameters - - -@pytest.fixture() -def route(openshift_ansible_helper, create_params): - request_body = openshift_ansible_helper.request_body_from_params(create_params) - namespace = create_params.get('namespace') - name = create_params.get('name') - k8s_obj = openshift_ansible_helper.create_object(namespace, body=request_body) - - yield k8s_obj - - try: - openshift_ansible_helper.delete_object(name, namespace) - except OpenShiftException as ex: - # Swallow exception if object is already removed - if ex.value.get('status') != 404: - raise - - -def test_create_route(openshift_ansible_helper, create_params, route, obj_compare): - obj_compare(openshift_ansible_helper, route, create_params) - - -def test_get_route(openshift_ansible_helper, route): - name = route.metadata.name - namespace = route.metadata.namespace - k8s_obj = openshift_ansible_helper.get_object(name, namespace) - assert k8s_obj is not None - - -def test_patch_route(openshift_ansible_helper, route, patch_params, obj_compare): - name = patch_params.get('name') - namespace = patch_params.get('namespace') - existing_obj = route - updated_obj = copy.deepcopy(existing_obj) - openshift_ansible_helper.object_from_params(patch_params, obj=updated_obj) - match, _ = openshift_ansible_helper.objects_match(existing_obj, updated_obj) - assert not match - new_obj = openshift_ansible_helper.patch_object(name, namespace, updated_obj) - assert new_obj is not None - obj_compare(openshift_ansible_helper, new_obj, patch_params) - - -def test_replace_route(openshift_ansible_helper, route, replace_params, obj_compare): - name = replace_params.get('name') - namespace = replace_params.get('namespace') - request_body = openshift_ansible_helper.request_body_from_params(replace_params) - k8s_obj = openshift_ansible_helper.replace_object(name, namespace, body=request_body) - obj_compare(openshift_ansible_helper, k8s_obj, replace_params) - - -def test_remove_route(openshift_ansible_helper, route): - name = route.metadata.name - namespace = route.metadata.namespace - openshift_ansible_helper.delete_object(name, namespace) - k8s_obj = openshift_ansible_helper.get_object(name, namespace) - assert k8s_obj is None diff --git a/tox.ini b/tox.ini index 93f217a2..92a2e712 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,16 @@ [tox] envlist = py{27,35}-{lint} - py{27,35}-openshift{latest,36,15,14,13}-functional + py{27,35}-openshift{latest,37,36,15,14,13}-functional [testenv] usedevelop = True setenv = openshift13: openshift_version=v1.3.3 openshift14: openshift_version=v1.4.1 - openshift15: openshift_verison=v1.5.0-rc.0 - openshift36: openshift_version=v3.6.0-alpha.0 + openshift15: openshift_version=v1.5.1 + openshift36: openshift_version=v3.6.0 + openshift37: openshift_version=v3.7.0-alpha.1 deps = -rrequirements.txt @@ -45,6 +46,7 @@ TEST_SUITE = functional: functional OPENSHIFT_VERSION = latest: openshiftlatest + 3.7: openshift37 3.6: openshift36 1.5: openshift15 1.4: openshift14 @@ -87,4 +89,4 @@ ignore = E123,E124,E127,E128,E201,E202,E203,E211,E221,E222,E225,E226,E228,E227,E # Matches line length set at github.com/ansible/ansible/tox.ini max-line-length = 160 # Not worrying about style in the following -exclude = .tox/*,test/*,openshift/test/*,openshift/client/models/*,openshift/client/apis/*,openshift/client/__init__.py,openshift/__init__.py,venv*/*,_modules/* +exclude = .tox/*,test/*,openshift/test/*,openshift/client/models/*,openshift/client/apis/*,openshift/client/__init__.py,openshift/__init__.py,venv*/*,_modules/*,build/*