From 84b0c742055a18fd38b8978f09e108665cf8cd0a Mon Sep 17 00:00:00 2001 From: Chandan Kumar Date: Sun, 10 Dec 2017 13:36:29 +0530 Subject: [PATCH] Merge intree freezer-api tempest plugin into freezer tempest plugin * It merges the freezer-api tempest plugin into freezer tempest plugin by moving freezer and freezer-api tempest tests in freezer_tempest_plugin/tests/freezer and freezer_tempest_plugin/tests/freezer_api. * clients.py is moved under main root folder. Change-Id: I66cc2507b0bbd9dda9d6279f9b8d74c546d1b0a6 --- freezer_tempest_plugin/clients.py | 24 ++ freezer_tempest_plugin/config.py | 29 ++ freezer_tempest_plugin/plugin.py | 11 +- .../services/freezer_api_client.py | 184 +++++++++++ .../tests/{api => freezer}/__init__.py | 0 .../{scenario => freezer/api}/__init__.py | 0 .../tests/{ => freezer}/api/base.py | 0 .../{ => freezer}/api/test_backup_compress.py | 2 +- .../tests/{ => freezer}/api/test_fs_backup.py | 2 +- .../api/test_metadata_checksum.py | 2 +- .../{ => freezer}/api/test_swift_backup.py | 2 +- .../{ => freezer}/api/test_tests_running.py | 2 +- .../tests/freezer/scenario/__init__.py | 0 .../{ => freezer}/scenario/test_backups.py | 2 +- .../tests/freezer_api/__init__.py | 0 .../tests/freezer_api/api/__init__.py | 0 .../tests/freezer_api/api/base.py | 33 ++ .../tests/freezer_api/api/test_api_actions.py | 219 +++++++++++++ .../tests/freezer_api/api/test_api_backups.py | 300 ++++++++++++++++++ .../tests/freezer_api/api/test_api_clients.py | 96 ++++++ .../tests/freezer_api/api/test_api_jobs.py | 154 +++++++++ .../freezer_api/api/test_api_sessions.py | 131 ++++++++ .../tests/freezer_api/api/test_api_version.py | 110 +++++++ 23 files changed, 1296 insertions(+), 7 deletions(-) create mode 100644 freezer_tempest_plugin/clients.py create mode 100644 freezer_tempest_plugin/services/freezer_api_client.py rename freezer_tempest_plugin/tests/{api => freezer}/__init__.py (100%) rename freezer_tempest_plugin/tests/{scenario => freezer/api}/__init__.py (100%) rename freezer_tempest_plugin/tests/{ => freezer}/api/base.py (100%) rename freezer_tempest_plugin/tests/{ => freezer}/api/test_backup_compress.py (99%) rename freezer_tempest_plugin/tests/{ => freezer}/api/test_fs_backup.py (98%) rename freezer_tempest_plugin/tests/{ => freezer}/api/test_metadata_checksum.py (98%) rename freezer_tempest_plugin/tests/{ => freezer}/api/test_swift_backup.py (98%) rename freezer_tempest_plugin/tests/{ => freezer}/api/test_tests_running.py (93%) create mode 100644 freezer_tempest_plugin/tests/freezer/scenario/__init__.py rename freezer_tempest_plugin/tests/{ => freezer}/scenario/test_backups.py (99%) create mode 100644 freezer_tempest_plugin/tests/freezer_api/__init__.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/__init__.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/base.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_actions.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_backups.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_clients.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_jobs.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_sessions.py create mode 100644 freezer_tempest_plugin/tests/freezer_api/api/test_api_version.py diff --git a/freezer_tempest_plugin/clients.py b/freezer_tempest_plugin/clients.py new file mode 100644 index 0000000..f804d84 --- /dev/null +++ b/freezer_tempest_plugin/clients.py @@ -0,0 +1,24 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from tempest import clients + +from freezer_tempest_plugin.services import freezer_api_client + + +class Manager(clients.Manager): + def __init__(self, credentials=None): + super(Manager, self).__init__(credentials) + self.freezer_api_client = freezer_api_client.FreezerApiClient( + self.auth_provider) diff --git a/freezer_tempest_plugin/config.py b/freezer_tempest_plugin/config.py index e83514b..046b1cd 100644 --- a/freezer_tempest_plugin/config.py +++ b/freezer_tempest_plugin/config.py @@ -19,3 +19,32 @@ service_option = cfg.BoolOpt('freezer', default=True, help="Whether or not freezer is expected to be " "available") + +ServiceAvailableGroup = [ + cfg.BoolOpt("freezer-api", + default=True, + help="Whether or not Freezer API is expected to be available"), +] + +service_available_group = cfg.OptGroup(name="service_available", + title="Available OpenStack Services") + +freezer_api_group = cfg.OptGroup(name="backup", + title="Freezer API Service Options") + +FreezerApiGroup = [ + cfg.StrOpt("region", + default="", + help="The freezer api region name to use. If empty, the value " + "of identity.region is used instead. If no such region " + "is found in the service catalog, the first found one is " + "used."), + cfg.StrOpt("catalog_type", + default="backup", + help="Catalog type of the freezer-api service."), + cfg.StrOpt('endpoint_type', + default='publicURL', + choices=['public', 'admin', 'internal', + 'publicURL', 'adminURL', 'internalURL'], + help="The endpoint type to use for the freezer-api service.") +] diff --git a/freezer_tempest_plugin/plugin.py b/freezer_tempest_plugin/plugin.py index 98be0ea..dfe5bba 100644 --- a/freezer_tempest_plugin/plugin.py +++ b/freezer_tempest_plugin/plugin.py @@ -15,6 +15,7 @@ import os +from tempest import config as tempest_config from tempest.test_discover import plugins from freezer_tempest_plugin import config as freezer_config @@ -29,8 +30,16 @@ class FreezerTempestPlugin(plugins.TempestPlugin): return full_test_dir, base_path def register_opts(self, conf): + tempest_config.register_opt_group( + conf, freezer_config.service_available_group, + freezer_config.ServiceAvailableGroup) + tempest_config.register_opt_group( + conf, freezer_config.freezer_api_group, + freezer_config.FreezerApiGroup) conf.register_opt(freezer_config.service_option, group='service_available') def get_opt_lists(self): - return [('service_available', [freezer_config.service_option])] + return [('service_available', [freezer_config.service_option]), + (freezer_config.freezer_api_group.name, + freezer_config.FreezerApiGroup)] diff --git a/freezer_tempest_plugin/services/freezer_api_client.py b/freezer_tempest_plugin/services/freezer_api_client.py new file mode 100644 index 0000000..eb535c4 --- /dev/null +++ b/freezer_tempest_plugin/services/freezer_api_client.py @@ -0,0 +1,184 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import urllib + +from oslo_serialization import jsonutils as json +from tempest import config +from tempest.lib.common import rest_client + +CONF = config.CONF + + +class FreezerApiClient(rest_client.RestClient): + def __init__(self, auth_provider): + super(FreezerApiClient, self).__init__( + auth_provider, + CONF.backup.catalog_type, + CONF.backup.region or CONF.identity.region, + endpoint_type=CONF.backup.endpoint_type + ) + + def get_version(self): + + resp, response_body = self.get('/') + return resp, response_body + + def get_version_v1(self): + + resp, response_body = self.get('/v1') + return resp, response_body + + def get_version_v2(self): + + resp, response_body = self.get('/v2') + return resp, response_body + + def get_backups(self, backup_id=None, **params): + + if backup_id is None: + uri = '/v1/backups' + if params: + uri += '?%s' % urllib.urlencode(params) + else: + uri = '/v1/backups/' + backup_id + + resp, response_body = self.get(uri) + return resp, json.loads(response_body) + + def post_backups(self, metadata, backup_id=None): + uri = '/v1/backups' + if backup_id is not None: + uri += '/' + backup_id + + request_body = json.dumps(metadata) + resp, response_body = self.post(uri, request_body) + + return resp, json.loads(response_body) + + def delete_backups(self, backup_id): + + uri = '/v1/backups/' + backup_id + resp, response_body = self.delete(uri) + return resp, response_body + + def get_clients(self, client_id=None, **params): + + if client_id is None: + uri = '/v1/clients' + if params: + uri += '?%s' % urllib.urlencode(params) + else: + uri = 'v1/clients/' + client_id + + resp, response_body = self.get(uri) + return resp, response_body + + def post_clients(self, client): + + request_body = json.dumps(client) + resp, response_body = self.post('/v1/clients', request_body) + return resp, json.loads(response_body) + + def delete_clients(self, client_id): + + uri = '/v1/clients/' + client_id + resp, response_body = self.delete(uri) + return resp, response_body + + def get_jobs(self, job_id=None, **params): + + if job_id is None: + uri = '/v1/jobs' + if params: + uri += '?%s' % urllib.urlencode(params) + else: + uri = '/v1/jobs/' + job_id + + resp, response_body = self.get(uri) + return resp, response_body + + def post_jobs(self, job): + + request_body = json.dumps(job) + resp, response_body = self.post('/v1/jobs', request_body) + return resp, json.loads(response_body) + + def delete_jobs(self, job_id): + + uri = '/v1/jobs/' + job_id + resp, response_body = self.delete(uri) + return resp, response_body + + def get_actions(self, action_id=None, **params): + + if action_id is None: + uri = '/v1/actions' + if params: + uri += '?%s' % urllib.urlencode(params) + else: + uri = '/v1/actions/' + action_id + + resp, response_body = self.get(uri) + return resp, response_body + + def post_actions(self, action, action_id=None): + + request_body = json.dumps(action) + + if action_id is None: + uri = '/v1/actions' + else: + uri = '/v1/actions/' + action_id + + resp, response_body = self.post(uri, request_body) + return resp, json.loads(response_body) + + def patch_actions(self, action, action_id): + + request_body = json.dumps(action) + + uri = '/v1/actions/' + action_id + resp, response_body = self.patch(uri, request_body) + return resp, json.loads(response_body) + + def delete_actions(self, id): + + uri = '/v1/actions/' + id + resp, response_body = self.delete(uri) + return resp, response_body + + def get_sessions(self, session_id=None, **params): + + if session_id is None: + uri = '/v1/sessions' + if params: + uri += '?%s' % urllib.urlencode(params) + else: + uri = 'v1/sessions/' + session_id + + resp, response_body = self.get(uri) + return resp, response_body + + def post_sessions(self, session): + + request_body = json.dumps(session) + resp, response_body = self.post('/v1/sessions', request_body) + return resp, json.loads(response_body) + + def delete_sessions(self, session_id): + + uri = '/v1/sessions/' + session_id + resp, response_body = self.delete(uri) + return resp, response_body diff --git a/freezer_tempest_plugin/tests/api/__init__.py b/freezer_tempest_plugin/tests/freezer/__init__.py similarity index 100% rename from freezer_tempest_plugin/tests/api/__init__.py rename to freezer_tempest_plugin/tests/freezer/__init__.py diff --git a/freezer_tempest_plugin/tests/scenario/__init__.py b/freezer_tempest_plugin/tests/freezer/api/__init__.py similarity index 100% rename from freezer_tempest_plugin/tests/scenario/__init__.py rename to freezer_tempest_plugin/tests/freezer/api/__init__.py diff --git a/freezer_tempest_plugin/tests/api/base.py b/freezer_tempest_plugin/tests/freezer/api/base.py similarity index 100% rename from freezer_tempest_plugin/tests/api/base.py rename to freezer_tempest_plugin/tests/freezer/api/base.py diff --git a/freezer_tempest_plugin/tests/api/test_backup_compress.py b/freezer_tempest_plugin/tests/freezer/api/test_backup_compress.py similarity index 99% rename from freezer_tempest_plugin/tests/api/test_backup_compress.py rename to freezer_tempest_plugin/tests/freezer/api/test_backup_compress.py index e5b2a51..2a2b910 100644 --- a/freezer_tempest_plugin/tests/api/test_backup_compress.py +++ b/freezer_tempest_plugin/tests/freezer/api/test_backup_compress.py @@ -19,7 +19,7 @@ import subprocess from tempest.lib import decorators from freezer_tempest_plugin import common -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base class TestFreezerCompressGzip(base.BaseFreezerTest): diff --git a/freezer_tempest_plugin/tests/api/test_fs_backup.py b/freezer_tempest_plugin/tests/freezer/api/test_fs_backup.py similarity index 98% rename from freezer_tempest_plugin/tests/api/test_fs_backup.py rename to freezer_tempest_plugin/tests/freezer/api/test_fs_backup.py index a3d3e10..4a5b856 100644 --- a/freezer_tempest_plugin/tests/api/test_fs_backup.py +++ b/freezer_tempest_plugin/tests/freezer/api/test_fs_backup.py @@ -18,7 +18,7 @@ import shutil from oslo_utils import uuidutils from tempest.lib import decorators -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base class TestFreezerFSBackup(base.BaseFreezerTest): diff --git a/freezer_tempest_plugin/tests/api/test_metadata_checksum.py b/freezer_tempest_plugin/tests/freezer/api/test_metadata_checksum.py similarity index 98% rename from freezer_tempest_plugin/tests/api/test_metadata_checksum.py rename to freezer_tempest_plugin/tests/freezer/api/test_metadata_checksum.py index 26eb5f8..4323338 100644 --- a/freezer_tempest_plugin/tests/api/test_metadata_checksum.py +++ b/freezer_tempest_plugin/tests/freezer/api/test_metadata_checksum.py @@ -16,7 +16,7 @@ import subprocess from tempest.lib import decorators from freezer_tempest_plugin import common -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base class TestFreezerMetadataChecksum(base.BaseFreezerTest): diff --git a/freezer_tempest_plugin/tests/api/test_swift_backup.py b/freezer_tempest_plugin/tests/freezer/api/test_swift_backup.py similarity index 98% rename from freezer_tempest_plugin/tests/api/test_swift_backup.py rename to freezer_tempest_plugin/tests/freezer/api/test_swift_backup.py index c2207c1..bd82823 100644 --- a/freezer_tempest_plugin/tests/api/test_swift_backup.py +++ b/freezer_tempest_plugin/tests/freezer/api/test_swift_backup.py @@ -18,7 +18,7 @@ import shutil from oslo_utils import uuidutils from tempest.lib import decorators -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base class TestFreezerSwiftBackup(base.BaseFreezerTest): diff --git a/freezer_tempest_plugin/tests/api/test_tests_running.py b/freezer_tempest_plugin/tests/freezer/api/test_tests_running.py similarity index 93% rename from freezer_tempest_plugin/tests/api/test_tests_running.py rename to freezer_tempest_plugin/tests/freezer/api/test_tests_running.py index 9a91480..c6f97bd 100644 --- a/freezer_tempest_plugin/tests/api/test_tests_running.py +++ b/freezer_tempest_plugin/tests/freezer/api/test_tests_running.py @@ -14,7 +14,7 @@ from tempest.lib import decorators -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base class TestFreezerTestsRunning(base.BaseFreezerTest): diff --git a/freezer_tempest_plugin/tests/freezer/scenario/__init__.py b/freezer_tempest_plugin/tests/freezer/scenario/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/freezer_tempest_plugin/tests/scenario/test_backups.py b/freezer_tempest_plugin/tests/freezer/scenario/test_backups.py similarity index 99% rename from freezer_tempest_plugin/tests/scenario/test_backups.py rename to freezer_tempest_plugin/tests/freezer/scenario/test_backups.py index 86f6cd2..9344f1c 100644 --- a/freezer_tempest_plugin/tests/scenario/test_backups.py +++ b/freezer_tempest_plugin/tests/freezer/scenario/test_backups.py @@ -22,7 +22,7 @@ import time from tempest.lib.cli import base as cli_base from tempest.lib.cli import output_parser -from freezer_tempest_plugin.tests.api import base +from freezer_tempest_plugin.tests.freezer.api import base JOB_TABLE_RESULT_COLUMN = 3 diff --git a/freezer_tempest_plugin/tests/freezer_api/__init__.py b/freezer_tempest_plugin/tests/freezer_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/freezer_tempest_plugin/tests/freezer_api/api/__init__.py b/freezer_tempest_plugin/tests/freezer_api/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/freezer_tempest_plugin/tests/freezer_api/api/base.py b/freezer_tempest_plugin/tests/freezer_api/api/base.py new file mode 100644 index 0000000..3187a56 --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/base.py @@ -0,0 +1,33 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from tempest import config +from tempest import test + +from freezer_tempest_plugin import clients + +CONF = config.CONF + + +class BaseFreezerApiTest(test.BaseTestCase): + """Base test case class for all Freezer API tests.""" + + credentials = ['primary'] + + client_manager = clients.Manager + + @classmethod + def setup_clients(cls): + super(BaseFreezerApiTest, cls).setup_clients() + cls.freezer_api_client = cls.os_primary.freezer_api_client diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_actions.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_actions.py new file mode 100644 index 0000000..ee5ac45 --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_actions.py @@ -0,0 +1,219 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from tempest.lib import decorators +from tempest.lib import exceptions + +from freezer_tempest_plugin.tests.freezer_api.api import base + + +class TestFreezerApiActions(base.BaseFreezerApiTest): + @classmethod + def resource_setup(cls): + super(TestFreezerApiActions, cls).resource_setup() + + @classmethod + def resource_cleanup(cls): + super(TestFreezerApiActions, cls).resource_cleanup() + + @decorators.attr(type="gate") + def test_api_actions(self): + resp, response_body = self.freezer_api_client.get_actions() + self.assertEqual(200, resp.status) + + resp_body_json = json.loads(response_body) + self.assertIn('actions', resp_body_json) + actions = resp_body_json['actions'] + self.assertEqual(actions, []) + + @decorators.attr(type="gate") + def test_api_actions_get_limit(self): + # limits > 0 should return successfully + for valid_limit in [2, 1]: + resp, body = self.freezer_api_client.get_actions(limit=valid_limit) + self.assertEqual(200, resp.status) + + # limits <= 0 should raise a bad request error + for bad_limit in [0, -1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_actions, + limit=bad_limit) + + @decorators.attr(type="gate") + def test_api_actions_get_offset(self): + # offsets >= 0 should return 200 + for valid_offset in [1, 0]: + resp, body = self.freezer_api_client.get_actions( + offset=valid_offset) + self.assertEqual(200, resp.status) + + # offsets < 0 should return 400 + for bad_offset in [-1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_actions, + offset=bad_offset) + + @decorators.attr(type="gate") + def test_api_actions_post(self): + + action = { + 'freezer_action': + { + 'actions': 'backup', + 'mode': 'fs', + 'src_file': '/dev/null', + 'backup_name': 'test freezer api actions', + 'container': 'test_freezer_api_actions_container', + 'max_backup_level': 1, + 'always_backup_level': 0, + 'no_incremental': True, + 'encrypt_pass_file': '/dev/null', + 'log_file': '/dev/null', + 'hostname': False, + 'max_cpu_priority': False + } + } + + # Create the action with POST + resp, response_body = self.freezer_api_client.post_actions(action) + self.assertEqual(201, resp.status) + + self.assertIn('action_id', response_body) + action_id = response_body['action_id'] + + # Check that the action has the correct values + resp, response_body = self.freezer_api_client.get_actions(action_id) + self.assertEqual(200, resp.status) + + resp_body_json = json.loads(response_body) + freezer_action_json = resp_body_json['freezer_action'] + + self.assertIn('backup_name', freezer_action_json) + backup_name = freezer_action_json['backup_name'] + self.assertEqual('test freezer api actions', backup_name) + + self.assertIn('container', freezer_action_json) + container = freezer_action_json['container'] + self.assertEqual('test_freezer_api_actions_container', container) + + self.assertIn('no_incremental', freezer_action_json) + no_incremental = freezer_action_json['no_incremental'] + self.assertEqual(True, no_incremental) + + self.assertIn('max_backup_level', freezer_action_json) + max_backup_level = freezer_action_json['max_backup_level'] + self.assertEqual(1, max_backup_level) + + self.assertIn('hostname', freezer_action_json) + hostname = freezer_action_json['hostname'] + self.assertEqual(False, hostname) + + self.assertIn('_version', response_body) + _version = resp_body_json['_version'] + self.assertEqual(1, _version) + + self.assertIn('actions', freezer_action_json) + actions = freezer_action_json['actions'] + self.assertEqual('backup', actions) + + self.assertIn('src_file', freezer_action_json) + src_file = freezer_action_json['src_file'] + self.assertEqual('/dev/null', src_file) + + self.assertIn('always_backup_level', freezer_action_json) + always_backup_level = freezer_action_json['always_backup_level'] + self.assertEqual(0, always_backup_level) + + self.assertIn('mode', freezer_action_json) + mode = freezer_action_json['mode'] + self.assertEqual('fs', mode) + + self.assertIn('encrypt_pass_file', freezer_action_json) + encrypt_pass_file = freezer_action_json['encrypt_pass_file'] + self.assertEqual('/dev/null', encrypt_pass_file) + + self.assertIn('max_cpu_priority', freezer_action_json) + max_cpu_priority = freezer_action_json['max_cpu_priority'] + self.assertEqual(False, max_cpu_priority) + + self.assertIn('user_id', response_body) + + self.assertIn('log_file', freezer_action_json) + log_file = freezer_action_json['log_file'] + self.assertEqual('/dev/null', log_file) + + self.assertIn('action_id', response_body) + action_id_in_resp_body = resp_body_json['action_id'] + self.assertEqual(action_id, action_id_in_resp_body) + + # Update the action backup_name with POST + action['freezer_action']['backup_name'] = \ + 'test freezer api actions update with post' + + resp, response_body = self.freezer_api_client.post_actions( + action, action_id) + self.assertEqual(201, resp.status) + + self.assertIn('version', response_body) + version = response_body['version'] + self.assertEqual(2, version) + + self.assertIn('action_id', response_body) + action_id_in_resp_body = response_body['action_id'] + self.assertEqual(action_id, action_id_in_resp_body) + + resp, response_body = self.freezer_api_client.get_actions(action_id) + self.assertEqual(200, resp.status) + + resp_body_json = json.loads(response_body) + freezer_action_json = resp_body_json['freezer_action'] + + self.assertIn('backup_name', freezer_action_json) + backup_name = freezer_action_json['backup_name'] + self.assertEqual('test freezer api actions update with post', + backup_name) + + # Update the action backup_name with PATCH + action['freezer_action']['backup_name'] = \ + 'test freezer api actions update with patch' + + resp, response_body = self.freezer_api_client.patch_actions( + action, action_id) + self.assertEqual(200, resp.status) + + self.assertIn('version', response_body) + version = response_body['version'] + self.assertEqual(3, version) + + self.assertIn('action_id', response_body) + action_id_in_resp_body = response_body['action_id'] + self.assertEqual(action_id, action_id_in_resp_body) + + resp, response_body = self.freezer_api_client.get_actions(action_id) + self.assertEqual(200, resp.status) + + resp_body_json = json.loads(response_body) + freezer_action_json = resp_body_json['freezer_action'] + + self.assertIn('backup_name', freezer_action_json) + backup_name = freezer_action_json['backup_name'] + self.assertEqual('test freezer api actions update with patch', + backup_name) + + # Delete the action + resp, response_body = self.freezer_api_client.delete_actions( + action_id) + self.assertEqual(204, resp.status) diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_backups.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_backups.py new file mode 100644 index 0000000..f07f57b --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_backups.py @@ -0,0 +1,300 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +import tempest +from tempest.lib import decorators + +from freezer_tempest_plugin.tests.freezer_api.api import base + + +class TestFreezerApiBackups(base.BaseFreezerApiTest): + credentials = ['primary', 'alt'] + + @decorators.attr(type="gate") + def test_api_backups_list(self): + for i in range(1, 4): + self._create_temporary_backup( + self._build_metadata("test_freezer_backups_" + str(i))) + + resp, response_body = self.freezer_api_client.get_backups() + self.assertEqual(200, resp.status) + + self.assertIn('backups', response_body) + backups = response_body['backups'] + + self.assertEqual(3, len(backups)) + + backup_names = [b['backup_metadata']['backup_name'] for b in backups] + for i in range(1, 4): + self.assertIn("test_freezer_backups_" + str(i), backup_names) + + @decorators.attr(type="gate") + def test_api_backups_list_other_users_backups(self): + # Test if it is not possible to list backups + # from a different user + self._create_temporary_backup( + self._build_metadata("test_freezer_backups")) + + # Switching to alt_user here + resp, response_body = self.os_alt.freezer_api_client.get_backups() + + self.assertEqual(200, resp.status) + self.assertEmpty(response_body['backups']) + + @decorators.attr(type="gate") + def test_api_backups_list_empty(self): + resp, response_body = self.freezer_api_client.get_backups() + self.assertEqual(200, resp.status) + + self.assertEmpty(response_body['backups']) + + @decorators.attr(type="gate") + def test_api_backups_list_limit(self): + for i in range(1, 9): + self._create_temporary_backup( + self._build_metadata("test_freezer_backups_" + str(i))) + + resp, response_body = self.freezer_api_client.get_backups(limit=5) + self.assertEqual(200, resp.status) + + self.assertIn('backups', response_body) + backups = response_body['backups'] + self.assertEqual(5, len(backups)) + + # limits <= 0 should return an error (bad request) + for bad_limit in [0, -1, -2]: + self.assertRaises(tempest.lib.exceptions.BadRequest, + self.freezer_api_client.get_actions, + limit=bad_limit) + + @decorators.attr(type="gate") + def test_api_backups_list_offset(self): + for i in range(1, 9): + self._create_temporary_backup( + self._build_metadata("test_freezer_backups_" + str(i))) + + # valid offsets should return the correct number of entries + resp, response_body = self.freezer_api_client.get_backups(offset=0) + self.assertEqual(200, resp.status) + self.assertEqual(8, len(response_body['backups'])) + + resp, response_body = self.freezer_api_client.get_backups(offset=5) + self.assertEqual(200, resp.status) + self.assertEqual(3, len(response_body['backups'])) + + resp, response_body = self.freezer_api_client.get_backups(offset=8) + self.assertEqual(200, resp.status) + self.assertEqual(0, len(response_body['backups'])) + + # an offset greater than the number of entries should successfully + # return no entries + resp, response_body = self.freezer_api_client.get_backups(offset=10) + self.assertEqual(200, resp.status) + self.assertEqual(0, len(response_body['backups'])) + + # negative offsets should raise an error + self.assertRaises(tempest.lib.exceptions.BadRequest, + self.freezer_api_client.get_backups, offset=-1) + + self.assertRaises(tempest.lib.exceptions.BadRequest, + self.freezer_api_client.get_backups, offset=-2) + + @decorators.attr(type="gate") + def test_api_backups_list_limit_offset(self): + """ Test pagination by grabbing the backups in two steps and + comparing to the list of all backups. + """ + for i in range(1, 9): + self._create_temporary_backup( + self._build_metadata("test_freezer_backups_" + str(i))) + + resp, response_body = self.freezer_api_client.get_backups(limit=5) + self.assertEqual(200, resp.status) + + self.assertIn('backups', response_body) + first_5_backups = response_body['backups'] + self.assertEqual(5, len(first_5_backups)) + + resp, response_body = self.freezer_api_client.get_backups(limit=3, + offset=5) + second_3_backups = response_body['backups'] + self.assertEqual(3, len(second_3_backups)) + + resp, response_body = self.freezer_api_client.get_backups() + all_backups = response_body['backups'] + + self.assertEqual(len(all_backups), + len(first_5_backups + second_3_backups)) + self.assertEqual(all_backups, first_5_backups + second_3_backups) + + @decorators.attr(type="gate") + def test_api_backups_post(self): + metadata = self._build_metadata("test_freezer_backups") + backup_id = self._create_temporary_backup(metadata) + + resp, response_body = self._workaround_get_backup(backup_id) + + expected = self._build_expected_data(backup_id, metadata) + + # backup_id is generated automatically, we can't know it + del(response_body['backup_id']) + + self.assertEqual(200, resp.status) + self.assertEqual(expected, response_body) + + @decorators.attr(type="gate") + def test_api_backups_post_without_content_type(self): + """ Test the backup endpoint without content-type=application/json. + + It's expected to work regardless of whether content-type is set or not. + """ + metadata = self._build_metadata("test_freezer_backups") + + uri = '/v1/backups' + request_body = json.dumps(metadata) + + # Passing in an empty dict for headers to avoid automatically + # generating headers + resp, response_body = self.freezer_api_client.post(uri, request_body, + headers={}) + + self.assertEqual(resp.status, 201) + + @decorators.attr(type="gate") + def test_api_backups_post_incomplete(self): + metadata = self._build_metadata("test_freezer_backups") + del (metadata['container']) + + self.assertRaises(tempest.lib.exceptions.BadRequest, + self.freezer_api_client.post_backups, metadata) + + @decorators.attr(type="gate") + def test_api_backups_post_minimal(self): + metadata = { + "curr_backup_level": 0, + "container": "test_freezer_api_backups_container", + "hostname": "localhost", + "backup_name": "test_freezer_backups", + "time_stamp": 1459349846, + } + + backup_id = self._create_temporary_backup(metadata) + resp, response_body = self._workaround_get_backup(backup_id) + + expected = self._build_expected_data(backup_id, metadata) + + # backup_id is generated automatically, we can't know it + del(response_body['backup_id']) + + self.assertEqual(200, resp.status) + self.assertEqual(expected, response_body) + + @decorators.attr(type="gate") + def test_api_backups_delete(self): + metadata = self._build_metadata("test_freezer_backups") + backup_id = self._create_temporary_backup(metadata) + + self.freezer_api_client.delete_backups(backup_id) + + resp, response_body = self.freezer_api_client.get_backups() + self.assertEqual(0, len(response_body['backups'])) + + @decorators.attr(type="gate") + def test_api_backups_delete_other_users_backups(self): + metadata = self._build_metadata("test_freezer_backups") + backup_id = self._create_temporary_backup(metadata) + + # Switching user + resp, response_body = self.os_alt.freezer_api_client.delete_backups( + backup_id) + self.assertEqual('204', resp['status']) + self.assertEmpty(response_body) + + # Switching back to original user + resp, response_body = self.freezer_api_client.get_backups() + self.assertEqual(1, len(response_body['backups'])) + + def _build_expected_data(self, backup_id, metadata): + return { + 'user_name': self.os_primary.credentials.username, + 'user_id': self.os_primary.credentials.user_id, + 'backup_metadata': metadata + } + + def _build_metadata(self, backup_name): + return { + "action": "backup", + "always_level": "", + "backup_media": "fs", + "client_id": "freezer", + "client_version": "1.2.18", + "container_segments": "", + "curr_backup_level": 0, + "dry_run": "", + "log_file": "", + "job_id": "76cf6739ca2e4dc58b2215632c2a0b49", + "os_auth_version": "", + "path_to_backup": "/dev/null", + "proxy": "", + "ssh_host": "", + "ssh_key": "", + "ssh_port": 22, + "ssh_username": "", + "storage": "swift", + "container": "test_freezer_api_backups_container", + "hostname": "localhost", + "backup_name": backup_name, + "time_stamp": 1459349846, + "level": 1, + "max_level": 14, + "mode": "fs", + "fs_real_path": "/dev/null", + "vol_snap_path": "", + "total_broken_links": 1, + "total_fs_files": 100, + "total_directories": 100, + "backup_size_uncompressed": 10000, + "backup_size_compressed": 1000, + "compression": "gzip", + "encrypted": False, + "client_os": "linux2", + "broken_links": [], + "excluded_files": [], + "cli": "freezer", + "version": "1.0" + } + + def _create_temporary_backup(self, metadata): + resp, response_body = self.freezer_api_client.post_backups(metadata) + + self.assertEqual('201', resp['status']) + + self.assertIn('backup_id', response_body) + backup_id = response_body['backup_id'] + + self.addCleanup(self.freezer_api_client.delete_backups, backup_id) + + return backup_id + + def _workaround_get_backup(self, backup_id): + # TODO(JonasPf): Use the following line, once this bug is fixed: + # https://bugs.launchpad.net/freezer/+bug/1564649 + # resp, response_body = self.freezer_api_client.get_backups(backup_id) + resp, response_body = self.freezer_api_client.get_backups() + + result = next((b for b in response_body['backups'] if + b['backup_id'] == backup_id)) + return resp, result diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_clients.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_clients.py new file mode 100644 index 0000000..d075755 --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_clients.py @@ -0,0 +1,96 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json +import time + +from tempest.lib import decorators +from tempest.lib import exceptions + +from freezer_tempest_plugin.tests.freezer_api.api import base + + +class TestFreezerApiClients(base.BaseFreezerApiTest): + @classmethod + def resource_setup(cls): + super(TestFreezerApiClients, cls).resource_setup() + + @classmethod + def resource_cleanup(cls): + super(TestFreezerApiClients, cls).resource_cleanup() + + @decorators.attr(type="gate") + def test_api_clients(self): + + resp, response_body = self.freezer_api_client.get_clients() + self.assertEqual(200, resp.status) + + response_body_json = json.loads(response_body) + self.assertIn('clients', response_body_json) + clients = response_body_json['clients'] + self.assertEmpty(clients) + + @decorators.attr(type="gate") + def test_api_clients_get_limit(self): + # limits > 0 should return successfully + for valid_limit in [2, 1]: + resp, body = self.freezer_api_client.get_clients(limit=valid_limit) + self.assertEqual(200, resp.status) + + # limits <= 0 should raise a bad request error + for bad_limit in [0, -1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_clients, + limit=bad_limit) + + @decorators.attr(type="gate") + def test_api_clients_get_offset(self): + # offsets >= 0 should return 200 + for valid_offset in [1, 0]: + resp, body = self.freezer_api_client.get_clients( + offset=valid_offset) + self.assertEqual(200, resp.status) + + # offsets < 0 should return 400 + for bad_offset in [-1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_clients, + offset=bad_offset) + + @decorators.attr(type="gate") + def test_api_clients_post(self): + client = {'client_id': 'test-client-id', + 'hostname': 'test-host-name', + 'description': 'a test client', + 'uuid': 'test-client-uuid'} + + # Create the client with POST + resp, response_body = self.freezer_api_client.post_clients(client) + self.assertEqual(201, resp.status) + + self.assertIn('client_id', response_body) + client_id = response_body['client_id'] + + # Check that the client has the correct values + + # Give the DB some time to catch up + time.sleep(5) + + resp, response_body = self.freezer_api_client.get_clients(client_id) + self.assertEqual(200, resp.status) + + # Delete the client + resp, response_body = self.freezer_api_client.delete_clients( + client_id) + self.assertEqual(204, resp.status) diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_jobs.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_jobs.py new file mode 100644 index 0000000..e08a33e --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_jobs.py @@ -0,0 +1,154 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from tempest.lib import decorators +from tempest.lib import exceptions + +from freezer_tempest_plugin.tests.freezer_api.api import base + +fake_job = { + "job_actions": + [ + { + "freezer_action": + { + "action": "backup", + "mode": "fs", + "src_file": "/home/tylerdurden/project_mayhem", + "backup_name": "project_mayhem_backup", + "container": "my_backup_container", + }, + "exit_status": "success", + "max_retries": 1, + "max_retries_interval": 1, + "mandatory": True + } + ], + "job_schedule": + { + "time_created": 1234, + "time_started": 1234, + "time_ended": 0, + "status": "stop", + "schedule_date": "2015-06-02T16:20:00", + "schedule_month": "1-6, 9-12", + "schedule_day": "mon, wed, fri", + "schedule_hour": "03", + "schedule_minute": "25", + }, + "job_id": "blabla", + "client_id": "01b0f00a-4ce2-11e6-beb8-9e71128cae77_myhost.mydomain.mytld", + "user_id": "blabla", + "description": "scheduled one shot" +} + + +class TestFreezerApiJobs(base.BaseFreezerApiTest): + @classmethod + def resource_setup(cls): + super(TestFreezerApiJobs, cls).resource_setup() + + @classmethod + def resource_cleanup(cls): + super(TestFreezerApiJobs, cls).resource_cleanup() + + @decorators.attr(type="gate") + def test_api_jobs(self): + + resp, response_body = self.freezer_api_client.get_jobs() + self.assertEqual(200, resp.status) + + response_body_json = json.loads(response_body) + self.assertIn('jobs', response_body_json) + jobs = response_body_json['jobs'] + self.assertEmpty(jobs) + + @decorators.attr(type="gate") + def test_api_jobs_get_limit(self): + # limits > 0 should return successfully + for valid_limit in [2, 1]: + resp, body = self.freezer_api_client.get_jobs(limit=valid_limit) + self.assertEqual(200, resp.status) + + # limits <= 0 should raise a bad request error + for bad_limit in [0, -1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_jobs, + limit=bad_limit) + + @decorators.attr(type="gate") + def test_api_jobs_get_offset(self): + # offsets >= 0 should return 200 + for valid_offset in [1, 0]: + resp, body = self.freezer_api_client.get_jobs(offset=valid_offset) + self.assertEqual(200, resp.status) + + # offsets < 0 should return 400 + for bad_offset in [-1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_jobs, + offset=bad_offset) + + @decorators.attr(type="gate") + def test_api_jobs_post(self): + + # Create the job with POST + resp, response_body = self.freezer_api_client.post_jobs(fake_job) + self.assertEqual(201, resp.status) + + self.assertIn('job_id', response_body) + job_id = response_body['job_id'] + + # Check that the job has the correct values + resp, response_body = self.freezer_api_client.get_jobs(job_id) + self.assertEqual(200, resp.status) + + # Delete the job + resp, response_body = self.freezer_api_client.delete_jobs( + job_id) + self.assertEqual(204, resp.status) + + @decorators.attr(type="gate") + def test_api_jobs_with_invalid_client_project_id_fail(self): + """Ensure that a job submitted with a bad client_id project id fails""" + fake_bad_job = fake_job + fake_bad_job['client_id'] = 'bad%project$id_host.domain.tld' + + # Create the job with POST + self.assertRaises(exceptions.BadRequest, + lambda: self.freezer_api_client.post_jobs( + fake_bad_job)) + + @decorators.attr(type="gate") + def test_api_jobs_with_invalid_client_host_fail(self): + """Ensure that a job submitted with a bad client_id hostname fails""" + fake_bad_job = fake_job + fake_bad_job['client_id'] = ("01b0f00a-4ce2-11e6-beb8-9e71128cae77" + "_bad_hostname.bad/domain.b") + + # Create the job with POST + self.assertRaises(exceptions.BadRequest, + lambda: self.freezer_api_client.post_jobs( + fake_bad_job)) + + def test_api_jobs_with_only_fqdn_succeeds(self): + """Ensure that a job submitted with only an FQDN succeeds""" + fqdn_only_job = fake_job + fqdn_only_job['client_id'] = 'padawan-ccp-c1-m1-mgmt' + + # Attempt to post the job, should succeed + resp, response_body = self.freezer_api_client.post_jobs(fqdn_only_job) + self.assertEqual(201, resp.status) diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_sessions.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_sessions.py new file mode 100644 index 0000000..c8e80e0 --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_sessions.py @@ -0,0 +1,131 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from tempest.lib import decorators +from tempest.lib import exceptions + +from freezer_tempest_plugin.tests.freezer_api.api import base + + +class TestFreezerApiSessions(base.BaseFreezerApiTest): + @classmethod + def resource_setup(cls): + super(TestFreezerApiSessions, cls).resource_setup() + + @classmethod + def resource_cleanup(cls): + super(TestFreezerApiSessions, cls).resource_cleanup() + + @decorators.attr(type="gate") + def test_api_sessions(self): + + resp, response_body = self.freezer_api_client.get_sessions() + self.assertEqual(200, resp.status) + + response_body_json = json.loads(response_body) + self.assertIn('sessions', response_body_json) + sessions = response_body_json['sessions'] + self.assertEmpty(sessions) + + @decorators.attr(type="gate") + def test_api_sessions_get_limit(self): + # limits > 0 should return successfully + for valid_limit in [2, 1]: + resp, body = self.freezer_api_client.get_sessions( + limit=valid_limit) + self.assertEqual(200, resp.status) + + # limits <= 0 should raise a bad request error + for bad_limit in [0, -1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_sessions, + limit=bad_limit) + + @decorators.attr(type="gate") + def test_api_sessions_get_offset(self): + # offsets >= 0 should return 200 + for valid_offset in [1, 0]: + resp, body = self.freezer_api_client.get_sessions( + offset=valid_offset) + self.assertEqual(200, resp.status) + + # offsets < 0 should return 400 + for bad_offset in [-1, -2]: + self.assertRaises(exceptions.BadRequest, + self.freezer_api_client.get_sessions, + offset=bad_offset) + + @decorators.attr(type="gate") + def test_api_sessions_post(self): + + session = { + "session_id": "test-session", + "session_tag": 1, + "description": "a test session", + "hold_off": 5, + "schedule": { + "time_created": 1234, + "time_started": 1234, + "time_ended": 0, + "status": "stop", + "schedule_date": "2015-06-02T16:20:00", + "schedule_month": "1-6, 9-12", + "schedule_day": "mon, wed, fri", + "schedule_hour": "03", + "schedule_minute": "25", + }, + "jobs": [ + { + 'job_id_1': { + "client_id": "client-id-1", + "status": "stop", + "result": "success", + "time_started": 1234, + "time_ended": 1234 + }, + 'job_id_2': { + "client_id": "client-id-1", + "status": "stop", + "result": "success", + "time_started": 1234, + "time_ended": 1234, + } + } + ], + "time_start": 1234, + "time_end": 1234, + "time_started": 1234, + "time_ended": 1234, + "status": "completed", + "result": "success", + "user_id": "user-id-1" + } + + # Create the session with POST + resp, response_body = self.freezer_api_client.post_sessions(session) + self.assertEqual(201, resp.status) + + self.assertIn('session_id', response_body) + session_id = response_body['session_id'] + + # Check that the session has the correct values + resp, response_body = self.freezer_api_client.get_sessions(session_id) + self.assertEqual(200, resp.status) + + # Delete the session + resp, response_body = self.freezer_api_client.delete_sessions( + session_id) + self.assertEqual(204, resp.status) diff --git a/freezer_tempest_plugin/tests/freezer_api/api/test_api_version.py b/freezer_tempest_plugin/tests/freezer_api/api/test_api_version.py new file mode 100644 index 0000000..51e4754 --- /dev/null +++ b/freezer_tempest_plugin/tests/freezer_api/api/test_api_version.py @@ -0,0 +1,110 @@ +# (C) Copyright 2016 Hewlett Packard Enterprise Development Company LP +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from tempest.lib import decorators + +from freezer_tempest_plugin.tests.freezer_api.api import base + + +class TestFreezerApiVersion(base.BaseFreezerApiTest): + @classmethod + def resource_setup(cls): + super(TestFreezerApiVersion, cls).resource_setup() + + @classmethod + def resource_cleanup(cls): + super(TestFreezerApiVersion, cls).resource_cleanup() + + @decorators.attr(type="gate") + def test_api_version(self): + resp, response_body = self.freezer_api_client.get_version() + self.assertEqual(300, resp.status) + + resp_body_json = json.loads(response_body) + self.assertIn('versions', resp_body_json) + current_version = resp_body_json['versions'][1] + self.assertEqual(len(current_version), 4) + self.assertIn('id', current_version) + self.assertEqual(current_version['id'], 'v1') + self.assertIn('links', current_version) + links = current_version['links'][0] + self.assertIn('href', links) + href = links['href'] + self.assertIn('/v1/', href) + self.assertIn('rel', links) + rel = links['rel'] + self.assertEqual('self', rel) + self.assertIn('status', current_version) + status = current_version['status'] + self.assertEqual('CURRENT', status) + self.assertIn('updated', current_version) + + @decorators.attr(type="gate") + def test_api_version_v1(self): + resp, response_body = self.freezer_api_client.get_version_v1() + self.assertEqual(200, resp.status) + + response_body_jason = json.loads(response_body) + self.assertIn('resources', response_body_jason) + resource = response_body_jason['resources'] + self.assertIn('rel/backups', resource) + rel_backups = resource['rel/backups'] + self.assertIn('href-template', rel_backups) + href_template = rel_backups['href-template'] + self.assertEqual('/v1/backups/{backup_id}', href_template) + self.assertIn('href-vars', rel_backups) + href_vars = rel_backups['href-vars'] + self.assertIn('backup_id', href_vars) + backup_id = href_vars['backup_id'] + self.assertEqual('param/backup_id', backup_id) + self.assertIn('hints', rel_backups) + hints = rel_backups['hints'] + self.assertIn('allow', hints) + allow = hints['allow'] + self.assertEqual('GET', allow[0]) + self.assertIn('formats', hints) + formats = hints['formats'] + self.assertIn('application/json', formats) + + @decorators.attr(type="gate") + def test_api_version_v2(self): + resp, response_body = self.freezer_api_client.get_version_v2() + self.assertEqual(200, resp.status) + + response_body_jason = json.loads(response_body) + self.assertIn('resources', response_body_jason) + resource = response_body_jason['resources'] + self.assertIn('rel/backups', resource) + rel_backups = resource['rel/backups'] + self.assertIn('href-template', rel_backups) + href_template = rel_backups['href-template'] + self.assertEqual('/v2/{project_id}/backups/{backup_id}', href_template) + self.assertIn('href-vars', rel_backups) + href_vars = rel_backups['href-vars'] + self.assertIn('backup_id', href_vars) + self.assertIn('project_id', href_vars) + backup_id = href_vars['backup_id'] + self.assertEqual('param/backup_id', backup_id) + project_id = href_vars['project_id'] + self.assertEqual('param/project_id', project_id) + self.assertIn('hints', rel_backups) + hints = rel_backups['hints'] + self.assertIn('allow', hints) + allow = hints['allow'] + self.assertEqual('GET', allow[0]) + self.assertIn('formats', hints) + formats = hints['formats'] + self.assertIn('application/json', formats)