API Tests for Create Service endpoint
This patch updates API Tests for Create Service endpoint, to include Fastly service validation. Change-Id: I6c3370b5dd8937f4349e10ca3e81ae3c2f5eada3
This commit is contained in:
parent
7af26b4c95
commit
ddf4174b22
|
@ -19,7 +19,6 @@ from cafe.drivers.unittest import fixtures
|
|||
import jsonschema
|
||||
from oslo.config import cfg
|
||||
|
||||
|
||||
from tests.api.utils import client
|
||||
from tests.api.utils import config
|
||||
from tests.api.utils import server
|
||||
|
@ -36,8 +35,6 @@ class TestBase(fixtures.BaseTestFixture):
|
|||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
cls.conf_file = 'poppy_mockdb.conf'
|
||||
|
||||
super(TestBase, cls).setUpClass()
|
||||
|
||||
cls.auth_config = config.AuthConfig()
|
||||
|
@ -57,11 +54,11 @@ class TestBase(fixtures.BaseTestFixture):
|
|||
serialize_format='json',
|
||||
deserialize_format='json')
|
||||
|
||||
cls.server_config = config.PoppyServerConfig()
|
||||
|
||||
if cls.server_config.run_server:
|
||||
cls.test_config = config.TestConfig()
|
||||
if cls.test_config.run_server:
|
||||
conf_file = 'poppy_mockdb.conf'
|
||||
conf_path = os.environ["POPPY_TESTS_CONFIGS_DIR"]
|
||||
config_file = os.path.join(conf_path, cls.conf_file)
|
||||
config_file = os.path.join(conf_path, conf_file)
|
||||
|
||||
conf = cfg.ConfigOpts()
|
||||
conf(project='poppy', prog='poppy', args=[],
|
||||
|
@ -79,6 +76,6 @@ class TestBase(fixtures.BaseTestFixture):
|
|||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
"""Deletes the added resources."""
|
||||
if cls.server_config.run_server:
|
||||
if cls.test_config.run_server:
|
||||
cls.poppy_server.stop()
|
||||
super(TestBase, cls).tearDownClass()
|
||||
|
|
|
@ -27,7 +27,6 @@ class TestHealth(base.TestBase):
|
|||
super(TestHealth, self).setUp()
|
||||
|
||||
def test_health(self):
|
||||
|
||||
self.skipTest('Endpoint Not Implemented')
|
||||
|
||||
resp = self.client.check_health()
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# 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 tests.api import base
|
||||
from tests.api.utils import fastlyclient as fastly
|
||||
|
||||
|
||||
class TestProviderBase(base.TestBase):
|
||||
"""Child class of base.TestBase for validating provider updates.
|
||||
|
||||
Inherit from this and write your test methods (for tests that require
|
||||
provider side validation. Operators might need to add validation for
|
||||
providers not supported already.If the child class defines a prepare(self)
|
||||
method, this method will be called before executing each test method.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestProviderBase, cls).setUpClass()
|
||||
|
||||
def getServiceFromProvider(self, provider, service_name):
|
||||
if provider == 'fastly':
|
||||
fastly_config = self.config.FastlyConfig()
|
||||
fastly_client = fastly.FastlyClient(
|
||||
api_key=fastly_config.api_key,
|
||||
email=fastly_config.email,
|
||||
password=fastly_config.password)
|
||||
service_details = fastly_client.get_service(service_name)
|
||||
return service_details
|
||||
|
||||
def getServiceFromFlavor(self, flavor, service_name):
|
||||
"""Verify response schema aligns with the expected schema."""
|
||||
provider_list = self.config.flavor[flavor]
|
||||
service_details = dict(
|
||||
(provider, self.getServiceFromProvider(provider, service_name))
|
||||
for provider in provider_list)
|
||||
return service_details
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(TestProviderBase, cls).tearDownClass()
|
|
@ -3,7 +3,7 @@
|
|||
"name": "my_service_name",
|
||||
"domain_list": [{"domain": "mywebsite.com"},
|
||||
{"domain": "blog.mywebsite.com"}],
|
||||
"origin_list": [{"origins": "mywebsite.com",
|
||||
"origin_list": [{"origin": "mywebsite1.com",
|
||||
"port": 443,
|
||||
"ssl": false}],
|
||||
"flavorRef": "standard",
|
||||
|
@ -17,10 +17,10 @@
|
|||
"name": "my_service_name_2",
|
||||
"domain_list": [{"domain": "mywebsite.com"},
|
||||
{"domain": "blog.mywebsite.com"}],
|
||||
"origin_list": [{"origins": "mywebsite.com",
|
||||
"origin_list": [{"origin": "mywebsite1.com",
|
||||
"port": 443,
|
||||
"ssl": false}],
|
||||
"flavorRef": "standard",
|
||||
"caching_list": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,45 +17,71 @@ import uuid
|
|||
|
||||
import ddt
|
||||
|
||||
from tests.api import base
|
||||
from tests.api.utils.schema import response
|
||||
from tests.api import providers
|
||||
# from tests.api.utils.schema import response - Uncomment after get_service API
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestServices(base.TestBase):
|
||||
class TestServices(providers.TestProviderBase):
|
||||
|
||||
"""Tests for Services."""
|
||||
|
||||
def setUp(self):
|
||||
super(TestServices, self).setUp()
|
||||
self.service_name = uuid.uuid1()
|
||||
self.service_name = str(uuid.uuid1())
|
||||
|
||||
@ddt.file_data('data_create_service.json')
|
||||
def test_create_service(self, test_data):
|
||||
|
||||
self.skipTest('Endpoint Not Implemented')
|
||||
|
||||
domain_list = test_data['domain_list']
|
||||
origin_list = test_data['origin_list']
|
||||
caching_list = test_data['caching_list']
|
||||
flavor = test_data['flavorRef']
|
||||
|
||||
resp = self.client.create_service(service_name=self.service_name,
|
||||
domain_list=domain_list,
|
||||
origin_list=origin_list,
|
||||
caching_list=caching_list)
|
||||
self.assertEqual(resp.status_code, 201)
|
||||
|
||||
response_body = resp.json()
|
||||
self.assertSchema(response_body, response.create_service)
|
||||
caching_list=caching_list,
|
||||
flavorRef=flavor)
|
||||
self.assertEqual(resp.status_code, 202)
|
||||
|
||||
# TODO(malini): uncomment after get_service endpoint is complete.
|
||||
'''
|
||||
# Get on Created Service
|
||||
resp = self.client.get_service(service_name=self.service_name)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
body = resp.json()
|
||||
self.assertSchema(body, response.create_service)
|
||||
|
||||
self.assertEqual(body['domains'], domain_list)
|
||||
self.assertEqual(body['origins'], origin_list)
|
||||
self.assertEqual(body['caching_list'], caching_list)
|
||||
'''
|
||||
|
||||
# Verify the service is updated at all Providers for the flavor
|
||||
if self.test_config.provider_validation:
|
||||
service_details = (
|
||||
self.getServiceFromFlavor(flavor, self.service_name))
|
||||
provider_list = self.config.flavor[flavor]
|
||||
# Verify that the service stored in each provider (that is part of
|
||||
# the flavor) is what Poppy sent them.
|
||||
for provider in provider_list:
|
||||
self.assertEqual(
|
||||
sorted(service_details[provider]['domain_list']),
|
||||
sorted(domain_list),
|
||||
msg='Domain Lists Not Correct for {0} service name {1}'.
|
||||
format(provider, self.service_name))
|
||||
self.assertEqual(
|
||||
sorted(service_details[provider]['origin_list']),
|
||||
sorted(origin_list),
|
||||
msg='Origin List Not Correct for {0} service name {1}'.
|
||||
format(provider, self.service_name))
|
||||
self.assertEqual(
|
||||
sorted(service_details[provider]['caching_list']),
|
||||
sorted(caching_list),
|
||||
msg='Caching List Not Correct for {0} service name {1}'.
|
||||
format(provider, self.service_name))
|
||||
|
||||
def tearDown(self):
|
||||
self.client.delete_service(service_name=self.service_name)
|
||||
|
|
|
@ -70,7 +70,8 @@ class PoppyClient(client.AutoMarshallingHTTPClient):
|
|||
|
||||
def create_service(self, service_name=None,
|
||||
domain_list=None, origin_list=None,
|
||||
caching_list=None, requestslib_kwargs=None):
|
||||
caching_list=None, requestslib_kwargs=None,
|
||||
flavorRef=None):
|
||||
"""Creates Service
|
||||
|
||||
:return: Response Object containing response code 200 and body with
|
||||
|
@ -82,8 +83,9 @@ class PoppyClient(client.AutoMarshallingHTTPClient):
|
|||
request_object = requests.CreateService(service_name=service_name,
|
||||
domain_list=domain_list,
|
||||
origin_list=origin_list,
|
||||
caching_list=caching_list)
|
||||
return self.request('PUT', url,
|
||||
caching_list=caching_list,
|
||||
flavorRef=flavorRef)
|
||||
return self.request('POST', url,
|
||||
request_entity=request_object,
|
||||
requestslib_kwargs=requestslib_kwargs)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
|
||||
from cafe.engine.models import data_interfaces
|
||||
|
||||
|
||||
|
@ -25,16 +27,26 @@ class PoppyConfig(data_interfaces.ConfigSectionInterface):
|
|||
"""poppy endpoint."""
|
||||
return self.get('base_url')
|
||||
|
||||
@property
|
||||
def flavor(self):
|
||||
"""poppy flavor definitions."""
|
||||
return json.loads(self.get('flavor'))
|
||||
|
||||
class PoppyServerConfig(data_interfaces.ConfigSectionInterface):
|
||||
"""Defines the config values for starting (or not) a Poppy server."""
|
||||
SECTION_NAME = 'poppy_server'
|
||||
|
||||
class TestConfig(data_interfaces.ConfigSectionInterface):
|
||||
"""Defines the config values specific to test execution."""
|
||||
SECTION_NAME = 'test_configuration'
|
||||
|
||||
@property
|
||||
def run_server(self):
|
||||
"""Boolean value indicating whether to start a Poppy server."""
|
||||
return self.get_boolean('run_server')
|
||||
|
||||
@property
|
||||
def provider_validation(self):
|
||||
"""Boolean value indicating if tests verify provider side details."""
|
||||
return self.get_boolean('provider_validation')
|
||||
|
||||
|
||||
class AuthConfig(data_interfaces.ConfigSectionInterface):
|
||||
"""Defines the auth config values."""
|
||||
|
@ -53,14 +65,34 @@ class AuthConfig(data_interfaces.ConfigSectionInterface):
|
|||
@property
|
||||
def user_name(self):
|
||||
"""The name of the user, if applicable."""
|
||||
return self.get("user_name")
|
||||
return self.get('user_name')
|
||||
|
||||
@property
|
||||
def api_key(self):
|
||||
"""The user's api key, if applicable."""
|
||||
return self.get_raw("api_key")
|
||||
return self.get_raw('api_key')
|
||||
|
||||
@property
|
||||
def tenant_id(self):
|
||||
"""The user's tenant_id, if applicable."""
|
||||
return self.get("tenant_id")
|
||||
return self.get('tenant_id')
|
||||
|
||||
|
||||
class FastlyConfig(data_interfaces.ConfigSectionInterface):
|
||||
"""Defines the fastly config values."""
|
||||
SECTION_NAME = 'fastly'
|
||||
|
||||
@property
|
||||
def api_key(self):
|
||||
"""Fastly API Key."""
|
||||
return self.get('api_key')
|
||||
|
||||
@property
|
||||
def email(self):
|
||||
"""Email id associated with Fastly account."""
|
||||
return self.get('email')
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
"""Fastly password."""
|
||||
return self.get('password')
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# Copyright (c) 2014 Rackspace, Inc.
|
||||
#
|
||||
# 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 cafe.engine.http import client
|
||||
import fastly
|
||||
|
||||
|
||||
class FastlyClient(client.AutoMarshallingHTTPClient):
|
||||
|
||||
"""Client objects for Fastly api calls."""
|
||||
|
||||
def __init__(self, api_key, email, password, serialize_format="json",
|
||||
deserialize_format="json"):
|
||||
super(FastlyClient, self).__init__(serialize_format,
|
||||
deserialize_format)
|
||||
self.client = fastly.connect(api_key)
|
||||
self.client.login(email, password)
|
||||
|
||||
self.serialize = serialize_format
|
||||
self.deserialize_format = deserialize_format
|
||||
|
||||
def get_service(self, service_name):
|
||||
# Get the service
|
||||
service = self.client.get_service_by_name(service_name)
|
||||
service_version = self.client.list_versions(service.id)
|
||||
|
||||
# The create service api_call updates the domain, origin & cache
|
||||
# settings in second version of the service. The version # will be the
|
||||
# value of 'number' in the second element of the list returned by
|
||||
# self.client.list_versions(service.id) call above
|
||||
version = service_version[1].number
|
||||
|
||||
# Get the Domain List
|
||||
domains = self.client.list_domains(service.id, version)
|
||||
domain_list = [{'domain': domain.name} for domain in domains]
|
||||
|
||||
# Get the Cache List
|
||||
cache_setting_list = self.client.list_cache_settings(
|
||||
service.id, version)
|
||||
|
||||
cache_list = [{'name': item['name'], 'ttl': int(item['ttl']),
|
||||
'rules': item['cache_condition']}
|
||||
for item in cache_setting_list]
|
||||
|
||||
# Get the Origin List
|
||||
backends = self.client.list_backends(service.id, version)
|
||||
origin = backends[0].address
|
||||
port = backends[0].port
|
||||
ssl = backends[0].use_ssl
|
||||
|
||||
origin_list = [{'origin': origin, 'port': port, 'ssl': ssl}]
|
||||
|
||||
return {'domain_list': domain_list,
|
||||
'origin_list': origin_list,
|
||||
'caching_list': cache_list}
|
||||
|
||||
'''except fastly.FastlyError:
|
||||
print('1', fastly.FastlyError)
|
||||
return ("failed to GET service")
|
||||
except Exception:
|
||||
print('2', Exception)
|
||||
return ("failed to GET service")
|
||||
'''
|
|
@ -21,20 +21,20 @@ from cafe.engine.models import base
|
|||
class CreateService(base.AutoMarshallingModel):
|
||||
"""Marshalling for Create Service requests."""
|
||||
|
||||
def __init__(self, name=None, domain_list=None, origin_list=None,
|
||||
flavorRef=None, caching_list=None):
|
||||
def __init__(self, service_name=None, domain_list=None, origin_list=None,
|
||||
caching_list=None, flavorRef=None):
|
||||
super(CreateService, self).__init__()
|
||||
|
||||
self.service_name = name
|
||||
self.service_name = service_name
|
||||
self.domain_list = domain_list or []
|
||||
self.origin_list = origin_list or []
|
||||
self.flavorRef = flavorRef
|
||||
self.caching_list = caching_list or []
|
||||
self.flavorRef = flavorRef
|
||||
|
||||
def _obj_to_json(self):
|
||||
create_service_request = {"name": self.service_name,
|
||||
"domains": self.domain_list,
|
||||
"origins": self.origin_list,
|
||||
"flavorRef": self.flavorRef,
|
||||
"caching": self.caching_list}
|
||||
"caching": self.caching_list,
|
||||
"flavorRef": self.flavorRef}
|
||||
return json.dumps(create_service_request)
|
||||
|
|
|
@ -10,6 +10,13 @@ base_url=https://identity.api.rackspacecloud.com/v2.0
|
|||
|
||||
[poppy]
|
||||
base_url=http://0.0.0.0:8888
|
||||
flavor = {"flavor1": ["provider_1], "flavor2": ["provider_2", "provider_3"]}
|
||||
|
||||
[poppy_server]
|
||||
[test_configuration]
|
||||
run_server=True
|
||||
provider_validation=False
|
||||
|
||||
[provider_1]
|
||||
api_key=INSERT_YOUR_API_KEY
|
||||
email_id=account_email_id
|
||||
password=password
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -16,7 +16,7 @@ setenv = VIRTUAL_ENV={envdir}
|
|||
NOSE_OPENSTACK_STDOUT=1
|
||||
deps = -r{toxinidir}/requirements/requirements.txt
|
||||
-r{toxinidir}/tests/test-requirements.txt
|
||||
commands = pip install git+https://github.com/malini-kamalambal/opencafe.git#egg=cafe
|
||||
commands = pip install git+https://github.com/stackforge/opencafe.git#egg=cafe
|
||||
pip install git+https://github.com/tonytan4ever/python-maxcdn.git#egg=maxcdn
|
||||
nosetests {posargs}
|
||||
|
||||
|
|
Loading…
Reference in New Issue