From 164275fbe887ba60633068cb938782e45d6eafc8 Mon Sep 17 00:00:00 2001 From: Malini Kamalambal Date: Wed, 22 Oct 2014 07:23:22 -0400 Subject: [PATCH] Add API tests for PATCH service endpoint This patch adds the API tests for patch service endpoint. Change-Id: I91c1fdfd157811114eeb474246ca10b44dfad46e --- tests/api/services/data_patch_service.json | 24 +++++ .../data_patch_service_failing_tests.json | 24 +++++ .../services/data_patch_service_negative.json | 89 +++++++++++++++++++ tests/api/services/test_services.py | 68 ++++++++++++-- tests/api/utils/client.py | 38 +++++++- tests/api/utils/config.py | 10 +++ tests/api/utils/models/requests.py | 13 +++ tests/etc/api.conf | 2 + 8 files changed, 261 insertions(+), 7 deletions(-) create mode 100644 tests/api/services/data_patch_service.json create mode 100644 tests/api/services/data_patch_service_failing_tests.json create mode 100644 tests/api/services/data_patch_service_negative.json diff --git a/tests/api/services/data_patch_service.json b/tests/api/services/data_patch_service.json new file mode 100644 index 00000000..1a802f31 --- /dev/null +++ b/tests/api/services/data_patch_service.json @@ -0,0 +1,24 @@ +{ + "update_domain_list": { + "domains": [{"domain": "woooznewwebsite.com"}, + {"domain": "woooznewblog.mywebsite.com"}] + }, + "update_origin_list": { + "origins": [{"origin": "www.wooozneworigin.com", + "port": 443, "ssl": false}] + }, + "update_caching_list": { + "caching": [{"newname": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + }, + "update_multiple_values": { + "domains": [{"domain": "wooozymynewwebsite.com"}, + {"domain": "wooozynewblog.mywebsite.com"}], + "origins": [{"origin": "www.wooozyneworigin.com", + "port": 443, + "ssl": false}] + } +} diff --git a/tests/api/services/data_patch_service_failing_tests.json b/tests/api/services/data_patch_service_failing_tests.json new file mode 100644 index 00000000..6f4d7dae --- /dev/null +++ b/tests/api/services/data_patch_service_failing_tests.json @@ -0,0 +1,24 @@ +{ + "update_name": { + "name": "my_new_name" + }, + "update_domain_list": { + "domain_list": [{"domain": "mynewwebsite.com"}, + {"domain": "newblog.mywebsite.com"}] + }, + "update_origin_list": { + "origin_list": [{"origin": "www.neworigin.com", + "port": 443, + "ssl": false}] + }, + "update_flavorRef": { + "flavorRef": "premium" + }, + "update_caching_list": { + "caching_list": [{"newname": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + } +} diff --git a/tests/api/services/data_patch_service_negative.json b/tests/api/services/data_patch_service_negative.json new file mode 100644 index 00000000..6c3c75bc --- /dev/null +++ b/tests/api/services/data_patch_service_negative.json @@ -0,0 +1,89 @@ +{ + "empty_domain_list": { + "domains": [] + }, + "empty_list": {}, + "too_short_name": { + "service_name": "ab" + }, + "too_long_name": { + "service_name": "too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name_too_long_name" + }, + "empty_domain_list": { + "service_name": "empty_domain_list", + "domains": [], + "origins": [{"origin": "mywebsite1.com", + "port": 443, + "ssl": false}], + "flavor_ref": "standard", + "caching": [{"name": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + }, + "invalid_domain_value": { + "domains": [{"domain": "ftp://BOOOOOOM"}, + {"domain": "abc://BAAAAAAM"}] + }, + "empty_origin_list": { + "origins": [] + }, + "invalid_origin_value": { + "origins": [{"origin": "^%}invalid_origin_value", + "port": 443, + "ssl": false}] + }, + "non_numeric_origin_port": { + "service_name": "non_numeric_origin_port", + "domains": [{"domain": "mywebsite.com"}, + {"domain": "blog.mywebsite.com"}], + "origins": [{"origin": "invalid_origin_value", + "port": "fourfourthree", + "ssl": false}], + "flavor_ref": "standard", + "caching_list": [{"name": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + }, + "non_boolean_origin_ssl": { + "service_name": "non_boolean_origin_ssl", + "domains": [{"domain": "mywebsite.com"}, + {"domain": "blog.mywebsite.com"}], + "origins": [{"origin": "invalid_origin_value", + "port": 443, + "ssl": "Arggg"}], + "flavor_ref": "standard", + "caching": [{"name": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + }, + "invalid_flavor": { + "service_name": "invalid_flavor", + "domains": [{"domain": "mywebsite.com"}, + {"domain": "blog.mywebsite.com"}], + "origins": [{"origin": "mywebsite1.com", + "port": 443, + "ssl": false}], + "flavor_ref": "non_exist", + "caching": [{"name": "default", "ttl": 3600}, + {"name": "home", + "ttl": 1200, + "rules": [{"name" : "index", + "request_url" : "/index.htm"}]}] + }, + "caching_list_no_name": { + "service_name": "caching_list_no_name", + "domains": [{"domain": "mywebsite.com"}, + {"domain": "blog.mywebsite.com"}], + "origins": [{"origin": "mywebsite1.com", + "port": 443, + "ssl": false}], + "flavor_ref": "standard", + "caching": [{"ttl": 3600}] + } +} diff --git a/tests/api/services/test_services.py b/tests/api/services/test_services.py index 0f054760..2ae89359 100644 --- a/tests/api/services/test_services.py +++ b/tests/api/services/test_services.py @@ -207,10 +207,11 @@ class TestServiceActions(base.TestBase): def setUp(self): super(TestServiceActions, self).setUp() self.service_name = str(uuid.uuid1()) - self.domain_list = [{"domain": "mywebsite.com"}, - {"domain": "blog.mywebsite.com"}] + domain = str(uuid.uuid1()) + '.com' + self.domain_list = [{"domain": domain}] - self.origin_list = [{"origin": "mywebsite.com", + origin = str(uuid.uuid1()) + '.com' + self.origin_list = [{"origin": origin, "port": 443, "ssl": False}] self.caching_list = [{"name": "default", "ttl": 3600}, @@ -223,6 +224,64 @@ class TestServiceActions(base.TestBase): origin_list=self.origin_list, caching_list=self.caching_list, flavor_ref='standard') + self.client.wait_for_service_status( + service_name=self.service_name, + status='deployed', + retry_interval=self.test_config.status_check_retry_interval, + retry_timeout=self.test_config.status_check_retry_timeout) + + @ddt.file_data('data_patch_service.json') + def test_patch_service(self, test_data): + '''Implemented - PATCH Origins & Domains.''' + + resp = self.client.patch_service(service_name=self.service_name, + request_body=test_data) + + self.assertEqual(resp.status_code, 202) + + location = resp.headers['location'] + resp = self.client.get_service(location=location) + self.assertEqual(resp.status_code, 200) + + body = resp.json() + self.assertEqual(body['status'], 'updating') + self.client.wait_for_service_status( + service_name=self.service_name, + status='deployed', + retry_interval=self.test_config.status_check_retry_interval, + retry_timeout=self.test_config.status_check_retry_timeout) + + resp = self.client.get_service(service_name=self.service_name) + body = resp.json() + + if 'domain_list' in test_data: + self.assertEqual(sorted(test_data['domain_list']), + sorted(body['domains'])) + + if 'origin_list' in test_data: + self.assertEqual(sorted(test_data['origin_list']), + sorted(body['origins'])) + # TODO(malini): Uncomment after caching is implemented + # if 'caching_list' in test_data: + # self.assertEqual(sorted(test_data['caching_list']), + # sorted(body['caching'])) + + @ddt.file_data('data_patch_service_negative.json') + def test_patch_service_HTTP_400(self, test_data): + + resp = self.client.patch_service(service_name=self.service_name, + request_body=test_data) + self.assertEqual(resp.status_code, 400) + + resp = self.client.get_service(service_name=self.service_name) + self.assertEqual(resp.status_code, 200) + + body = resp.json() + self.assertEqual(body['status'], 'deployed') + self.assertEqual(sorted(self.domain_list), sorted(body['domains'])) + self.assertEqual(sorted(self.origin_list), sorted(body['origins'])) + # TODO(malini): Uncomment below after caching is implemented. + # self.assertEqual(sorted(self.caching_list), sorted(body['caching'])) def test_get_service(self): @@ -257,8 +316,7 @@ class TestServiceActions(base.TestBase): self.assertEqual(resp.status_code, 200) body = resp.json() - # self.assertEqual(body['status'], 'delete_in_progress') - self.assertEqual(body['status'], 'deployed') + self.assertEqual(body['status'], 'delete_in_progress') # TODO(malini): find a better solution # As is, the servvice is still available in the DB till deleted from diff --git a/tests/api/utils/client.py b/tests/api/utils/client.py index 8f2c3a86..2460a121 100644 --- a/tests/api/utils/client.py +++ b/tests/api/utils/client.py @@ -16,6 +16,7 @@ # limitations under the License. import json +import time from cafe.engine.http import client @@ -92,7 +93,20 @@ class PoppyClient(client.AutoMarshallingHTTPClient): return self.request('POST', url, request_entity=request_object, requestslib_kwargs=requestslib_kwargs) - def get_service(self, service_name): + def patch_service(self, service_name=None, request_body=None, + requestslib_kwargs=None): + """Updates Service + + :return: Response code 202 with location header + PATCH + services/{service_name} + """ + url = '{0}/v1.0/services/{1}'.format(self.url, service_name) + request_object = requests.PatchService(request_body=request_body) + return self.request('PATCH', url, request_entity=request_object, + requestslib_kwargs=requestslib_kwargs) + + def get_service(self, location=None, service_name=None): """Get Service :return: Response Object containing response code 200 and body with @@ -101,7 +115,10 @@ class PoppyClient(client.AutoMarshallingHTTPClient): services/{service_name} """ - url = '{0}/v1.0/services/{1}'.format(self.url, service_name) + if location: + url = location + else: + url = '{0}/v1.0/services/{1}'.format(self.url, service_name) return self.request('GET', url) def list_services(self, param=None): @@ -195,3 +212,20 @@ class PoppyClient(client.AutoMarshallingHTTPClient): url = u'{0}/v1.0/flavors/{1}'.format(self.url, flavor_id) return self.request('DELETE', url) + + def wait_for_service_status(self, service_name, status, retry_interval=2, + retry_timeout=30): + """Waits for a service to reach a given status.""" + current_status = '' + start_time = int(time.time()) + stop_time = start_time + retry_timeout + while current_status != status: + time.sleep(retry_interval) + service = self.get_service(service_name=service_name) + body = service.json() + current_status = body['status'] + if (current_status == status): + return + current_time = int(time.time()) + if current_time > stop_time: + return diff --git a/tests/api/utils/config.py b/tests/api/utils/config.py index 8503a0bd..c804eddc 100644 --- a/tests/api/utils/config.py +++ b/tests/api/utils/config.py @@ -42,6 +42,16 @@ class TestConfig(data_interfaces.ConfigSectionInterface): """Boolean value indicating if tests verify provider side details.""" return self.get_boolean('provider_validation') + @property + def status_check_retry_interval(self): + """Int value to set retry intervals for status check.""" + return int(self.get('status_check_retry_interval')) + + @property + def status_check_retry_timeout(self): + """Int value to set timeout for status check.""" + return int(self.get('status_check_retry_timeout')) + class AuthConfig(data_interfaces.ConfigSectionInterface): """Defines the auth config values.""" diff --git a/tests/api/utils/models/requests.py b/tests/api/utils/models/requests.py index f0f01f7e..02f6c269 100644 --- a/tests/api/utils/models/requests.py +++ b/tests/api/utils/models/requests.py @@ -40,6 +40,19 @@ class CreateService(base.AutoMarshallingModel): return json.dumps(create_service_request) +class PatchService(base.AutoMarshallingModel): + """Marshalling for Patch Service requests.""" + + def __init__(self, request_body=None): + super(PatchService, self).__init__() + + self.request_body = request_body + + def _obj_to_json(self): + patch_service_request = self.request_body + return json.dumps(patch_service_request) + + class CreateFlavor(base.AutoMarshallingModel): """Marshalling for Create Flavor requests.""" diff --git a/tests/etc/api.conf b/tests/etc/api.conf index 05c6e5d4..d5524254 100644 --- a/tests/etc/api.conf +++ b/tests/etc/api.conf @@ -14,6 +14,8 @@ flavor = {"flavor1": ["provider_1"], "flavor2": ["provider_2", "provider_3"]} [test_configuration] provider_validation=False +status_check_retry_interval=2 +status_check_retry_timeout=30 [provider_1] api_key=INSERT_YOUR_API_KEY