Create Service
Change-Id: Id5c8da6b3b3bfc8aad6495b441e294a64598c260
This commit is contained in:
parent
3bed3f2ec2
commit
4735284a41
@ -3,5 +3,6 @@ omit = *poppy/openstack*
|
|||||||
|
|
||||||
[report]
|
[report]
|
||||||
exclude_lines =
|
exclude_lines =
|
||||||
|
pragma: no cover
|
||||||
# Don't complain if tests don't hit defensive assertion code
|
# Don't complain if tests don't hit defensive assertion code
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -52,4 +52,13 @@ keyspace = poppy
|
|||||||
database = poppy
|
database = poppy
|
||||||
|
|
||||||
[drivers:provider:fastly]
|
[drivers:provider:fastly]
|
||||||
apikey = "MYAPIKEY"
|
apikey = "MYAPIKEY"
|
||||||
|
|
||||||
|
[drivers:provider:maxcdn]
|
||||||
|
alias = "MYALIAS"
|
||||||
|
consumer_secret = "MYCONSUMER_SECRET"
|
||||||
|
consumer_key = "MYCONSUMERKEY"
|
||||||
|
|
||||||
|
[drivers:provider:cloudfront]
|
||||||
|
aws_access_key_id = "MY_AWS_ACCESS_KEY_ID"
|
||||||
|
aws_secret_access_key = "MY_AWS_SECRET_ACCESS_KEY"
|
||||||
|
@ -18,8 +18,8 @@ from poppy.common import errors
|
|||||||
|
|
||||||
class ProviderWrapper(object):
|
class ProviderWrapper(object):
|
||||||
|
|
||||||
def create(self, ext, service_name, service_json):
|
def create(self, ext, service_obj):
|
||||||
return ext.obj.service_controller.create(service_name, service_json)
|
return ext.obj.service_controller.create(service_obj)
|
||||||
|
|
||||||
def update(self, ext, provider_details, service_json):
|
def update(self, ext, provider_details, service_json):
|
||||||
try:
|
try:
|
||||||
@ -28,7 +28,7 @@ class ProviderWrapper(object):
|
|||||||
raise errors.BadProviderDetail(
|
raise errors.BadProviderDetail(
|
||||||
"No provider detail information."
|
"No provider detail information."
|
||||||
"Perhaps service has not been created")
|
"Perhaps service has not been created")
|
||||||
provider_service_id = provider_detail.id
|
provider_service_id = provider_detail.provider_service_id
|
||||||
return ext.obj.service_controller.update(
|
return ext.obj.service_controller.update(
|
||||||
provider_service_id,
|
provider_service_id,
|
||||||
service_json)
|
service_json)
|
||||||
@ -40,5 +40,5 @@ class ProviderWrapper(object):
|
|||||||
raise errors.BadProviderDetail(
|
raise errors.BadProviderDetail(
|
||||||
"No provider detail information."
|
"No provider detail information."
|
||||||
"Perhaps service has not been created")
|
"Perhaps service has not been created")
|
||||||
provider_service_id = provider_detail.id
|
provider_service_id = provider_detail.provider_service_id
|
||||||
return ext.obj.service_controller.delete(provider_service_id)
|
return ext.obj.service_controller.delete(provider_service_id)
|
||||||
|
@ -38,11 +38,11 @@ class ServicesControllerBase(controller.ManagerControllerBase):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create(self, project_id, service_name, service_json):
|
def create(self, project_id, service_obj):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def update(self, project_id, service_name, service_json):
|
def update(self, project_id, service_name, service_obj):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from poppy.manager import base
|
from poppy.manager import base
|
||||||
|
from poppy.model.helpers import provider_details
|
||||||
|
|
||||||
|
|
||||||
class DefaultServicesController(base.ServicesController):
|
class DefaultServicesController(base.ServicesController):
|
||||||
@ -21,45 +22,91 @@ class DefaultServicesController(base.ServicesController):
|
|||||||
def __init__(self, manager):
|
def __init__(self, manager):
|
||||||
super(DefaultServicesController, self).__init__(manager)
|
super(DefaultServicesController, self).__init__(manager)
|
||||||
|
|
||||||
self.storage = self._driver.storage.services_controller
|
self.storage_controller = self._driver.storage.services_controller
|
||||||
|
self.flavor_controller = self._driver.storage.flavors_controller
|
||||||
|
|
||||||
def list(self, project_id, marker=None, limit=None):
|
def list(self, project_id, marker=None, limit=None):
|
||||||
return self.storage.list(project_id, marker, limit)
|
return self.storage_controller.list(project_id, marker, limit)
|
||||||
|
|
||||||
def get(self, project_id, service_name):
|
def get(self, project_id, service_name):
|
||||||
return self.storage.get(project_id, service_name)
|
return self.storage_controller.get(project_id, service_name)
|
||||||
|
|
||||||
def create(self, project_id, service_name, service_obj):
|
def create(self, project_id, service_obj):
|
||||||
self.storage.create(
|
try:
|
||||||
project_id,
|
flavor = self.flavor_controller.get(service_obj.flavorRef)
|
||||||
service_name,
|
# raise a lookup error if the flavor is not found
|
||||||
service_obj)
|
except LookupError as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
# TODO(tonytan4ever): need to update provider_detail info in storage
|
providers = [p.provider_id for p in flavor.providers]
|
||||||
return self._driver.providers.map(
|
service_name = service_obj.name
|
||||||
self.provider_wrapper.create,
|
|
||||||
service_name,
|
try:
|
||||||
service_obj)
|
self.storage_controller.create(
|
||||||
|
project_id,
|
||||||
|
service_obj)
|
||||||
|
# ValueError will be raised if the service has already existed
|
||||||
|
except ValueError as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
responders = []
|
||||||
|
for provider in providers:
|
||||||
|
responder = self.provider_wrapper.create(
|
||||||
|
self._driver.providers[provider],
|
||||||
|
service_obj)
|
||||||
|
responders.append(responder)
|
||||||
|
|
||||||
|
provider_details_dict = {}
|
||||||
|
for responder in responders:
|
||||||
|
for provider_name in responder:
|
||||||
|
if 'error' not in responder[provider_name]:
|
||||||
|
provider_details_dict[provider_name] = (
|
||||||
|
provider_details.ProviderDetail(
|
||||||
|
provider_service_id=responder[provider_name]['id'],
|
||||||
|
access_urls=[link['href'] for link in
|
||||||
|
responder[provider_name]['links']])
|
||||||
|
)
|
||||||
|
if 'status' in responder[provider_name]:
|
||||||
|
provider_details_dict[provider_name].status = (
|
||||||
|
responder[provider_name]['status'])
|
||||||
|
else:
|
||||||
|
provider_details_dict[provider_name].status = (
|
||||||
|
'deployed')
|
||||||
|
else:
|
||||||
|
provider_details_dict[provider_name] = (
|
||||||
|
provider_details.ProviderDetail(
|
||||||
|
error_info=responder[provider_name]['error_detail']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
provider_details_dict[provider_name].status = 'failed'
|
||||||
|
|
||||||
|
self.storage_controller.update_provider_details(project_id,
|
||||||
|
service_name,
|
||||||
|
provider_details_dict)
|
||||||
|
|
||||||
|
return responders
|
||||||
|
|
||||||
def update(self, project_id, service_name, service_obj):
|
def update(self, project_id, service_name, service_obj):
|
||||||
self.storage.update(
|
self.storage_controller.update(
|
||||||
project_id,
|
project_id,
|
||||||
service_name,
|
service_name,
|
||||||
service_obj
|
service_obj
|
||||||
)
|
)
|
||||||
|
|
||||||
provider_details = self.storage.get_provider_details(project_id,
|
provider_details = self.storage_controller.get_provider_details(
|
||||||
service_name)
|
project_id,
|
||||||
|
service_name)
|
||||||
return self._driver.providers.map(
|
return self._driver.providers.map(
|
||||||
self.provider_wrapper.update,
|
self.provider_wrapper.update,
|
||||||
provider_details,
|
provider_details,
|
||||||
service_obj)
|
service_obj)
|
||||||
|
|
||||||
def delete(self, project_id, service_name):
|
def delete(self, project_id, service_name):
|
||||||
self.storage.delete(project_id, service_name)
|
self.storage_controller.delete(project_id, service_name)
|
||||||
|
|
||||||
provider_details = self.storage.get_provider_details(project_id,
|
provider_details = self.storage_controller.get_provider_details(
|
||||||
service_name)
|
project_id,
|
||||||
|
service_name)
|
||||||
return self._driver.providers.map(
|
return self._driver.providers.map(
|
||||||
self.provider_wrapper.delete,
|
self.provider_wrapper.delete,
|
||||||
provider_details)
|
provider_details)
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
import inspect
|
import inspect
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
class DictSerializableModel(object):
|
class DictSerializableModel(object):
|
||||||
@ -48,7 +48,7 @@ class DictSerializableModel(object):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def init_from_dict(cls, dict):
|
def init_from_dict(cls, input_dict):
|
||||||
"""Construct a model instance from a dictionary.
|
"""Construct a model instance from a dictionary.
|
||||||
|
|
||||||
This is only meant to be used for converting a
|
This is only meant to be used for converting a
|
||||||
|
@ -21,27 +21,33 @@ class ProviderDetail(object):
|
|||||||
|
|
||||||
'''ProviderDetail object for each provider.'''
|
'''ProviderDetail object for each provider.'''
|
||||||
|
|
||||||
def __init__(self, id=None, access_url=None, status=u"unknown", name=None):
|
def __init__(self, provider_service_id=None, access_urls=[],
|
||||||
self._id = id
|
status=u"unknown", name=None, error_info=None):
|
||||||
self._access_url = access_url
|
self._provider_service_id = provider_service_id
|
||||||
|
self._access_urls = access_urls
|
||||||
self._status = status
|
self._status = status
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._error_info = error_info
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def provider_service_id(self):
|
||||||
return self._id
|
return self._provider_service_id
|
||||||
|
|
||||||
@id.setter
|
@provider_service_id.setter
|
||||||
def id(self, value):
|
def provider_service_id(self, value):
|
||||||
self._id = value
|
self._provider_service_id = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def access_url(self):
|
def access_urls(self):
|
||||||
return self._access_url
|
return self._access_urls
|
||||||
|
|
||||||
@access_url.setter
|
@property
|
||||||
def access_url(self, value):
|
def name(self):
|
||||||
self._access_url = value
|
return self._name
|
||||||
|
|
||||||
|
@access_urls.setter
|
||||||
|
def access_urls(self, value):
|
||||||
|
self._access_urls = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self):
|
def status(self):
|
||||||
@ -57,3 +63,11 @@ class ProviderDetail(object):
|
|||||||
value,
|
value,
|
||||||
VALID_STATUSES)
|
VALID_STATUSES)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def error_info(self):
|
||||||
|
return self._error_info
|
||||||
|
|
||||||
|
@error_info.setter
|
||||||
|
def error_info(self, value):
|
||||||
|
self._error_info = value
|
||||||
|
@ -25,11 +25,13 @@ class Service(common.DictSerializableModel):
|
|||||||
name,
|
name,
|
||||||
domains,
|
domains,
|
||||||
origins,
|
origins,
|
||||||
|
flavorRef,
|
||||||
caching=[],
|
caching=[],
|
||||||
restrictions=[]):
|
restrictions=[]):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._domains = domains
|
self._domains = domains
|
||||||
self._origins = origins
|
self._origins = origins
|
||||||
|
self._flavorRef = flavorRef
|
||||||
self._caching = caching
|
self._caching = caching
|
||||||
self._restrictions = restrictions
|
self._restrictions = restrictions
|
||||||
self._status = u'unknown'
|
self._status = u'unknown'
|
||||||
@ -58,6 +60,14 @@ class Service(common.DictSerializableModel):
|
|||||||
def origins(self, value):
|
def origins(self, value):
|
||||||
self._origins = value
|
self._origins = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def flavorRef(self):
|
||||||
|
return self._flavorRef
|
||||||
|
|
||||||
|
@flavorRef.setter
|
||||||
|
def flavorRef(self, value):
|
||||||
|
self._flavorRef = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def caching(self):
|
def caching(self):
|
||||||
return self._caching
|
return self._caching
|
||||||
@ -92,7 +102,7 @@ class Service(common.DictSerializableModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def init_from_dict(cls, dict):
|
def init_from_dict(cls, input_dict):
|
||||||
"""Construct a model instance from a dictionary.
|
"""Construct a model instance from a dictionary.
|
||||||
|
|
||||||
This is only meant to be used for converting a
|
This is only meant to be used for converting a
|
||||||
@ -100,6 +110,6 @@ class Service(common.DictSerializableModel):
|
|||||||
When converting a model into a request model,
|
When converting a model into a request model,
|
||||||
use to_dict.
|
use to_dict.
|
||||||
"""
|
"""
|
||||||
o = cls("unnamed", [], [])
|
o = cls('unnamed', [], [], 'unnamed')
|
||||||
o.from_dict(dict)
|
o.from_dict(input_dict)
|
||||||
return o
|
return o
|
||||||
|
@ -31,16 +31,19 @@ class Responder(object):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
self.provider: {
|
self.provider: {
|
||||||
"error": msg
|
"error": msg,
|
||||||
|
"error_detail": traceback.format_exc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def created(self, provider_service_id, links):
|
def created(self, provider_service_id, links, **extras):
|
||||||
|
provider_response = {
|
||||||
|
"id": provider_service_id,
|
||||||
|
"links": links
|
||||||
|
}
|
||||||
|
provider_response.update(extras)
|
||||||
return {
|
return {
|
||||||
self.provider: {
|
self.provider: provider_response
|
||||||
"id": provider_service_id,
|
|
||||||
"links": links
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated(self, provider_service_id):
|
def updated(self, provider_service_id):
|
||||||
|
@ -45,3 +45,21 @@ class ServicesControllerBase(controller.ProviderControllerBase):
|
|||||||
def get(self, service_name):
|
def get(self, service_name):
|
||||||
"""Get details of the service, as stored by the provider."""
|
"""Get details of the service, as stored by the provider."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def _map_service_name(self, service_name):
|
||||||
|
"""Map poppy service name to provider's specific service name.
|
||||||
|
|
||||||
|
Map a poppy service name to a provider's service name so it
|
||||||
|
can comply provider's naming convention.
|
||||||
|
"""
|
||||||
|
return service_name
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def current_customer(self):
|
||||||
|
"""Return the current customer for a provider.
|
||||||
|
|
||||||
|
This will needed call each provider's customer API,
|
||||||
|
useful for certain providers ( e.g fastly) and manage
|
||||||
|
master-sub account
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
@ -51,6 +51,7 @@ class CDNProvider(base.Driver):
|
|||||||
def provider_name(self):
|
def provider_name(self):
|
||||||
return 'CloudFront'
|
return 'CloudFront'
|
||||||
|
|
||||||
|
@property
|
||||||
def client(self):
|
def client(self):
|
||||||
return self.cloudfront_client
|
return self.cloudfront_client
|
||||||
|
|
||||||
|
@ -15,8 +15,12 @@
|
|||||||
|
|
||||||
from boto import cloudfront
|
from boto import cloudfront
|
||||||
|
|
||||||
|
from poppy.common import decorators
|
||||||
|
from poppy.openstack.common import log
|
||||||
from poppy.provider import base
|
from poppy.provider import base
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ServiceController(base.ServiceBase):
|
class ServiceController(base.ServiceBase):
|
||||||
|
|
||||||
@ -28,36 +32,46 @@ class ServiceController(base.ServiceBase):
|
|||||||
super(ServiceController, self).__init__(driver)
|
super(ServiceController, self).__init__(driver)
|
||||||
|
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.current_customer = self.client.get_current_customer()
|
|
||||||
|
|
||||||
# TODO(obulpathi): get service
|
# TODO(obulpathi): get service
|
||||||
def get(self, service_name):
|
def get(self, service_name):
|
||||||
return {'domains': [], 'origins': [], 'caching': []}
|
return {'domains': [], 'origins': [], 'caching': []}
|
||||||
|
|
||||||
# TODo(obulpathi): update service
|
# TODo(obulpathi): update service
|
||||||
def update(self, service_name, service_json):
|
def update(self, service_name, service_obj):
|
||||||
return self.responder.updated(service_name)
|
return self.responder.updated(service_name)
|
||||||
|
|
||||||
def create(self, service_name, service_json):
|
def create(self, service_obj):
|
||||||
# TODO(obulpathi): create a single distribution for multiple origins
|
# TODO(obulpathi): create a single distribution for multiple origins
|
||||||
origin = service_json['origins'][0]
|
origin = service_obj.origins[0]
|
||||||
|
LOG.info('Start creating cloudfront config for %s' % service_obj.name)
|
||||||
try:
|
try:
|
||||||
# Create the origin for this domain:
|
# Create the origin for this domain:
|
||||||
aws_origin = cloudfront.origin.CustomOrigin(
|
aws_origin = cloudfront.origin.CustomOrigin(
|
||||||
dns_name=origin['origin'],
|
dns_name=origin.origin,
|
||||||
http_port=origin['port'],
|
http_port=origin.port,
|
||||||
https_port=origin['ssl'],
|
# cannot specify ssl like this yet, CF takes a port #
|
||||||
|
# https_port=origin.ssl,
|
||||||
origin_protocol_policy='match-viewer')
|
origin_protocol_policy='match-viewer')
|
||||||
distribution = self.client.create_distribution(
|
distribution = self.client.create_distribution(
|
||||||
origin=aws_origin,
|
origin=aws_origin,
|
||||||
enabled=True)
|
enabled=True)
|
||||||
|
if distribution.status == 'InProgress':
|
||||||
|
status = 'in_progress'
|
||||||
|
elif distribution.status == 'Deployed':
|
||||||
|
status = 'deployed'
|
||||||
|
else:
|
||||||
|
status = 'unknown'
|
||||||
except cloudfront.exception.CloudFrontServerError as e:
|
except cloudfront.exception.CloudFrontServerError as e:
|
||||||
return self.responder.failed(str(e))
|
return self.responder.failed(str(e))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.responder.failed(str(e))
|
return self.responder.failed(str(e))
|
||||||
|
|
||||||
links = [{'href': distribution.domain_name, 'rel': 'access_url'}]
|
links = [{'href': distribution.domain_name, 'rel': 'access_url'}]
|
||||||
return self.responder.created(distribution.id, links)
|
# extra information should be passed in here.
|
||||||
|
LOG.info('Creating cloudfront config for %s'
|
||||||
|
'successfull...' % service_obj.name)
|
||||||
|
return self.responder.created(distribution.id, links, status=status)
|
||||||
|
|
||||||
def delete(self, service_name):
|
def delete(self, service_name):
|
||||||
# NOTE(obulpathi): distribution_id is the equivalent of service_name
|
# NOTE(obulpathi): distribution_id is the equivalent of service_name
|
||||||
@ -68,3 +82,8 @@ class ServiceController(base.ServiceBase):
|
|||||||
return self.responder.deleted(distribution_id)
|
return self.responder.deleted(distribution_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.responder.failed(str(e))
|
return self.responder.failed(str(e))
|
||||||
|
|
||||||
|
@decorators.lazy_property(write=False)
|
||||||
|
def current_customer(self):
|
||||||
|
# TODO(tonytan4ever/obulpathi): Implement cloudfront's current_customer
|
||||||
|
pass
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import fastly
|
import fastly
|
||||||
|
|
||||||
|
from poppy.common import decorators
|
||||||
from poppy.provider import base
|
from poppy.provider import base
|
||||||
|
|
||||||
|
|
||||||
@ -28,47 +29,57 @@ class ServiceController(base.ServiceBase):
|
|||||||
super(ServiceController, self).__init__(driver)
|
super(ServiceController, self).__init__(driver)
|
||||||
|
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.current_customer = self.client.get_current_customer()
|
|
||||||
|
|
||||||
def update(self, provider_service_id, service_json):
|
def update(self, provider_service_id, service_obj):
|
||||||
return self.responder.updated(provider_service_id)
|
return self.responder.updated(provider_service_id)
|
||||||
|
|
||||||
def create(self, service_name, service_json):
|
def create(self, service_obj):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create a new service
|
# Create a new service
|
||||||
service = self.client.create_service(self.current_customer.id,
|
service = self.client.create_service(self.current_customer.id,
|
||||||
service_name)
|
service_obj.name)
|
||||||
|
|
||||||
# Create a new version of the service.
|
# Create a new version of the service.
|
||||||
service_version = self.client.create_version(service.id)
|
service_version = self.client.create_version(service.id)
|
||||||
|
|
||||||
# Create the domain for this service
|
# Create the domain for this service
|
||||||
for domain in service_json["domains"]:
|
for domain in service_obj.domains:
|
||||||
domain = self.client.create_domain(service.id,
|
domain = self.client.create_domain(service.id,
|
||||||
service_version.number,
|
service_version.number,
|
||||||
domain["domain"])
|
domain.domain)
|
||||||
|
|
||||||
# TODO(tonytan4ever): what if check_domains fail ?
|
# TODO(tonytan4ever): what if check_domains fail ?
|
||||||
# For right now we fail the who create process.
|
# For right now we fail the who create process.
|
||||||
# But do we want to fail the whole service create ? probably not.
|
# But do we want to fail the whole service create ? probably not.
|
||||||
# we need to carefully divise our try_catch here.
|
# we need to carefully divise our try_catch here.
|
||||||
links = [{"href": '.'.join([domain_dict['name'], suffix]),
|
domain_checks = self.client.check_domains(service.id,
|
||||||
|
service_version.number)
|
||||||
|
links = [{"href": '.'.join([domain_check.domain.name,
|
||||||
|
"global.prod.fastly.net"]),
|
||||||
"rel": 'access_url'}
|
"rel": 'access_url'}
|
||||||
for domain_dict, suffix, enabled in
|
for domain_check in domain_checks]
|
||||||
self.client.check_domains(service.id,
|
|
||||||
service_version.number)
|
|
||||||
if enabled]
|
|
||||||
|
|
||||||
for origin in service_json["origins"]:
|
for origin in service_obj.origins:
|
||||||
# Create the origins for this domain
|
# Create the origins for this domain
|
||||||
self.client.create_backend(service.id,
|
self.client.create_backend(service.id,
|
||||||
service_version.number,
|
service_version.number,
|
||||||
origin["origin"],
|
origin.origin.replace(":", "-"),
|
||||||
origin["origin"],
|
origin.origin,
|
||||||
origin["ssl"],
|
origin.ssl,
|
||||||
origin["port"]
|
origin.port
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO(tonytan4ever): To incorporate caching, restriction change
|
||||||
|
# once standarnd/limitation on these service details have been
|
||||||
|
# figured out
|
||||||
|
|
||||||
|
# activate latest version of this fastly service
|
||||||
|
service_versions = self.client.list_versions(service.id)
|
||||||
|
latest_version_number = max([version.number
|
||||||
|
for version in service_versions])
|
||||||
|
self.client.activate_version(service.id, latest_version_number)
|
||||||
|
|
||||||
return self.responder.created(service.id, links)
|
return self.responder.created(service.id, links)
|
||||||
|
|
||||||
except fastly.FastlyError:
|
except fastly.FastlyError:
|
||||||
@ -122,3 +133,7 @@ class ServiceController(base.ServiceBase):
|
|||||||
return self.responder.failed("failed to GET service")
|
return self.responder.failed("failed to GET service")
|
||||||
except Exception:
|
except Exception:
|
||||||
return self.responder.failed("failed to GET service")
|
return self.responder.failed("failed to GET service")
|
||||||
|
|
||||||
|
@decorators.lazy_property(write=False)
|
||||||
|
def current_customer(self):
|
||||||
|
return self.client.get_current_customer()
|
||||||
|
@ -13,8 +13,14 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import re
|
||||||
|
|
||||||
|
from poppy.common import decorators
|
||||||
from poppy.provider import base
|
from poppy.provider import base
|
||||||
|
|
||||||
|
MAXCDN_NAMING_REGEX = re.compile('^[a-zA-Z0-9-]{3,32}$')
|
||||||
|
|
||||||
|
|
||||||
class ServiceController(base.ServiceBase):
|
class ServiceController(base.ServiceBase):
|
||||||
|
|
||||||
@ -32,21 +38,17 @@ class ServiceController(base.ServiceBase):
|
|||||||
|
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
|
|
||||||
# This returns the current customer account info
|
def update(self, pullzone_id, service_obj):
|
||||||
account_info_return = self.client.get('/account.json')
|
|
||||||
if account_info_return['code'] != 200:
|
|
||||||
raise RuntimeError(account_info_return['error'])
|
|
||||||
self.current_customer = account_info_return['data']['account']
|
|
||||||
|
|
||||||
def update(self, pullzone_id, service_json):
|
|
||||||
'''MaxCDN update.
|
'''MaxCDN update.
|
||||||
|
|
||||||
manager needs to pass in pullzone id to delete.
|
manager needs to pass in pullzone id to delete.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
|
# TODO(tonytan4ever): correctly convert and update service_obj
|
||||||
|
# to a dictionary passed into maxcdn call.
|
||||||
update_response = self.client.put('/zones/pull.json/%s'
|
update_response = self.client.put('/zones/pull.json/%s'
|
||||||
% pullzone_id,
|
% pullzone_id,
|
||||||
params=service_json)
|
params=service_obj.to_dict())
|
||||||
if update_response['code'] != 200:
|
if update_response['code'] != 200:
|
||||||
return self.responder.failed('failed to update service')
|
return self.responder.failed('failed to update service')
|
||||||
return self.responder.updated(
|
return self.responder.updated(
|
||||||
@ -55,19 +57,21 @@ class ServiceController(base.ServiceBase):
|
|||||||
# this exception branch will most likely for a network failure
|
# this exception branch will most likely for a network failure
|
||||||
return self.responder.failed('failed to update service')
|
return self.responder.failed('failed to update service')
|
||||||
|
|
||||||
def create(self, service_name, service_json):
|
def create(self, service_obj):
|
||||||
'''MaxCDN create.
|
'''MaxCDN create.
|
||||||
|
|
||||||
manager needs to pass in a service name to create.
|
manager needs to pass in a service name to create.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
# Create a new pull zone: maxcdn only supports 1 origin
|
# Create a new pull zone: maxcdn only supports 1 origin
|
||||||
origin = service_json['origins'][0]
|
origin = service_obj.origins[0]
|
||||||
|
origin_prefix = 'https://' if origin.ssl else 'http://'
|
||||||
create_response = self.client.post('/zones/pull.json', data={
|
create_response = self.client.post('/zones/pull.json', data={
|
||||||
'name': service_name,
|
'name': self._map_service_name(service_obj.name),
|
||||||
'url': origin['origin'],
|
# TODO(tonytan4ever): maxcdn takes origin with
|
||||||
'port': origin.get('port', 80),
|
# 'http://' or 'https://' prefix.
|
||||||
'sslshared': 1 if origin['ssl'] else 0,
|
'url': ''.join([origin_prefix, origin.origin]),
|
||||||
|
'port': getattr(origin, 'port', 80),
|
||||||
})
|
})
|
||||||
|
|
||||||
if create_response['code'] != 201:
|
if create_response['code'] != 201:
|
||||||
@ -77,12 +81,12 @@ class ServiceController(base.ServiceBase):
|
|||||||
|
|
||||||
# Add custom domains to this service
|
# Add custom domains to this service
|
||||||
links = []
|
links = []
|
||||||
for domain in service_json['domains']:
|
for domain in service_obj.domains:
|
||||||
custom_domain_response = self.client.post(
|
self.client.post(
|
||||||
'/zones/pull/%s/customdomains.json'
|
'/zones/pull/%s/customdomains.json'
|
||||||
% created_zone_info['id'],
|
% created_zone_info['id'],
|
||||||
{'custom_domain': domain['domain']})
|
{'custom_domain': domain.domain})
|
||||||
links.append(custom_domain_response)
|
links.append({'href': domain.domain, "rel": "access_url"})
|
||||||
# TODO(tonytan4ever): What if it fails during add domains ?
|
# TODO(tonytan4ever): What if it fails during add domains ?
|
||||||
return self.responder.created(created_zone_info['id'], links)
|
return self.responder.created(created_zone_info['id'], links)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -108,3 +112,23 @@ class ServiceController(base.ServiceBase):
|
|||||||
def get(self, service_name):
|
def get(self, service_name):
|
||||||
'''Get details of the service, as stored by the provider.'''
|
'''Get details of the service, as stored by the provider.'''
|
||||||
return {'domains': [], 'origins': [], 'caching': []}
|
return {'domains': [], 'origins': [], 'caching': []}
|
||||||
|
|
||||||
|
def _map_service_name(self, service_name):
|
||||||
|
"""Map poppy service name to provider's specific service name.
|
||||||
|
|
||||||
|
Map a poppy service name to a provider's service name so it
|
||||||
|
can comply provider's naming convention.
|
||||||
|
"""
|
||||||
|
if MAXCDN_NAMING_REGEX.match(service_name):
|
||||||
|
return service_name
|
||||||
|
else:
|
||||||
|
return hashlib.sha1(service_name.encode("utf-8")).hexdigest()[:30]
|
||||||
|
|
||||||
|
@decorators.lazy_property(write=False)
|
||||||
|
def current_customer(self):
|
||||||
|
# This returns the current customer account info
|
||||||
|
account_info_return = self.client.get('/account.json')
|
||||||
|
if account_info_return['code'] == 200:
|
||||||
|
return account_info_return['data']['account']
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Get maxcdn current customer failed...")
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from poppy.common import decorators
|
||||||
from poppy.openstack.common import log
|
from poppy.openstack.common import log
|
||||||
from poppy.provider import base
|
from poppy.provider import base
|
||||||
|
|
||||||
@ -26,17 +27,23 @@ class ServiceController(base.ServiceBase):
|
|||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(ServiceController, self).__init__(driver)
|
super(ServiceController, self).__init__(driver)
|
||||||
|
|
||||||
def update(self, provider_service_id, service_json):
|
def update(self, provider_service_id, service_obj):
|
||||||
return self.responder.updated(provider_service_id)
|
return self.responder.updated(provider_service_id)
|
||||||
|
|
||||||
def create(self, service_name, service_json):
|
def create(self, service_obj):
|
||||||
LOG.debug("Mock creating service: %s" % service_name)
|
|
||||||
# We generate a fake id here
|
# We generate a fake id here
|
||||||
service_id = uuid.uuid1()
|
service_id = uuid.uuid1()
|
||||||
return self.responder.created(str(service_id), {})
|
return self.responder.created(str(service_id), [{
|
||||||
|
"href": "www.mysite.com",
|
||||||
|
'rel': "access_url"}])
|
||||||
|
|
||||||
def delete(self, provider_service_id):
|
def delete(self, provider_service_id):
|
||||||
return self.responder.deleted(provider_service_id)
|
return self.responder.deleted(provider_service_id)
|
||||||
|
|
||||||
def get(self, service_name):
|
def get(self, service_name):
|
||||||
return self.responder.get([], [], [])
|
return self.responder.get([], [], [])
|
||||||
|
|
||||||
|
@decorators.lazy_property(write=False)
|
||||||
|
def current_customer(self):
|
||||||
|
'''return current_customer for Mock. We can return a None.'''
|
||||||
|
return None
|
||||||
|
@ -49,3 +49,7 @@ class ServicesControllerBase(controller.StorageControllerBase):
|
|||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_provider_details(self, project_id, service_name):
|
def get_provider_details(self, project_id, service_name):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def update_provider_details(self, provider_details):
|
||||||
|
raise NotImplementedError
|
||||||
|
@ -83,11 +83,21 @@ class FlavorsController(base.FlavorsController):
|
|||||||
if (len(flavors) == 1):
|
if (len(flavors) == 1):
|
||||||
return flavors[0]
|
return flavors[0]
|
||||||
else:
|
else:
|
||||||
raise LookupError("More than one flavor was retrieved.")
|
raise LookupError("More than one flavor/no record was retrieved.")
|
||||||
|
|
||||||
def add(self, flavor):
|
def add(self, flavor):
|
||||||
"""Add a new flavor."""
|
"""Add a new flavor."""
|
||||||
|
|
||||||
|
# check if the flavor already exist.
|
||||||
|
# Note: If it does, no LookupError will be raised
|
||||||
|
try:
|
||||||
|
self.get(flavor.flavor_id)
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError("Flavor %s already exists..."
|
||||||
|
% flavor.flavor_id)
|
||||||
|
|
||||||
providers = dict((p.provider_id, p.provider_url)
|
providers = dict((p.provider_id, p.provider_url)
|
||||||
for p in flavor.providers)
|
for p in flavor.providers)
|
||||||
|
|
||||||
|
@ -52,16 +52,21 @@ CQL_DELETE_SERVICE = '''
|
|||||||
CQL_CREATE_SERVICE = '''
|
CQL_CREATE_SERVICE = '''
|
||||||
INSERT INTO services (project_id,
|
INSERT INTO services (project_id,
|
||||||
service_name,
|
service_name,
|
||||||
|
flavor_id,
|
||||||
domains,
|
domains,
|
||||||
origins,
|
origins,
|
||||||
caching_rules,
|
caching_rules,
|
||||||
restrictions)
|
restrictions,
|
||||||
|
provider_details
|
||||||
|
)
|
||||||
VALUES (%(project_id)s,
|
VALUES (%(project_id)s,
|
||||||
%(service_name)s,
|
%(service_name)s,
|
||||||
|
%(flavor_id)s,
|
||||||
%(domains)s,
|
%(domains)s,
|
||||||
%(origins)s,
|
%(origins)s,
|
||||||
%(caching_rules)s,
|
%(caching_rules)s,
|
||||||
%(restrictions)s)
|
%(restrictions)s,
|
||||||
|
%(provider_details)s)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
CQL_UPDATE_DOMAINS = '''
|
CQL_UPDATE_DOMAINS = '''
|
||||||
@ -94,6 +99,12 @@ CQL_GET_PROVIDER_DETAILS = '''
|
|||||||
WHERE project_id = %(project_id)s AND service_name = %(service_name)s
|
WHERE project_id = %(project_id)s AND service_name = %(service_name)s
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
CQL_UPDATE_PROVIDER_DETAILS = '''
|
||||||
|
UPDATE services
|
||||||
|
set provider_details = %(provider_details)s
|
||||||
|
WHERE project_id = %(project_id)s AND service_name = %(service_name)s
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
class ServicesController(base.ServicesController):
|
class ServicesController(base.ServicesController):
|
||||||
|
|
||||||
@ -115,7 +126,7 @@ class ServicesController(base.ServicesController):
|
|||||||
# TODO(amitgandhinz): return services instead once its formatted.
|
# TODO(amitgandhinz): return services instead once its formatted.
|
||||||
services = []
|
services = []
|
||||||
for r in results:
|
for r in results:
|
||||||
name = r.get("name", "unnamed")
|
name = r.get("service_name")
|
||||||
origins = r.get("origins", [])
|
origins = r.get("origins", [])
|
||||||
domains = r.get("domains", [])
|
domains = r.get("domains", [])
|
||||||
origins = [origin.Origin(json.loads(o)['origin'],
|
origins = [origin.Origin(json.loads(o)['origin'],
|
||||||
@ -123,7 +134,8 @@ class ServicesController(base.ServicesController):
|
|||||||
json.loads(o).get("ssl", False))
|
json.loads(o).get("ssl", False))
|
||||||
for o in origins]
|
for o in origins]
|
||||||
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
|
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
|
||||||
services.append(service.Service(name, domains, origins))
|
flavorRef = r.get("flavor_id")
|
||||||
|
services.append(service.Service(name, domains, origins, flavorRef))
|
||||||
return services
|
return services
|
||||||
|
|
||||||
def get(self, project_id, service_name):
|
def get(self, project_id, service_name):
|
||||||
@ -135,12 +147,12 @@ class ServicesController(base.ServicesController):
|
|||||||
results = self.session.execute(CQL_GET_SERVICE, args)
|
results = self.session.execute(CQL_GET_SERVICE, args)
|
||||||
|
|
||||||
if len(results) != 1:
|
if len(results) != 1:
|
||||||
raise ValueError("No service or multiple service found: %s"
|
raise LookupError("No service or multiple service found: %s"
|
||||||
% service_name)
|
% service_name)
|
||||||
|
|
||||||
services = []
|
services = []
|
||||||
for r in results:
|
for r in results:
|
||||||
name = r.get("name", "unnamed")
|
name = r.get("service_name")
|
||||||
origins = r.get("origins", [])
|
origins = r.get("origins", [])
|
||||||
domains = r.get("domains", [])
|
domains = r.get("domains", [])
|
||||||
origins = [origin.Origin(json.loads(o)['origin'],
|
origins = [origin.Origin(json.loads(o)['origin'],
|
||||||
@ -148,12 +160,23 @@ class ServicesController(base.ServicesController):
|
|||||||
json.loads(o).get("ssl", False))
|
json.loads(o).get("ssl", False))
|
||||||
for o in origins]
|
for o in origins]
|
||||||
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
|
domains = [domain.Domain(json.loads(d)['domain']) for d in domains]
|
||||||
services.append(service.Service(name, domains, origins))
|
flavorRef = r.get("flavor_id")
|
||||||
|
services.append(service.Service(name, domains, origins, flavorRef))
|
||||||
return services[0]
|
return services[0]
|
||||||
|
|
||||||
def create(self, project_id, service_name, service_obj):
|
def create(self, project_id, service_obj):
|
||||||
|
|
||||||
# create the service in storage
|
# create the service in storage
|
||||||
|
service_name = service_obj.name
|
||||||
|
|
||||||
|
# check if the serivce already exist.
|
||||||
|
# Note: If it does, no LookupError will be raised
|
||||||
|
try:
|
||||||
|
self.get(project_id, service_name)
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError("Service %s already exists..." % service_name)
|
||||||
|
|
||||||
domains = [json.dumps(domain.to_dict())
|
domains = [json.dumps(domain.to_dict())
|
||||||
for domain in service_obj.domains]
|
for domain in service_obj.domains]
|
||||||
origins = [json.dumps(origin.to_dict())
|
origins = [json.dumps(origin.to_dict())
|
||||||
@ -167,10 +190,13 @@ class ServicesController(base.ServicesController):
|
|||||||
args = {
|
args = {
|
||||||
'project_id': project_id,
|
'project_id': project_id,
|
||||||
'service_name': service_name,
|
'service_name': service_name,
|
||||||
|
'flavor_id': service_obj.flavorRef,
|
||||||
'domains': domains,
|
'domains': domains,
|
||||||
'origins': origins,
|
'origins': origins,
|
||||||
'caching_rules': caching_rules,
|
'caching_rules': caching_rules,
|
||||||
'restrictions': restrictions
|
'restrictions': restrictions,
|
||||||
|
# TODO(tonytan4ever): Incorporate flavor change.
|
||||||
|
'provider_details': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session.execute(CQL_CREATE_SERVICE, args)
|
self.session.execute(CQL_CREATE_SERVICE, args)
|
||||||
@ -206,12 +232,37 @@ class ServicesController(base.ServicesController):
|
|||||||
results = {}
|
results = {}
|
||||||
for provider_name in exec_results[0]:
|
for provider_name in exec_results[0]:
|
||||||
provider_detail_dict = json.loads(exec_results[0][provider_name])
|
provider_detail_dict = json.loads(exec_results[0][provider_name])
|
||||||
id = provider_detail_dict.get("id", None)
|
pr_id = provider_detail_dict.get("provider_service_id", None)
|
||||||
access_url = provider_detail_dict.get("access_url", None)
|
access_urls = provider_detail_dict.get("access_urls", None)
|
||||||
status = provider_detail_dict.get("status", u'unknown')
|
status = provider_detail_dict.get("status", u'unknown')
|
||||||
|
error_info = provider_detail_dict.get("error_info", None)
|
||||||
provider_detail_obj = provider_details.ProviderDetail(
|
provider_detail_obj = provider_details.ProviderDetail(
|
||||||
id=id,
|
provider_service_id=pr_id,
|
||||||
access_url=access_url,
|
access_urls=access_urls,
|
||||||
status=status)
|
status=status,
|
||||||
|
error_info=error_info)
|
||||||
results[provider_name] = provider_detail_obj
|
results[provider_name] = provider_detail_obj
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def update_provider_details(self, project_id, service_name,
|
||||||
|
provider_details):
|
||||||
|
provider_detail_dict = {}
|
||||||
|
for provider_name in provider_details:
|
||||||
|
provider_detail_dict[provider_name] = json.dumps({
|
||||||
|
"id": provider_details[provider_name].provider_service_id,
|
||||||
|
"access_urls": provider_details[provider_name].access_urls,
|
||||||
|
"status": provider_details[provider_name].status,
|
||||||
|
"name": provider_details[provider_name].name,
|
||||||
|
"error_info": provider_details[provider_name].error_info
|
||||||
|
})
|
||||||
|
args = {
|
||||||
|
'project_id': project_id,
|
||||||
|
'service_name': service_name,
|
||||||
|
'provider_details': provider_detail_dict
|
||||||
|
}
|
||||||
|
# TODO(tonytan4ever): Not sure this returns a list or a single
|
||||||
|
# dictionary.
|
||||||
|
# Needs to verify after cassandra unittest framework has been added in
|
||||||
|
# if a list, the return the first item of a list. if it is a dictionary
|
||||||
|
# returns the dictionary
|
||||||
|
self.session.execute(CQL_UPDATE_PROVIDER_DETAILS, args)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from poppy.model import flavor
|
||||||
from poppy.storage import base
|
from poppy.storage import base
|
||||||
|
|
||||||
|
|
||||||
@ -23,10 +24,24 @@ class FlavorsController(base.FlavorsController):
|
|||||||
return self._driver.database
|
return self._driver.database
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
return []
|
f = flavor.Flavor(
|
||||||
|
"standard",
|
||||||
|
[flavor.Provider("cloudfront", "www.cloudfront.com"),
|
||||||
|
flavor.Provider("fastly", "www.fastly.com"),
|
||||||
|
flavor.Provider("mock", "www.mock_provider.com")]
|
||||||
|
)
|
||||||
|
return [f]
|
||||||
|
|
||||||
def get(self, flavor_id):
|
def get(self, flavor_id):
|
||||||
return None
|
f = flavor.Flavor(
|
||||||
|
"standard",
|
||||||
|
[flavor.Provider("cloudfront", "www.cloudfront.com"),
|
||||||
|
flavor.Provider("fastly", "www.fastly.com"),
|
||||||
|
flavor.Provider("mock", "www.mock_provider.com")]
|
||||||
|
)
|
||||||
|
if flavor_id == "non_exist":
|
||||||
|
raise LookupError("More than one flavor/no record was retrieved.")
|
||||||
|
return f
|
||||||
|
|
||||||
def add(self, flavor):
|
def add(self, flavor):
|
||||||
pass
|
pass
|
||||||
|
@ -42,6 +42,7 @@ class ServicesController(base.ServicesController):
|
|||||||
"ssl": False
|
"ssl": False
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"flavorRef": "standard",
|
||||||
"caching": [
|
"caching": [
|
||||||
{"name": "default", "ttl": 3600},
|
{"name": "default", "ttl": 3600},
|
||||||
{
|
{
|
||||||
@ -76,12 +77,14 @@ class ServicesController(base.ServicesController):
|
|||||||
|
|
||||||
services_result = []
|
services_result = []
|
||||||
for r in services:
|
for r in services:
|
||||||
name = r.get("name", "unnamed")
|
name = r.get("name")
|
||||||
origins = r.get("origins", [])
|
origins = r.get("origins", [])
|
||||||
domains = r.get("domains", [])
|
domains = r.get("domains", [])
|
||||||
origins = [origin.Origin(d) for d in origins]
|
origins = [origin.Origin(d) for d in origins]
|
||||||
domains = [domain.Domain(d) for d in domains]
|
domains = [domain.Domain(d) for d in domains]
|
||||||
services_result.append(service.Service(name, domains, origins))
|
flavorRef = r.get("name").split("/")[-1]
|
||||||
|
services_result.append(service.Service(name, domains, origins,
|
||||||
|
flavorRef))
|
||||||
|
|
||||||
return services_result
|
return services_result
|
||||||
|
|
||||||
@ -101,6 +104,7 @@ class ServicesController(base.ServicesController):
|
|||||||
"ssl": False
|
"ssl": False
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"flavorRef": "standard",
|
||||||
"caching": [
|
"caching": [
|
||||||
{"name": "default", "ttl": 3600},
|
{"name": "default", "ttl": 3600},
|
||||||
{
|
{
|
||||||
@ -132,16 +136,18 @@ class ServicesController(base.ServicesController):
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
name = service_dict.get("name", "unnamed")
|
name = service_dict.get("name")
|
||||||
origins = service_dict.get("origins", [])
|
origins = service_dict.get("origins", [])
|
||||||
domains = service_dict.get("domains", [])
|
domains = service_dict.get("domains", [])
|
||||||
origins = [origin.Origin(d) for d in origins]
|
origins = [origin.Origin(d) for d in origins]
|
||||||
domains = [domain.Domain(d) for d in domains]
|
domains = [domain.Domain(d) for d in domains]
|
||||||
services_result = service.Service(name, domains, origins)
|
flavorRef = service_dict.get("name").split("/")[-1]
|
||||||
|
services_result = service.Service(name, domains, origins, flavorRef)
|
||||||
return services_result
|
return services_result
|
||||||
|
|
||||||
def create(self, project_id, service_name, service_json):
|
def create(self, project_id, service_obj):
|
||||||
|
if service_obj.name == "mockdb1_service_name":
|
||||||
|
raise ValueError("Service %s already exists..." % service_obj.name)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def update(self, project_id, service_name, service_json):
|
def update(self, project_id, service_name, service_json):
|
||||||
@ -156,19 +162,23 @@ class ServicesController(base.ServicesController):
|
|||||||
def get_provider_details(self, project_id, service_name):
|
def get_provider_details(self, project_id, service_name):
|
||||||
return {
|
return {
|
||||||
"MaxCDN": provider_details.ProviderDetail(
|
"MaxCDN": provider_details.ProviderDetail(
|
||||||
id=11942,
|
provider_service_id=11942,
|
||||||
name='my_service_name',
|
name='my_service_name',
|
||||||
access_url='my_service_name'
|
access_urls=['my_service_name'
|
||||||
'.mycompanyalias.netdna-cdn.com'),
|
'.mycompanyalias.netdna-cdn.com']),
|
||||||
"Fastly": provider_details.ProviderDetail(
|
"Fastly": provider_details.ProviderDetail(
|
||||||
id=3488,
|
provider_service_id=3488,
|
||||||
name="my_service_name",
|
name="my_service_name",
|
||||||
access_url='my_service_name'
|
access_urls=['my_service_name'
|
||||||
'.global.prod.fastly.net'),
|
'.global.prod.fastly.net']),
|
||||||
"CloudFront": provider_details.ProviderDetail(
|
"CloudFront": provider_details.ProviderDetail(
|
||||||
id=5892,
|
provider_service_id=5892,
|
||||||
access_url='my_service_name'
|
access_urls=['my_service_name'
|
||||||
'.gibberish.amzcf.com'),
|
'.gibberish.amzcf.com']),
|
||||||
"Mock": provider_details.ProviderDetail(
|
"Mock": provider_details.ProviderDetail(
|
||||||
id="73242",
|
provider_service_id="73242",
|
||||||
access_url='my_service_name.mock.com')}
|
access_urls=['my_service_name.mock.com'])}
|
||||||
|
|
||||||
|
def update_provider_details(self, project_id, service_name,
|
||||||
|
provider_details):
|
||||||
|
pass
|
||||||
|
@ -43,14 +43,12 @@ class FlavorsController(base.Controller):
|
|||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
def get_one(self, flavor_id):
|
def get_one(self, flavor_id):
|
||||||
flavors_controller = self.driver.manager.flavors_controller
|
flavors_controller = self.driver.manager.flavors_controller
|
||||||
result = flavors_controller.get(flavor_id)
|
try:
|
||||||
|
result = flavors_controller.get(flavor_id)
|
||||||
if result is not None:
|
except LookupError as e:
|
||||||
print (result)
|
pecan.abort(404, detail=str(e))
|
||||||
print('done')
|
|
||||||
return flavor_response.Model(result, pecan.request)
|
|
||||||
else:
|
else:
|
||||||
pecan.response.status = 404
|
return flavor_response.Model(result, pecan.request)
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
@decorators.validate(
|
@decorators.validate(
|
||||||
|
@ -17,6 +17,7 @@ import json
|
|||||||
|
|
||||||
import pecan
|
import pecan
|
||||||
|
|
||||||
|
from poppy.common import uri
|
||||||
from poppy.transport.pecan.controllers import base
|
from poppy.transport.pecan.controllers import base
|
||||||
from poppy.transport.pecan.models.request import service as req_service_model
|
from poppy.transport.pecan.models.request import service as req_service_model
|
||||||
from poppy.transport.pecan.models.response import link
|
from poppy.transport.pecan.models.response import link
|
||||||
@ -58,20 +59,28 @@ class ServicesController(base.Controller):
|
|||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
@decorators.validate(
|
@decorators.validate(
|
||||||
service_name=rule.Rule(
|
|
||||||
helpers.is_valid_service_name(),
|
|
||||||
helpers.abort_with_message),
|
|
||||||
request=rule.Rule(
|
request=rule.Rule(
|
||||||
helpers.json_matches_schema(
|
helpers.json_matches_schema(
|
||||||
service.ServiceSchema.get_schema("service", "PUT")),
|
service.ServiceSchema.get_schema("service", "POST")),
|
||||||
helpers.abort_with_message,
|
helpers.abort_with_message,
|
||||||
stoplight_helpers.pecan_getter))
|
stoplight_helpers.pecan_getter))
|
||||||
def put(self, service_name):
|
def post(self):
|
||||||
services_controller = self._driver.manager.services_controller
|
services_controller = self._driver.manager.services_controller
|
||||||
service_json_dict = json.loads(pecan.request.body.decode('utf-8'))
|
service_json_dict = json.loads(pecan.request.body.decode('utf-8'))
|
||||||
service_obj = req_service_model.load_from_json(service_json_dict)
|
service_obj = req_service_model.load_from_json(service_json_dict)
|
||||||
return services_controller.create(self.project_id, service_name,
|
service_name = service_json_dict.get("name", None)
|
||||||
service_obj)
|
try:
|
||||||
|
services_controller.create(self.project_id, service_obj)
|
||||||
|
except LookupError as e: # error handler for no flavor
|
||||||
|
pecan.abort(400, detail=str(e))
|
||||||
|
except ValueError as e: # error handler for existing service name
|
||||||
|
pecan.abort(400, detail=str(e))
|
||||||
|
service_url = str(
|
||||||
|
uri.encode(u'{0}/v1.0/services/{1}'.format(
|
||||||
|
pecan.request.host_url,
|
||||||
|
service_name)))
|
||||||
|
pecan.response.status = 202
|
||||||
|
pecan.response.headers["Location"] = service_url
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
def delete(self, service_name):
|
def delete(self, service_name):
|
||||||
|
@ -17,5 +17,5 @@ from poppy.model.helpers import domain
|
|||||||
|
|
||||||
|
|
||||||
def load_from_json(json_data):
|
def load_from_json(json_data):
|
||||||
domain_name = json_data.get("domain", None)
|
domain_name = json_data.get("domain")
|
||||||
return domain.Domain(domain_name)
|
return domain.Domain(domain_name)
|
||||||
|
@ -17,7 +17,7 @@ from poppy.model.helpers import origin
|
|||||||
|
|
||||||
|
|
||||||
def load_from_json(json_data):
|
def load_from_json(json_data):
|
||||||
origin_name = json_data.get("origin", "unnamed")
|
origin_name = json_data.get("origin")
|
||||||
port = json_data.get("port", 80)
|
port = json_data.get("port", 80)
|
||||||
ssl = json_data.get("ssl", False)
|
ssl = json_data.get("ssl", False)
|
||||||
return origin.Origin(origin_name, port, ssl)
|
return origin.Origin(origin_name, port, ssl)
|
||||||
|
@ -19,9 +19,10 @@ from poppy.transport.pecan.models.request import origin
|
|||||||
|
|
||||||
|
|
||||||
def load_from_json(json_data):
|
def load_from_json(json_data):
|
||||||
name = json_data.get("name", "unnamed")
|
name = json_data.get("name")
|
||||||
origins = json_data.get("origins", [])
|
origins = json_data.get("origins", [])
|
||||||
domains = json_data.get("domains", [])
|
domains = json_data.get("domains", [])
|
||||||
|
flavorRef = json_data.get("flavorRef")
|
||||||
origins = [origin.load_from_json(d) for d in origins]
|
origins = [origin.load_from_json(d) for d in origins]
|
||||||
domains = [domain.load_from_json(d) for d in domains]
|
domains = [domain.load_from_json(d) for d in domains]
|
||||||
return service.Service(name, origins, domains)
|
return service.Service(name, domains, origins, flavorRef)
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
class Model(collections.OrderedDict):
|
class Model(collections.OrderedDict):
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
from poppy.transport.pecan.models.response import link
|
from poppy.transport.pecan.models.response import link
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
class Model(collections.OrderedDict):
|
class Model(collections.OrderedDict):
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
class Model(collections.OrderedDict):
|
class Model(collections.OrderedDict):
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import ordereddict as collections
|
import ordereddict as collections
|
||||||
except ImportError:
|
except ImportError: # pragma: no cover
|
||||||
import collections
|
import collections # pragma: no cover
|
||||||
|
|
||||||
from poppy.transport.pecan.models.response import domain
|
from poppy.transport.pecan.models.response import domain
|
||||||
from poppy.transport.pecan.models.response import link
|
from poppy.transport.pecan.models.response import link
|
||||||
|
@ -178,7 +178,10 @@ def json_matches_schema_inner(request, schema=None):
|
|||||||
|
|
||||||
if len(errors_list) > 0:
|
if len(errors_list) > 0:
|
||||||
details = dict(errors=[{
|
details = dict(errors=[{
|
||||||
'message': str(getattr(error, "message", error))}
|
'message': '-'.join([
|
||||||
|
"[%s]" % "][".join(repr(p) for p in error.path),
|
||||||
|
str(getattr(error, "message", error))
|
||||||
|
])}
|
||||||
for error in errors_list])
|
for error in errors_list])
|
||||||
raise exceptions.ValidationFailed(json.dumps(details))
|
raise exceptions.ValidationFailed(json.dumps(details))
|
||||||
else:
|
else:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (c) 2014 Rackspace, Inc.
|
# Copyright (c) 2014 Rackspace, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -13,71 +14,82 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
from poppy.transport.validators import schema_base
|
from poppy.transport.validators import schema_base
|
||||||
|
|
||||||
|
|
||||||
class ServiceSchema(schema_base.SchemaBase):
|
class ServiceSchema(schema_base.SchemaBase):
|
||||||
|
|
||||||
"""JSON Schmema validation for /service."""
|
'''JSON Schmema validation for /service.'''
|
||||||
|
|
||||||
schema = {
|
schema = {
|
||||||
'service': {
|
'service': {
|
||||||
'PUT': {
|
'POST': {
|
||||||
'name': 'service',
|
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
"domains": {
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True,
|
||||||
|
},
|
||||||
|
'domains': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"domain": {
|
'domain': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
'pattern': "^(([a-zA-Z]{1})|"
|
'pattern': re.compile(
|
||||||
"([a-zA-Z]{1}[a-zA-Z]{1})|"
|
'^(([^:/?#]+):)?'
|
||||||
"([a-zA-Z]{1}[0-9]{1})"
|
'(//([^/?#]*))?'
|
||||||
"|([0-9]{1}[a-zA-Z]{1})|"
|
'([^?#]*)(\?([^#]*))?'
|
||||||
"([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}"
|
'(#(.*))?$',
|
||||||
"[a-zA-Z0-9]))\."
|
re.UNICODE
|
||||||
"([a-zA-Z]{2,6}|"
|
)
|
||||||
"[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$"
|
|
||||||
}}},
|
}}},
|
||||||
'required': True,
|
'required': True,
|
||||||
"minItems": 1},
|
'minItems': 1},
|
||||||
"origins": {
|
'origins': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"origin": {
|
'origin': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
"required": True},
|
'pattern': re.compile(
|
||||||
"port": {
|
'^(([^:/?#]+):)?'
|
||||||
"type": "integer",
|
'(//([^/?#]*))?'
|
||||||
"enum": [
|
'([^?#]*)(\?([^#]*))?'
|
||||||
|
'(#(.*))?$',
|
||||||
|
re.UNICODE
|
||||||
|
),
|
||||||
|
'required': True},
|
||||||
|
'port': {
|
||||||
|
'type': 'integer',
|
||||||
|
'enum': [
|
||||||
80,
|
80,
|
||||||
443]},
|
443]},
|
||||||
"ssl": {
|
'ssl': {
|
||||||
"type": "boolean"}},
|
'type': 'boolean'}},
|
||||||
},
|
},
|
||||||
'required': True,
|
'required': True,
|
||||||
"minItems": 1},
|
'minItems': 1},
|
||||||
"caching": {
|
'caching': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"name": {
|
'name': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
"required": True},
|
'required': True},
|
||||||
"ttl": {
|
'ttl': {
|
||||||
"type": "integer",
|
'type': 'integer',
|
||||||
"required": True},
|
'required': True},
|
||||||
"rules": {
|
'rules': {
|
||||||
"type": "array",
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
'name': {
|
'name': {
|
||||||
'type': 'string'},
|
'type': 'string'},
|
||||||
'request_url': {
|
'request_url': {
|
||||||
@ -85,60 +97,101 @@ class ServiceSchema(schema_base.SchemaBase):
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'restrictions': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True},
|
||||||
|
'rules': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string'},
|
||||||
|
'request_url': {
|
||||||
|
'type': 'string'},
|
||||||
|
'http_host': {
|
||||||
|
'type': 'string'},
|
||||||
|
'client_ip': {
|
||||||
|
'type': 'string'},
|
||||||
|
'http_method': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': [
|
||||||
|
'GET',
|
||||||
|
'PUT',
|
||||||
|
'POST',
|
||||||
|
'PATCH']}}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'flavorRef': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True,
|
||||||
|
}
|
||||||
}},
|
}},
|
||||||
'PATCH': {
|
'PATCH': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'properties': {
|
'properties': {
|
||||||
"domains": {
|
'domains': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"domain": {
|
'domain': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
'pattern': "^(([a-zA-Z]{1})|"
|
'pattern': re.compile(
|
||||||
"([a-zA-Z]{1}[a-zA-Z]{1})|"
|
'^(([^:/?#]+):)?'
|
||||||
"([a-zA-Z]{1}[0-9]{1})"
|
'(//([^/?#]*))?'
|
||||||
"|([0-9]{1}[a-zA-Z]{1})|"
|
'([^?#]*)(\?([^#]*))?'
|
||||||
"([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}"
|
'(#(.*))?$',
|
||||||
"[a-zA-Z0-9]))\."
|
re.UNICODE
|
||||||
"([a-zA-Z]{2,6}|"
|
)
|
||||||
"[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3})$"
|
|
||||||
}}},
|
}}},
|
||||||
},
|
},
|
||||||
"origins": {
|
'origins': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"origin": {
|
'origin': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
"required": True},
|
'pattern': re.compile(
|
||||||
"port": {
|
'^(([^:/?#]+):)?'
|
||||||
"type": "integer",
|
'(//([^/?#]*))?'
|
||||||
"enum": [
|
'([^?#]*)(\?([^#]*))?'
|
||||||
|
'(#(.*))?$',
|
||||||
|
re.UNICODE
|
||||||
|
),
|
||||||
|
'required': True},
|
||||||
|
'port': {
|
||||||
|
'type': 'integer',
|
||||||
|
'enum': [
|
||||||
80,
|
80,
|
||||||
443]},
|
443]},
|
||||||
"ssl": {
|
'ssl': {
|
||||||
"type": "boolean"}},
|
'type': 'boolean'}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"caching": {
|
'caching': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
"name": {
|
'name': {
|
||||||
"type": "string",
|
'type': 'string',
|
||||||
"required": True},
|
'required': True},
|
||||||
"ttl": {
|
'ttl': {
|
||||||
"type": "integer",
|
'type': 'integer',
|
||||||
"required": True},
|
'required': True},
|
||||||
"rules": {
|
'rules': {
|
||||||
"type": "array",
|
'type': 'array',
|
||||||
'items': {
|
'items': {
|
||||||
'type': "object",
|
'type': 'object',
|
||||||
"properties": {
|
'properties': {
|
||||||
'name': {
|
'name': {
|
||||||
'type': 'string'},
|
'type': 'string'},
|
||||||
'request_url': {
|
'request_url': {
|
||||||
@ -146,6 +199,40 @@ class ServiceSchema(schema_base.SchemaBase):
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'restrictions': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True},
|
||||||
|
'rules': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string'},
|
||||||
|
'request_url': {
|
||||||
|
'type': 'string'},
|
||||||
|
'http_host': {
|
||||||
|
'type': 'string'},
|
||||||
|
'client_ip': {
|
||||||
|
'type': 'string'},
|
||||||
|
'http_method': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': [
|
||||||
|
'GET',
|
||||||
|
'PUT',
|
||||||
|
'POST',
|
||||||
|
'PATCH']}}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'flavorRef': {
|
||||||
|
'type': 'string',
|
||||||
|
}
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ poppy.storage =
|
|||||||
poppy.provider =
|
poppy.provider =
|
||||||
fastly = poppy.provider.fastly:Driver
|
fastly = poppy.provider.fastly:Driver
|
||||||
mock = poppy.provider.mock:Driver
|
mock = poppy.provider.mock:Driver
|
||||||
|
cloudfront = poppy.provider.cloudfront:Driver
|
||||||
|
maxcdn = poppy.provider.maxcdn:Driver
|
||||||
|
|
||||||
[wheel]
|
[wheel]
|
||||||
universal = 1
|
universal = 1
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"all_fields": {
|
"all_fields": {
|
||||||
|
"name": "my_service_name",
|
||||||
"domain_list": [{"domain": "mywebsite.com"},
|
"domain_list": [{"domain": "mywebsite.com"},
|
||||||
{"domain": "blog.mywebsite.com"}],
|
{"domain": "blog.mywebsite.com"}],
|
||||||
"origin_list": [{"origins": "mywebsite.com",
|
"origin_list": [{"origins": "mywebsite.com",
|
||||||
"port": 443,
|
"port": 443,
|
||||||
"ssl": false}],
|
"ssl": false}],
|
||||||
|
"flavorRef": "standard",
|
||||||
"caching_list": [{"name": "default", "ttl": 3600},
|
"caching_list": [{"name": "default", "ttl": 3600},
|
||||||
{"name": "home",
|
{"name": "home",
|
||||||
"ttl": 1200,
|
"ttl": 1200,
|
||||||
@ -12,11 +14,13 @@
|
|||||||
"request_url" : "/index.htm"}]}]
|
"request_url" : "/index.htm"}]}]
|
||||||
},
|
},
|
||||||
"caching_empty": {
|
"caching_empty": {
|
||||||
|
"name": "my_service_name_2",
|
||||||
"domain_list": [{"domain": "mywebsite.com"},
|
"domain_list": [{"domain": "mywebsite.com"},
|
||||||
{"domain": "blog.mywebsite.com"}],
|
{"domain": "blog.mywebsite.com"}],
|
||||||
"origin_list": [{"origins": "mywebsite.com",
|
"origin_list": [{"origins": "mywebsite.com",
|
||||||
"port": 443,
|
"port": 443,
|
||||||
"ssl": false}],
|
"ssl": false}],
|
||||||
|
"flavorRef": "standard",
|
||||||
"caching_list": []
|
"caching_list": []
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -78,8 +78,9 @@ class PoppyClient(client.AutoMarshallingHTTPClient):
|
|||||||
PUT
|
PUT
|
||||||
services/{service_name}
|
services/{service_name}
|
||||||
"""
|
"""
|
||||||
url = '{0}/v1.0/services/{1}'.format(self.url, service_name)
|
url = '{0}/v1.0/services'.format(self.url)
|
||||||
request_object = requests.CreateService(domain_list=domain_list,
|
request_object = requests.CreateService(service_name=service_name,
|
||||||
|
domain_list=domain_list,
|
||||||
origin_list=origin_list,
|
origin_list=origin_list,
|
||||||
caching_list=caching_list)
|
caching_list=caching_list)
|
||||||
return self.request('PUT', url,
|
return self.request('PUT', url,
|
||||||
|
@ -21,15 +21,20 @@ from cafe.engine.models import base
|
|||||||
class CreateService(base.AutoMarshallingModel):
|
class CreateService(base.AutoMarshallingModel):
|
||||||
"""Marshalling for Create Service requests."""
|
"""Marshalling for Create Service requests."""
|
||||||
|
|
||||||
def __init__(self, domain_list=None, origin_list=None, caching_list=None):
|
def __init__(self, name=None, domain_list=None, origin_list=None,
|
||||||
|
flavorRef=None, caching_list=None):
|
||||||
super(CreateService, self).__init__()
|
super(CreateService, self).__init__()
|
||||||
|
|
||||||
|
self.service_name = name
|
||||||
self.domain_list = domain_list or []
|
self.domain_list = domain_list or []
|
||||||
self.origin_list = origin_list or []
|
self.origin_list = origin_list or []
|
||||||
|
self.flavorRef = flavorRef
|
||||||
self.caching_list = caching_list or []
|
self.caching_list = caching_list or []
|
||||||
|
|
||||||
def _obj_to_json(self):
|
def _obj_to_json(self):
|
||||||
create_service_request = {"domains": self.domain_list,
|
create_service_request = {"name": self.service_name,
|
||||||
|
"domains": self.domain_list,
|
||||||
"origins": self.origin_list,
|
"origins": self.origin_list,
|
||||||
|
"flavorRef": self.flavorRef,
|
||||||
"caching": self.caching_list}
|
"caching": self.caching_list}
|
||||||
return json.dumps(create_service_request)
|
return json.dumps(create_service_request)
|
||||||
|
@ -11,3 +11,7 @@ apikey = "MYAPIKEY"
|
|||||||
alias = "MYALIAS"
|
alias = "MYALIAS"
|
||||||
consumer_secret = "MYCONSUMER_SECRET"
|
consumer_secret = "MYCONSUMER_SECRET"
|
||||||
consumer_key = "MYCONSUMERKEY"
|
consumer_key = "MYCONSUMERKEY"
|
||||||
|
|
||||||
|
[drivers:provider:cloudfront]
|
||||||
|
aws_access_key_id = "MY_AWS_ACCESS_KEY_ID"
|
||||||
|
aws_secret_access_key = "MY_AWS_SECRET_ACCESS_KEY"
|
||||||
|
@ -52,4 +52,13 @@ keyspace = poppy
|
|||||||
database = poppy
|
database = poppy
|
||||||
|
|
||||||
[drivers:provider:fastly]
|
[drivers:provider:fastly]
|
||||||
apikey = "MYAPIKEY"
|
apikey = "MYAPIKEY"
|
||||||
|
|
||||||
|
[drivers:provider:maxcdn]
|
||||||
|
alias = "MYALIAS"
|
||||||
|
consumer_secret = "MYCONSUMER_SECRET"
|
||||||
|
consumer_key = "MYCONSUMERKEY"
|
||||||
|
|
||||||
|
[drivers:provider:cloudfront]
|
||||||
|
aws_access_key_id = "MY_AWS_ACCESS_KEY_ID"
|
||||||
|
aws_secret_access_key = "MY_AWS_SECRET_ACCESS_KEY"
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"using_all_fields": {
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"domains": [
|
||||||
|
{"domain": "test.mocksite.com" },
|
||||||
|
{"domain": "blog.mocksite.com"}
|
||||||
|
],
|
||||||
|
"origins": [
|
||||||
|
{
|
||||||
|
"origin": "mocksite.com",
|
||||||
|
"port": 80,
|
||||||
|
"ssl": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flavorRef": "standard",
|
||||||
|
"caching": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"ttl": 3600
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"restrictions": [
|
||||||
|
{
|
||||||
|
"name": "website only",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"http_host": "www.mocksite.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"missing_origin": {
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"domain": "my_domain.com"
|
||||||
|
},
|
||||||
|
"non_existing_flavor_input": {
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"domains": [
|
||||||
|
{"domain": "test.mocksite.com" },
|
||||||
|
{"domain": "blog.mocksite.com"}
|
||||||
|
],
|
||||||
|
"origins": [
|
||||||
|
{
|
||||||
|
"origin": "mocksite.com",
|
||||||
|
"port": 80,
|
||||||
|
"ssl": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flavorRef": "non_exist",
|
||||||
|
"caching": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"ttl": 3600
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"restrictions": [
|
||||||
|
{
|
||||||
|
"name": "website only",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"http_host": "www.mocksite.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"existing_name_service_json": {
|
||||||
|
"name": "mockdb1_service_name",
|
||||||
|
"domains": [
|
||||||
|
{"domain": "test.mocksite.com" },
|
||||||
|
{"domain": "blog.mocksite.com"}
|
||||||
|
],
|
||||||
|
"origins": [
|
||||||
|
{
|
||||||
|
"origin": "mocksite.com",
|
||||||
|
"port": 80,
|
||||||
|
"ssl": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flavorRef": "standard",
|
||||||
|
"caching": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"ttl": 3600
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"restrictions": [
|
||||||
|
{
|
||||||
|
"name": "website only",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"name": "mocksite.com",
|
||||||
|
"http_host": "www.mocksite.com"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ class FlavorControllerTest(base.FunctionalTest):
|
|||||||
self.assertEqual(200, response.status_code)
|
self.assertEqual(200, response.status_code)
|
||||||
|
|
||||||
def test_get_not_found(self):
|
def test_get_not_found(self):
|
||||||
response = self.app.get('/v1.0/flavors/{0}'.format(uuid.uuid1()),
|
response = self.app.get('/v1.0/flavors/{0}'.format("non_exist"),
|
||||||
status=404,
|
status=404,
|
||||||
expect_errors=True)
|
expect_errors=True)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import ddt
|
||||||
import pecan
|
import pecan
|
||||||
from webtest import app
|
from webtest import app
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ from poppy.transport.pecan.controllers import base as c_base
|
|||||||
from tests.functional.transport.pecan import base
|
from tests.functional.transport.pecan import base
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
class ServiceControllerTest(base.FunctionalTest):
|
class ServiceControllerTest(base.FunctionalTest):
|
||||||
|
|
||||||
def test_get_all(self):
|
def test_get_all(self):
|
||||||
@ -45,52 +47,30 @@ class ServiceControllerTest(base.FunctionalTest):
|
|||||||
self.assertTrue("domains" in response_dict)
|
self.assertTrue("domains" in response_dict)
|
||||||
self.assertTrue("origins" in response_dict)
|
self.assertTrue("origins" in response_dict)
|
||||||
|
|
||||||
def test_create(self):
|
@ddt.file_data("data_create_service.json")
|
||||||
|
def test_create(self, service_json):
|
||||||
# create with errorenous data: invalid json data
|
# create with errorenous data: invalid json data
|
||||||
self.assertRaises(app.AppError, self.app.put,
|
self.assertRaises(app.AppError, self.app.post,
|
||||||
'/v1.0/0001/services/fake_service_name_2',
|
'/v1.0/0001/services',
|
||||||
params="{", headers={
|
params="{", headers={
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# create with good data
|
||||||
|
response = self.app.post('/v1.0/0001/services',
|
||||||
|
params=json.dumps(service_json),
|
||||||
|
headers={"Content-Type": "application/json"})
|
||||||
|
self.assertEqual(202, response.status_code)
|
||||||
|
|
||||||
|
@ddt.file_data("data_create_service_bad_input_json.json")
|
||||||
|
def test_create_with_bad_input_json(self, service_json):
|
||||||
# create with errorenous data
|
# create with errorenous data
|
||||||
self.assertRaises(app.AppError, self.app.put,
|
self.assertRaises(app.AppError, self.app.post,
|
||||||
'/v1.0/0001/services/fake_service_name_2',
|
'/v1.0/0001/services',
|
||||||
params=json.dumps({
|
params=json.dumps(service_json), headers={
|
||||||
"domain": "www.mytest.com"
|
|
||||||
}), headers={
|
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
})
|
})
|
||||||
|
|
||||||
# create with good data
|
|
||||||
response = self.app.put('/v1.0/0001/services/fake_service_name_2',
|
|
||||||
params=json.dumps({
|
|
||||||
"domains": [
|
|
||||||
{"domain": "www.mywebsite.com"},
|
|
||||||
{"domain": "blog.mywebsite.com"},
|
|
||||||
],
|
|
||||||
"origins": [{"origin": "mywebsite.com",
|
|
||||||
"port": 80,
|
|
||||||
"ssl": False},
|
|
||||||
{"origin": "mywebsite.com",
|
|
||||||
}],
|
|
||||||
"caching": [{"name": "default",
|
|
||||||
"ttl": 3600},
|
|
||||||
{"name": "home",
|
|
||||||
"ttl": 17200,
|
|
||||||
"rules": [
|
|
||||||
{"name": "index",
|
|
||||||
"request_url":
|
|
||||||
"/index.htm"}]},
|
|
||||||
{"name": "images",
|
|
||||||
"ttl": 12800,
|
|
||||||
"rules": [
|
|
||||||
{"name": "images",
|
|
||||||
"request_url": "*.png"}]}
|
|
||||||
]}),
|
|
||||||
headers={"Content-Type": "application/json"})
|
|
||||||
self.assertEqual(200, response.status_code)
|
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
# update with erroneous data
|
# update with erroneous data
|
||||||
self.assertRaises(app.AppError, self.app.patch,
|
self.assertRaises(app.AppError, self.app.patch,
|
||||||
|
@ -27,7 +27,7 @@ from poppy.transport.validators.stoplight import rule
|
|||||||
|
|
||||||
class MockPecanEndpoint(object):
|
class MockPecanEndpoint(object):
|
||||||
|
|
||||||
testing_schema = service.ServiceSchema.get_schema("service", "PUT")
|
testing_schema = service.ServiceSchema.get_schema("service", "POST")
|
||||||
|
|
||||||
@decorators.validation_function
|
@decorators.validation_function
|
||||||
def is_valid_json(r):
|
def is_valid_json(r):
|
||||||
|
@ -48,8 +48,9 @@ class DummyRequest(object):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.headers = dict(header1='headervalue1')
|
self.headers = dict(header1='headervalue1')
|
||||||
self.method = "PUT"
|
self.method = "POST"
|
||||||
self.body = json.dumps({
|
self.body = json.dumps({
|
||||||
|
"name": "fake_service_name",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "www.mywebsite.com"},
|
{"domain": "www.mywebsite.com"},
|
||||||
{"domain": "blog.mywebsite.com"},
|
{"domain": "blog.mywebsite.com"},
|
||||||
@ -75,7 +76,8 @@ class DummyRequest(object):
|
|||||||
{"name": "images",
|
{"name": "images",
|
||||||
"ttl": 12800,
|
"ttl": 12800,
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"flavorRef": "https://www.poppycdn.io/v1.0/flavors/standard"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ class DummyRequestWithInvalidHeader(DummyRequest):
|
|||||||
fake_request_good = DummyRequest()
|
fake_request_good = DummyRequest()
|
||||||
fake_request_bad_missing_domain = DummyRequest()
|
fake_request_bad_missing_domain = DummyRequest()
|
||||||
fake_request_bad_missing_domain.body = json.dumps({
|
fake_request_bad_missing_domain.body = json.dumps({
|
||||||
|
"name": "fake_service_name",
|
||||||
"origins": [
|
"origins": [
|
||||||
{
|
{
|
||||||
"origin": "mywebsite.com",
|
"origin": "mywebsite.com",
|
||||||
@ -112,7 +115,8 @@ fake_request_bad_missing_domain.body = json.dumps({
|
|||||||
{"name": "images", "request_url": "*.png"}
|
{"name": "images", "request_url": "*.png"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"flavorRef": "https://www.poppycdn.io/v1.0/flavors/standard"
|
||||||
})
|
})
|
||||||
fake_request_bad_invalid_json_body = DummyRequest()
|
fake_request_bad_invalid_json_body = DummyRequest()
|
||||||
fake_request_bad_invalid_json_body.body = "{"
|
fake_request_bad_invalid_json_body.body = "{"
|
||||||
|
@ -24,7 +24,7 @@ from poppy.transport.validators.stoplight import rule
|
|||||||
from tests.functional.transport.validator import base
|
from tests.functional.transport.validator import base
|
||||||
|
|
||||||
|
|
||||||
testing_schema = service.ServiceSchema.get_schema("service", "PUT")
|
testing_schema = service.ServiceSchema.get_schema("service", "POST")
|
||||||
request_fit_schema = functools.partial(
|
request_fit_schema = functools.partial(
|
||||||
helpers.with_schema_falcon,
|
helpers.with_schema_falcon,
|
||||||
schema=testing_schema)
|
schema=testing_schema)
|
||||||
|
@ -31,8 +31,8 @@ class TestProviderWrapper(base.TestCase):
|
|||||||
# fake a provider details to work with unittest
|
# fake a provider details to work with unittest
|
||||||
self.fake_provider_details = {
|
self.fake_provider_details = {
|
||||||
"Fastly": provider_details.ProviderDetail(
|
"Fastly": provider_details.ProviderDetail(
|
||||||
id=uuid.uuid1(),
|
provider_service_id=uuid.uuid1(),
|
||||||
access_url='mydummywebsite.prod.fastly.com')}
|
access_urls='mydummywebsite.prod.fastly.com')}
|
||||||
|
|
||||||
def test_update_with_keyerror(self):
|
def test_update_with_keyerror(self):
|
||||||
mock_ext = mock.Mock(provider_name="no_existent_provider")
|
mock_ext = mock.Mock(provider_name="no_existent_provider")
|
||||||
@ -47,7 +47,7 @@ class TestProviderWrapper(base.TestCase):
|
|||||||
self.provider_wrapper_obj.update(mock_ext,
|
self.provider_wrapper_obj.update(mock_ext,
|
||||||
self.fake_provider_details, {})
|
self.fake_provider_details, {})
|
||||||
mock_ext.obj.service_controller.update.assert_called_once_with(
|
mock_ext.obj.service_controller.update.assert_called_once_with(
|
||||||
fastly_provider_detail.id,
|
fastly_provider_detail.provider_service_id,
|
||||||
{})
|
{})
|
||||||
|
|
||||||
def test_delete_with_keyerror(self):
|
def test_delete_with_keyerror(self):
|
||||||
@ -62,4 +62,4 @@ class TestProviderWrapper(base.TestCase):
|
|||||||
fastly_provider_detail = self.fake_provider_details["Fastly"]
|
fastly_provider_detail = self.fake_provider_details["Fastly"]
|
||||||
self.provider_wrapper_obj.delete(mock_ext, self.fake_provider_details)
|
self.provider_wrapper_obj.delete(mock_ext, self.fake_provider_details)
|
||||||
mock_ext.obj.service_controller.delete.assert_called_once_with(
|
mock_ext.obj.service_controller.delete.assert_called_once_with(
|
||||||
fastly_provider_detail.id)
|
fastly_provider_detail.provider_service_id)
|
||||||
|
@ -21,7 +21,9 @@ from oslo.config import cfg
|
|||||||
|
|
||||||
from poppy.manager.default import driver
|
from poppy.manager.default import driver
|
||||||
from poppy.manager.default import services
|
from poppy.manager.default import services
|
||||||
|
from poppy.model import flavor
|
||||||
from poppy.model.helpers import provider_details
|
from poppy.model.helpers import provider_details
|
||||||
|
from poppy.transport.pecan.models.request import service
|
||||||
from tests.unit import base
|
from tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@ -44,21 +46,98 @@ class DefaultManagerServiceTests(base.TestCase):
|
|||||||
|
|
||||||
self.project_id = 'mock_id'
|
self.project_id = 'mock_id'
|
||||||
self.service_name = 'mock_service'
|
self.service_name = 'mock_service'
|
||||||
self.service_json = ''
|
self.service_json = {
|
||||||
|
"name": "fake_service_name",
|
||||||
|
"domains": [
|
||||||
|
{"domain": "www.mywebsite.com"},
|
||||||
|
{"domain": "blog.mywebsite.com"},
|
||||||
|
],
|
||||||
|
"origins": [
|
||||||
|
{
|
||||||
|
"origin": "mywebsite.com",
|
||||||
|
"port": 80,
|
||||||
|
"ssl": False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"origin": "mywebsite.com",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"caching": [
|
||||||
|
{"name": "default", "ttl": 3600},
|
||||||
|
{"name": "home",
|
||||||
|
"ttl": 17200,
|
||||||
|
"rules": [
|
||||||
|
{"name": "index", "request_url": "/index.htm"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{"name": "images",
|
||||||
|
"ttl": 12800,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flavorRef": "https://www.poppycdn.io/v1.0/flavors/standard"
|
||||||
|
}
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
|
service_obj = service.load_from_json(self.service_json)
|
||||||
|
# fake one return value
|
||||||
|
self.sc.flavor_controller.get.return_value = flavor.Flavor(
|
||||||
|
"standard",
|
||||||
|
[flavor.Provider("cloudfront", "www.cloudfront.com"),
|
||||||
|
flavor.Provider("fastly", "www.fastly.com"),
|
||||||
|
flavor.Provider("mock", "www.mock_provider.com")]
|
||||||
|
)
|
||||||
|
|
||||||
self.sc.create(self.project_id, self.service_name, self.service_json)
|
providers = self.sc._driver.providers
|
||||||
|
|
||||||
|
# mock responses from provider_wrapper.create call
|
||||||
|
# to get code coverage
|
||||||
|
def get_provider_extension_by_name(name):
|
||||||
|
if name == "cloudfront":
|
||||||
|
return mock.Mock(
|
||||||
|
obj=mock.Mock(
|
||||||
|
service_controller=mock.Mock(
|
||||||
|
create=mock.Mock(
|
||||||
|
return_value={
|
||||||
|
'Cloudfront': {
|
||||||
|
'id':
|
||||||
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
||||||
|
'links': [
|
||||||
|
{
|
||||||
|
'href': 'www.mysite.com',
|
||||||
|
'rel': 'access_url'}],
|
||||||
|
'status': "in_progress"}}),
|
||||||
|
)))
|
||||||
|
elif name == "fastly":
|
||||||
|
return mock.Mock(obj=mock.Mock(service_controller=mock.Mock(
|
||||||
|
create=mock.Mock(return_value={
|
||||||
|
'Fastly': {'error': "fail to create servcice",
|
||||||
|
'error_detail': 'Fastly Create failed'
|
||||||
|
' because of XYZ'}})
|
||||||
|
)
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
return mock.Mock(
|
||||||
|
obj=mock.Mock(
|
||||||
|
service_controller=mock.Mock(
|
||||||
|
create=mock.Mock(
|
||||||
|
return_value={
|
||||||
|
name.title(): {
|
||||||
|
'id':
|
||||||
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
||||||
|
'links': [
|
||||||
|
{
|
||||||
|
'href': 'www.mysite.com',
|
||||||
|
'rel': 'access_url'}]}}),
|
||||||
|
)))
|
||||||
|
|
||||||
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
||||||
|
|
||||||
|
self.sc.create(self.project_id, service_obj)
|
||||||
|
|
||||||
# ensure the manager calls the storage driver with the appropriate data
|
# ensure the manager calls the storage driver with the appropriate data
|
||||||
self.sc.storage.create.assert_called_once_with(self.project_id,
|
self.sc.storage_controller.create.assert_called_once_with(
|
||||||
self.service_name,
|
self.project_id,
|
||||||
self.service_json)
|
service_obj)
|
||||||
# and that the providers are notified.
|
|
||||||
providers = self.sc._driver.providers
|
|
||||||
providers.map.assert_called_once_with(self.sc.provider_wrapper.create,
|
|
||||||
self.service_name,
|
|
||||||
self.service_json)
|
|
||||||
|
|
||||||
@ddt.file_data('data_provider_details.json')
|
@ddt.file_data('data_provider_details.json')
|
||||||
def test_update(self, provider_details_json):
|
def test_update(self, provider_details_json):
|
||||||
@ -67,27 +146,29 @@ class DefaultManagerServiceTests(base.TestCase):
|
|||||||
provider_detail_dict = json.loads(
|
provider_detail_dict = json.loads(
|
||||||
provider_details_json[provider_name]
|
provider_details_json[provider_name]
|
||||||
)
|
)
|
||||||
id = provider_detail_dict.get("id", None)
|
provider_service_id = provider_detail_dict.get(
|
||||||
access_url = provider_detail_dict.get("access_url", None)
|
"provider_service_id", None)
|
||||||
|
access_urls = provider_detail_dict.get("access_url", None)
|
||||||
status = provider_detail_dict.get("status", u'unknown')
|
status = provider_detail_dict.get("status", u'unknown')
|
||||||
provider_detail_obj = provider_details.ProviderDetail(
|
provider_detail_obj = provider_details.ProviderDetail(
|
||||||
id=id,
|
provider_service_id=provider_service_id,
|
||||||
access_url=access_url,
|
access_urls=access_urls,
|
||||||
status=status)
|
status=status)
|
||||||
self.provider_details[provider_name] = provider_detail_obj
|
self.provider_details[provider_name] = provider_detail_obj
|
||||||
|
|
||||||
providers = self.sc._driver.providers
|
providers = self.sc._driver.providers
|
||||||
|
|
||||||
self.sc.storage.get_provider_details.return_value = (
|
self.sc.storage_controller.get_provider_details.return_value = (
|
||||||
self.provider_details
|
self.provider_details
|
||||||
)
|
)
|
||||||
|
|
||||||
self.sc.update(self.project_id, self.service_name, self.service_json)
|
self.sc.update(self.project_id, self.service_name, self.service_json)
|
||||||
|
|
||||||
# ensure the manager calls the storage driver with the appropriate data
|
# ensure the manager calls the storage driver with the appropriate data
|
||||||
self.sc.storage.update.assert_called_once_with(self.project_id,
|
self.sc.storage_controller.update.assert_called_once_with(
|
||||||
self.service_name,
|
self.project_id,
|
||||||
self.service_json)
|
self.service_name,
|
||||||
|
self.service_json)
|
||||||
# and that the providers are notified.
|
# and that the providers are notified.
|
||||||
providers.map.assert_called_once_with(self.sc.provider_wrapper.update,
|
providers.map.assert_called_once_with(self.sc.provider_wrapper.update,
|
||||||
self.provider_details,
|
self.provider_details,
|
||||||
@ -100,24 +181,27 @@ class DefaultManagerServiceTests(base.TestCase):
|
|||||||
provider_detail_dict = json.loads(
|
provider_detail_dict = json.loads(
|
||||||
provider_details_json[provider_name]
|
provider_details_json[provider_name]
|
||||||
)
|
)
|
||||||
id = provider_detail_dict.get("id", None)
|
provider_service_id = provider_detail_dict.get(
|
||||||
access_url = provider_detail_dict.get("access_url", None)
|
"provider_service_id", None)
|
||||||
|
access_urls = provider_detail_dict.get("access_urls", None)
|
||||||
status = provider_detail_dict.get("status", u'unknown')
|
status = provider_detail_dict.get("status", u'unknown')
|
||||||
provider_detail_obj = provider_details.ProviderDetail(
|
provider_detail_obj = provider_details.ProviderDetail(
|
||||||
id=id,
|
provider_service_id=provider_service_id,
|
||||||
access_url=access_url,
|
access_urls=access_urls,
|
||||||
status=status)
|
status=status)
|
||||||
self.provider_details[provider_name] = provider_detail_obj
|
self.provider_details[provider_name] = provider_detail_obj
|
||||||
|
|
||||||
self.sc.storage.get_provider_details.return_value = (
|
self.sc.storage_controller.get_provider_details.return_value = (
|
||||||
self.provider_details
|
self.provider_details
|
||||||
)
|
)
|
||||||
|
|
||||||
self.sc.delete(self.project_id, self.service_name)
|
self.sc.delete(self.project_id, self.service_name)
|
||||||
|
|
||||||
# ensure the manager calls the storage driver with the appropriate data
|
# ensure the manager calls the storage driver with the appropriate data
|
||||||
self.sc.storage.delete.assert_called_once_with(self.project_id,
|
self.sc.storage_controller.delete.assert_called_once_with(
|
||||||
self.service_name)
|
self.project_id,
|
||||||
|
self.service_name
|
||||||
|
)
|
||||||
# and that the providers are notified.
|
# and that the providers are notified.
|
||||||
providers = self.sc._driver.providers
|
providers = self.sc._driver.providers
|
||||||
providers.map.assert_called_once_with(self.sc.provider_wrapper.delete,
|
providers.map.assert_called_once_with(self.sc.provider_wrapper.delete,
|
||||||
|
@ -53,7 +53,7 @@ class TestServiceModel(base.TestCase):
|
|||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
myservice = service.Service(
|
myservice = service.Service(
|
||||||
self.service_name, self.mydomains, self.myorigins,
|
self.service_name, self.mydomains, self.myorigins, self.flavorRef,
|
||||||
self.mycaching, self.myrestrictions)
|
self.mycaching, self.myrestrictions)
|
||||||
|
|
||||||
# test all properties
|
# test all properties
|
||||||
@ -76,6 +76,11 @@ class TestServiceModel(base.TestCase):
|
|||||||
myservice.origins = []
|
myservice.origins = []
|
||||||
self.assertEqual(myservice.origins, [])
|
self.assertEqual(myservice.origins, [])
|
||||||
|
|
||||||
|
# flavorRef
|
||||||
|
self.assertEqual(myservice.flavorRef, self.flavorRef)
|
||||||
|
myservice.flavorRef = "standard"
|
||||||
|
self.assertEqual(myservice.flavorRef, "standard")
|
||||||
|
|
||||||
self.assertEqual(myservice.restrictions, self.myrestrictions)
|
self.assertEqual(myservice.restrictions, self.myrestrictions)
|
||||||
myservice.restrictions = []
|
myservice.restrictions = []
|
||||||
self.assertEqual(myservice.restrictions, [])
|
self.assertEqual(myservice.restrictions, [])
|
||||||
@ -88,12 +93,24 @@ class TestServiceModel(base.TestCase):
|
|||||||
# status
|
# status
|
||||||
self.assertEqual(myservice.status, u'unknown')
|
self.assertEqual(myservice.status, u'unknown')
|
||||||
|
|
||||||
|
def test_init_from_dict_method(self):
|
||||||
|
# this should generate a service copy from my service
|
||||||
|
myservice = service.Service(
|
||||||
|
self.service_name, self.mydomains, self.myorigins, self.flavorRef,
|
||||||
|
self.mycaching, self.myrestrictions)
|
||||||
|
cloned_service = service.Service.init_from_dict(myservice.to_dict())
|
||||||
|
|
||||||
|
self.assertEqual(cloned_service.domains, myservice.domains)
|
||||||
|
self.assertEqual(cloned_service.origins, myservice.origins)
|
||||||
|
self.assertEqual(cloned_service.flavorRef, myservice.flavorRef)
|
||||||
|
|
||||||
@ddt.data(u'', u'apple')
|
@ddt.data(u'', u'apple')
|
||||||
def test_set_invalid_status(self, status):
|
def test_set_invalid_status(self, status):
|
||||||
myservice = service.Service(
|
myservice = service.Service(
|
||||||
self.service_name,
|
self.service_name,
|
||||||
self.mydomains,
|
self.mydomains,
|
||||||
self.myorigins)
|
self.myorigins,
|
||||||
|
self.flavorRef)
|
||||||
|
|
||||||
self.assertRaises(ValueError, setattr, myservice, 'status', status)
|
self.assertRaises(ValueError, setattr, myservice, 'status', status)
|
||||||
|
|
||||||
@ -102,7 +119,8 @@ class TestServiceModel(base.TestCase):
|
|||||||
myservice = service.Service(
|
myservice = service.Service(
|
||||||
self.service_name,
|
self.service_name,
|
||||||
self.mydomains,
|
self.mydomains,
|
||||||
self.myorigins)
|
self.myorigins,
|
||||||
|
self.flavorRef)
|
||||||
|
|
||||||
myservice.status = status
|
myservice.status = status
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"service_json": {
|
"service_json": {
|
||||||
|
"name" : "mysite.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "parsely.sage.com"},
|
{"domain": "parsely.sage.com"},
|
||||||
{"domain": "rosemary.thyme.net"}
|
{"domain": "rosemary.thyme.net"}
|
||||||
@ -7,6 +8,7 @@
|
|||||||
"origins": [
|
"origins": [
|
||||||
{"origin": "mydomain.com", "ssl": false, "port": 80},
|
{"origin": "mydomain.com", "ssl": false, "port": 80},
|
||||||
{"origin": "youdomain.com", "ssl": true, "port": 443}
|
{"origin": "youdomain.com", "ssl": true, "port": 443}
|
||||||
]
|
],
|
||||||
|
"flavorRef" : "standard"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ from boto import cloudfront
|
|||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
|
||||||
from poppy.provider.cloudfront import services
|
from poppy.provider.cloudfront import services
|
||||||
|
from poppy.transport.pecan.models.request import service
|
||||||
from tests.unit import base
|
from tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@ -46,30 +46,58 @@ class TestServices(base.TestCase):
|
|||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_server_error(self, service_json):
|
def test_create_server_error(self, service_json):
|
||||||
# create_distribution: CloudFrontServerError
|
# create_distribution: CloudFrontServerError
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
side_effect = cloudfront.exception.CloudFrontServerError(
|
side_effect = cloudfront.exception.CloudFrontServerError(
|
||||||
503, 'Service Unavailable')
|
503, 'Service Unavailable')
|
||||||
self.controller.client.create_distribution.side_effect = side_effect
|
self.controller.client.create_distribution.side_effect = side_effect
|
||||||
|
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_exception(self, service_json):
|
def test_create_exception(self, service_json):
|
||||||
# generic exception: Exception
|
# generic exception: Exception
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
self.controller.client.create_distribution.side_effect = Exception(
|
self.controller.client.create_distribution.side_effect = Exception(
|
||||||
'Creating service failed.')
|
'Creating service failed.')
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create(self, service_json):
|
def test_create_service_in_progress(self, service_json):
|
||||||
# clear run
|
# clear run
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
service_obj = service.load_from_json(service_json)
|
||||||
|
self.controller.client.create_distribution.return_value = (
|
||||||
|
mock.Mock(domain_name="jibberish.cloudfront.com",
|
||||||
|
id=uuid.uuid1(),
|
||||||
|
status="InProgress")
|
||||||
|
)
|
||||||
|
resp = self.controller.create(service_obj)
|
||||||
|
self.assertIn('links', resp[self.driver.provider_name])
|
||||||
|
|
||||||
|
@ddt.file_data('data_service.json')
|
||||||
|
def test_create_service_deployed(self, service_json):
|
||||||
|
# clear run
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
self.controller.client.create_distribution.return_value = (
|
||||||
|
mock.Mock(domain_name="jibberish.cloudfront.com",
|
||||||
|
id=uuid.uuid1(),
|
||||||
|
status="Deployed")
|
||||||
|
)
|
||||||
|
resp = self.controller.create(service_obj)
|
||||||
|
self.assertIn('links', resp[self.driver.provider_name])
|
||||||
|
|
||||||
|
@ddt.file_data('data_service.json')
|
||||||
|
def test_create_service_unknown(self, service_json):
|
||||||
|
# clear run
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('links', resp[self.driver.provider_name])
|
self.assertIn('links', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_update(self, service_json):
|
def test_update(self, service_json):
|
||||||
resp = self.controller.update(self.service_name, service_json)
|
service_obj = service.load_from_json(service_json)
|
||||||
|
resp = self.controller.update(self.service_name, service_obj)
|
||||||
self.assertIn('id', resp[self.driver.provider_name])
|
self.assertIn('id', resp[self.driver.provider_name])
|
||||||
|
|
||||||
def test_delete_exceptions(self):
|
def test_delete_exceptions(self):
|
||||||
@ -85,3 +113,8 @@ class TestServices(base.TestCase):
|
|||||||
|
|
||||||
def test_client(self):
|
def test_client(self):
|
||||||
self.assertNotEqual(self.controller.client(), None)
|
self.assertNotEqual(self.controller.client(), None)
|
||||||
|
|
||||||
|
def test_current_customer(self):
|
||||||
|
# TODO(tonytan4ever/obulpathi): fill in once correct
|
||||||
|
# current_customer logic is done
|
||||||
|
self.assertTrue(self.controller.current_customer is None)
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
"service_json": {
|
"service_json": {
|
||||||
|
"name" : "mysite.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "parsely.sage.com"},
|
{"domain": "parsely.sage.com"},
|
||||||
{"domain": "rosemary.thyme.net"}
|
{"domain": "rosemary.thyme.net"}
|
||||||
],
|
],
|
||||||
"origins": [
|
"origins": [
|
||||||
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
||||||
]
|
],
|
||||||
|
"flavorRef" : "standard"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import fastly
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from poppy.provider.fastly import services
|
from poppy.provider.fastly import services
|
||||||
|
from poppy.transport.pecan.models.request import service
|
||||||
from tests.unit import base
|
from tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@ -59,91 +60,118 @@ class TestServices(base.TestCase):
|
|||||||
def test_create_with_create_service_exception(self, service_json):
|
def test_create_with_create_service_exception(self, service_json):
|
||||||
# ASSERTIONS
|
# ASSERTIONS
|
||||||
# create_service
|
# create_service
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
self.controller.client.create_service.side_effect = fastly.FastlyError(
|
self.controller.client.create_service.side_effect = fastly.FastlyError(
|
||||||
Exception('Creating service failed.'))
|
Exception('Creating service failed.'))
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_with_create_version_exception(self, service_json):
|
def test_create_with_create_version_exception(self, service_json):
|
||||||
self.controller.client.reset_mock()
|
self.controller.client.reset_mock()
|
||||||
self.controller.client.create_service.side_effect = None
|
self.controller.client.create_service.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
# create_version
|
# create_version
|
||||||
self.controller.client.create_version.side_effect = fastly.FastlyError(
|
self.controller.client.create_version.side_effect = fastly.FastlyError(
|
||||||
Exception('Creating version failed.'))
|
Exception('Creating version failed.'))
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_with_create_domain_exception(self, service_json):
|
def test_create_with_create_domain_exception(self, service_json):
|
||||||
self.controller.client.reset_mock()
|
self.controller.client.reset_mock()
|
||||||
self.controller.client.create_version.side_effect = None
|
self.controller.client.create_version.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
# create domains
|
# create domains
|
||||||
self.controller.client.create_domain.side_effect = fastly.FastlyError(
|
self.controller.client.create_domain.side_effect = fastly.FastlyError(
|
||||||
Exception('Creating domains failed.'))
|
Exception('Creating domains failed.'))
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_with_create_backend_exception(self, service_json):
|
def test_create_with_create_backend_exception(self, service_json):
|
||||||
self.controller.client.reset_mock()
|
self.controller.client.reset_mock()
|
||||||
self.controller.client.create_domain.side_effect = None
|
self.controller.client.create_domain.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
# create backends
|
# create backends
|
||||||
self.controller.client.create_backend.side_effect = fastly.FastlyError(
|
self.controller.client.create_backend.side_effect = fastly.FastlyError(
|
||||||
Exception('Creating backend failed.'))
|
Exception('Creating backend failed.'))
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_with_check_domains_exception(self, service_json):
|
def test_create_with_check_domains_exception(self, service_json):
|
||||||
self.controller.client.reset_mock()
|
self.controller.client.reset_mock()
|
||||||
self.controller.client.create_backend.side_effect = None
|
self.controller.client.create_backend.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
self.controller.client.check_domains.side_effect = fastly.FastlyError(
|
self.controller.client.check_domains.side_effect = fastly.FastlyError(
|
||||||
Exception('Check_domains failed.'))
|
Exception('Check_domains failed.'))
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
|
@ddt.file_data('data_service.json')
|
||||||
|
def test_create_with_list_versions_exception(self, service_json):
|
||||||
|
self.controller.client.reset_mock()
|
||||||
|
self.controller.client.create_backend.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
|
self.controller.client.list_versions.side_effect = fastly.FastlyError(
|
||||||
|
Exception('List_versions failed.'))
|
||||||
|
resp = self.controller.create(service_obj)
|
||||||
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
|
@ddt.file_data('data_service.json')
|
||||||
|
def test_create_with_activate_version_exception(self, service_json):
|
||||||
|
self.controller.client.reset_mock()
|
||||||
|
self.controller.client.create_backend.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
|
self.controller.client.active_version.side_effect = fastly.FastlyError(
|
||||||
|
Exception('Active_version failed.'))
|
||||||
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create_with_general_exception(self, service_json):
|
def test_create_with_general_exception(self, service_json):
|
||||||
self.controller.client.reset_mock()
|
self.controller.client.reset_mock()
|
||||||
self.controller.client.check_domains.side_effect = None
|
self.controller.client.check_domains.side_effect = None
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
# test a general exception
|
# test a general exception
|
||||||
self.controller.client.create_service.side_effect = Exception(
|
self.controller.client.create_service.side_effect = Exception(
|
||||||
'Wild exception occurred.')
|
'Wild exception occurred.')
|
||||||
resp = self.controller.create(self.service_name, service_json)
|
resp = self.controller.create(service_obj)
|
||||||
self.assertIn('error', resp[self.driver.provider_name])
|
self.assertIn('error', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create(self, service_json):
|
def test_create(self, service_json):
|
||||||
# instantiate
|
# instantiate
|
||||||
# this case needs to set all return value for each call
|
# this case needs to set all return value for each call
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
|
||||||
controller = services.ServiceController(self.driver)
|
controller = services.ServiceController(self.driver)
|
||||||
|
|
||||||
controller.client.create_service.return_value = self.service_instance
|
controller.client.create_service.return_value = self.service_instance
|
||||||
controller.client.create_version.return_value = self.version
|
controller.client.create_version.return_value = self.version
|
||||||
|
controller.client.list_versions.return_value = [self.version]
|
||||||
|
controller.client.active_version.return_value = self.version
|
||||||
|
|
||||||
|
fastly_fake_domain_check = type(
|
||||||
|
'FastlyDomain', (object,), {
|
||||||
|
'name': 'fake_domain.global.prod.fastly.net'})
|
||||||
controller.client.check_domains.return_value = [
|
controller.client.check_domains.return_value = [
|
||||||
[{
|
mock.Mock(domain=fastly_fake_domain_check)
|
||||||
"name": "www.example.com",
|
|
||||||
"comment": "",
|
|
||||||
"service_id": "<fake_id>",
|
|
||||||
"version": "1",
|
|
||||||
"locked": True
|
|
||||||
},
|
|
||||||
"global.prod.fastly.net.",
|
|
||||||
True
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
resp = controller.create(self.service_name, service_json)
|
resp = controller.create(service_obj)
|
||||||
|
|
||||||
controller.client.create_service.assert_called_once_with(
|
controller.client.create_service.assert_called_once_with(
|
||||||
controller.current_customer.id, self.service_name)
|
controller.current_customer.id, service_obj.name)
|
||||||
|
|
||||||
controller.client.create_version.assert_called_once_with(
|
controller.client.create_version.assert_called_once_with(
|
||||||
self.service_instance.id)
|
self.service_instance.id)
|
||||||
@ -151,22 +179,22 @@ class TestServices(base.TestCase):
|
|||||||
controller.client.create_domain.assert_any_call(
|
controller.client.create_domain.assert_any_call(
|
||||||
self.service_instance.id,
|
self.service_instance.id,
|
||||||
self.version.number,
|
self.version.number,
|
||||||
service_json['domains'][0]['domain'])
|
service_obj.domains[0].domain)
|
||||||
|
|
||||||
controller.client.create_domain.assert_any_call(
|
controller.client.create_domain.assert_any_call(
|
||||||
self.service_instance.id,
|
self.service_instance.id,
|
||||||
self.version.number,
|
self.version.number,
|
||||||
service_json['domains'][1]['domain'])
|
service_obj.domains[1].domain)
|
||||||
|
|
||||||
controller.client.check_domains.assert_called_once_with(
|
controller.client.check_domains.assert_called_once_with(
|
||||||
self.service_instance.id, self.version.number)
|
self.service_instance.id, self.version.number)
|
||||||
|
|
||||||
controller.client.create_backend.assert_has_any_call(
|
controller.client.create_backend.assert_has_any_call(
|
||||||
self.service_instance.id, 1,
|
self.service_instance.id, 1,
|
||||||
service_json['origins'][0]['origin'],
|
service_obj.origins[0].origin.replace(":", "-"),
|
||||||
service_json['origins'][0]['origin'],
|
service_obj.origins[0].origin,
|
||||||
service_json['origins'][0]['ssl'],
|
service_obj.origins[0].ssl,
|
||||||
service_json['origins'][0]['port'])
|
service_obj.origins[0].port)
|
||||||
|
|
||||||
self.assertIn('links', resp[self.driver.provider_name])
|
self.assertIn('links', resp[self.driver.provider_name])
|
||||||
|
|
||||||
@ -231,10 +259,13 @@ class TestProviderValidation(base.TestCase):
|
|||||||
self.controller = services.ServiceController(self.driver)
|
self.controller = services.ServiceController(self.driver)
|
||||||
self.client = mock_client
|
self.client = mock_client
|
||||||
self.service_name = uuid.uuid1()
|
self.service_name = uuid.uuid1()
|
||||||
service_json = {"domains": [{"domain": "parsely.sage.com"}],
|
service_json = {"name": "mocksite.com",
|
||||||
|
"domains": [{"domain": "parsely.sage.com"}],
|
||||||
"origins": [{"origin": "mockdomain.com",
|
"origins": [{"origin": "mockdomain.com",
|
||||||
"ssl": False, "port": 80}]}
|
"ssl": False, "port": 80}],
|
||||||
self.controller.create(self.service_name, service_json)
|
"flavorRef": "standard"}
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
|
self.controller.create(service_obj)
|
||||||
|
|
||||||
@mock.patch('fastly.FastlyService')
|
@mock.patch('fastly.FastlyService')
|
||||||
def test_get_service_details(self, mock_service):
|
def test_get_service_details(self, mock_service):
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
"service_json": {
|
"service_json": {
|
||||||
|
"name" : "mysite.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "parsely.sage.com"},
|
{"domain": "parsely.sage.com"},
|
||||||
{"domain": "rosemary.thyme.net"}
|
{"domain": "rosemary.thyme.net"}
|
||||||
],
|
],
|
||||||
"origins": [
|
"origins": [
|
||||||
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
||||||
]
|
],
|
||||||
|
"flavorRef" : "standard"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (c) 2014 Rackspace, Inc.
|
# Copyright (c) 2014 Rackspace, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,6 +20,7 @@ from oslo.config import cfg
|
|||||||
|
|
||||||
from poppy.provider.maxcdn import driver
|
from poppy.provider.maxcdn import driver
|
||||||
from poppy.provider.maxcdn import services
|
from poppy.provider.maxcdn import services
|
||||||
|
from poppy.transport.pecan.models.request import service
|
||||||
from tests.unit import base
|
from tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ fake_maxcdn_client_get_return_value = {u'code': 200,
|
|||||||
|
|
||||||
fake_maxcdn_client_400_return_value = {
|
fake_maxcdn_client_400_return_value = {
|
||||||
u'code': 400,
|
u'code': 400,
|
||||||
u'message': "operation PUT/GET/POST failed due to technical difficulties.."
|
u'message': 'operation PUT/GET/POST failed due to technical difficulties..'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,8 +65,8 @@ class fake_maxcdn_api_client:
|
|||||||
def post(self, url=None, data=None):
|
def post(self, url=None, data=None):
|
||||||
return {u'code': 201,
|
return {u'code': 201,
|
||||||
u'data': {
|
u'data': {
|
||||||
u"pullzone": {
|
u'pullzone': {
|
||||||
u"cdn_url": u"newpullzone1.alias.netdna-cdn.com",
|
u'cdn_url': u'newpullzone1.alias.netdna-cdn.com',
|
||||||
u'name': u'newpullzone1',
|
u'name': u'newpullzone1',
|
||||||
u'id': u'97312'
|
u'id': u'97312'
|
||||||
}}}
|
}}}
|
||||||
@ -72,8 +74,8 @@ class fake_maxcdn_api_client:
|
|||||||
def put(self, url=None, params=None):
|
def put(self, url=None, params=None):
|
||||||
return {u'code': 200,
|
return {u'code': 200,
|
||||||
u'data': {
|
u'data': {
|
||||||
u"pullzone": {
|
u'pullzone': {
|
||||||
u"cdn_url": u"newpullzone1.alias.netdna-cdn.com",
|
u'cdn_url': u'newpullzone1.alias.netdna-cdn.com',
|
||||||
u'name': u'newpullzone1',
|
u'name': u'newpullzone1',
|
||||||
u'id': u'97312'
|
u'id': u'97312'
|
||||||
}}}
|
}}}
|
||||||
@ -91,19 +93,13 @@ class TestServices(base.TestCase):
|
|||||||
|
|
||||||
self.conf = cfg.ConfigOpts()
|
self.conf = cfg.ConfigOpts()
|
||||||
|
|
||||||
@mock.patch.object(driver, 'MAXCDN_OPTIONS', new=MAXCDN_OPTIONS)
|
|
||||||
def test_init(self):
|
|
||||||
provider = driver.CDNProvider(self.conf)
|
|
||||||
# instantiate will get
|
|
||||||
self.assertRaises(RuntimeError, services.ServiceController, provider)
|
|
||||||
|
|
||||||
@mock.patch.object(driver.CDNProvider, 'client',
|
@mock.patch.object(driver.CDNProvider, 'client',
|
||||||
new=fake_maxcdn_api_client())
|
new=fake_maxcdn_api_client())
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
new_driver = driver.CDNProvider(self.conf)
|
new_driver = driver.CDNProvider(self.conf)
|
||||||
# instantiate
|
# instantiate
|
||||||
controller = services.ServiceController(new_driver)
|
controller = services.ServiceController(new_driver)
|
||||||
service_name = "test_service_name"
|
service_name = 'test_service_name'
|
||||||
self.assertTrue(controller.get(service_name) is not None)
|
self.assertTrue(controller.get(service_name) is not None)
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
@ -114,8 +110,8 @@ class TestServices(base.TestCase):
|
|||||||
# instantiate
|
# instantiate
|
||||||
controller = services.ServiceController(new_driver)
|
controller = services.ServiceController(new_driver)
|
||||||
# test create, everything goes through successfully
|
# test create, everything goes through successfully
|
||||||
service_name = "test_service_name"
|
service_obj = service.load_from_json(service_json)
|
||||||
resp = controller.create(service_name, service_json)
|
resp = controller.create(service_obj)
|
||||||
self.assertIn('id', resp[new_driver.provider_name])
|
self.assertIn('id', resp[new_driver.provider_name])
|
||||||
self.assertIn('links', resp[new_driver.provider_name])
|
self.assertIn('links', resp[new_driver.provider_name])
|
||||||
|
|
||||||
@ -130,26 +126,23 @@ class TestServices(base.TestCase):
|
|||||||
driver.client.configure_mock(**{'get.return_value':
|
driver.client.configure_mock(**{'get.return_value':
|
||||||
fake_maxcdn_client_get_return_value
|
fake_maxcdn_client_get_return_value
|
||||||
})
|
})
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
service_name = "test_service_name"
|
|
||||||
|
|
||||||
controller_with_create_exception = services.ServiceController(driver)
|
controller_with_create_exception = services.ServiceController(driver)
|
||||||
controller_with_create_exception.client.configure_mock(**{
|
controller_with_create_exception.client.configure_mock(**{
|
||||||
"post.side_effect":
|
'post.side_effect':
|
||||||
RuntimeError('Creating service mysteriously failed.')})
|
RuntimeError('Creating service mysteriously failed.')})
|
||||||
resp = controller_with_create_exception.create(
|
resp = controller_with_create_exception.create(
|
||||||
service_name,
|
service_obj)
|
||||||
service_json)
|
|
||||||
self.assertIn('error', resp[driver.provider_name])
|
self.assertIn('error', resp[driver.provider_name])
|
||||||
|
|
||||||
controller_with_create_exception.client.reset_mock()
|
controller_with_create_exception.client.reset_mock()
|
||||||
controller_with_create_exception.client.configure_mock(**{
|
controller_with_create_exception.client.configure_mock(**{
|
||||||
'post.side_effect': None,
|
'post.side_effect': None,
|
||||||
"post.return_value": fake_maxcdn_client_400_return_value
|
'post.return_value': fake_maxcdn_client_400_return_value
|
||||||
})
|
})
|
||||||
resp = controller_with_create_exception.create(
|
resp = controller_with_create_exception.create(
|
||||||
service_name,
|
service_obj)
|
||||||
service_json)
|
|
||||||
self.assertIn('error', resp[driver.provider_name])
|
self.assertIn('error', resp[driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
@ -160,8 +153,9 @@ class TestServices(base.TestCase):
|
|||||||
# instantiate
|
# instantiate
|
||||||
controller = services.ServiceController(new_driver)
|
controller = services.ServiceController(new_driver)
|
||||||
# test create, everything goes through successfully
|
# test create, everything goes through successfully
|
||||||
service_name = "test_service_name"
|
service_obj = service.load_from_json(service_json)
|
||||||
resp = controller.update(service_name, service_json)
|
service_name = 'test_service_name'
|
||||||
|
resp = controller.update(service_name, service_obj)
|
||||||
self.assertIn('id', resp[new_driver.provider_name])
|
self.assertIn('id', resp[new_driver.provider_name])
|
||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
@ -176,11 +170,11 @@ class TestServices(base.TestCase):
|
|||||||
fake_maxcdn_client_get_return_value
|
fake_maxcdn_client_get_return_value
|
||||||
})
|
})
|
||||||
|
|
||||||
service_name = "test_service_name"
|
service_name = 'test_service_name'
|
||||||
|
|
||||||
controller_with_update_exception = services.ServiceController(driver)
|
controller_with_update_exception = services.ServiceController(driver)
|
||||||
controller_with_update_exception.client.configure_mock(**{
|
controller_with_update_exception.client.configure_mock(**{
|
||||||
"put.side_effect":
|
'put.side_effect':
|
||||||
RuntimeError('Updating service mysteriously failed.')})
|
RuntimeError('Updating service mysteriously failed.')})
|
||||||
resp = controller_with_update_exception.update(
|
resp = controller_with_update_exception.update(
|
||||||
service_name,
|
service_name,
|
||||||
@ -189,12 +183,13 @@ class TestServices(base.TestCase):
|
|||||||
|
|
||||||
controller_with_update_exception.client.reset_mock()
|
controller_with_update_exception.client.reset_mock()
|
||||||
controller_with_update_exception.client.configure_mock(**{
|
controller_with_update_exception.client.configure_mock(**{
|
||||||
"put.side_effect": None,
|
'put.side_effect': None,
|
||||||
"put.return_value": fake_maxcdn_client_400_return_value
|
'put.return_value': fake_maxcdn_client_400_return_value
|
||||||
})
|
})
|
||||||
|
service_obj = service.load_from_json(service_json)
|
||||||
resp = controller_with_update_exception.update(
|
resp = controller_with_update_exception.update(
|
||||||
service_name,
|
service_name,
|
||||||
service_json)
|
service_obj)
|
||||||
self.assertIn('error', resp[driver.provider_name])
|
self.assertIn('error', resp[driver.provider_name])
|
||||||
|
|
||||||
@mock.patch.object(driver.CDNProvider, 'client',
|
@mock.patch.object(driver.CDNProvider, 'client',
|
||||||
@ -204,7 +199,7 @@ class TestServices(base.TestCase):
|
|||||||
# instantiate
|
# instantiate
|
||||||
controller = services.ServiceController(new_driver)
|
controller = services.ServiceController(new_driver)
|
||||||
# test create, everything goes through successfully
|
# test create, everything goes through successfully
|
||||||
service_name = "test_service_name"
|
service_name = 'test_service_name'
|
||||||
resp = controller.delete(service_name)
|
resp = controller.delete(service_name)
|
||||||
self.assertIn('id', resp[new_driver.provider_name])
|
self.assertIn('id', resp[new_driver.provider_name])
|
||||||
|
|
||||||
@ -219,11 +214,11 @@ class TestServices(base.TestCase):
|
|||||||
fake_maxcdn_client_get_return_value
|
fake_maxcdn_client_get_return_value
|
||||||
})
|
})
|
||||||
|
|
||||||
service_name = "test_service_name"
|
service_name = 'test_service_name'
|
||||||
|
|
||||||
controller_with_delete_exception = services.ServiceController(driver)
|
controller_with_delete_exception = services.ServiceController(driver)
|
||||||
controller_with_delete_exception.client.configure_mock(**{
|
controller_with_delete_exception.client.configure_mock(**{
|
||||||
"delete.side_effect":
|
'delete.side_effect':
|
||||||
RuntimeError('Deleting service mysteriously failed.')})
|
RuntimeError('Deleting service mysteriously failed.')})
|
||||||
resp = controller_with_delete_exception.delete(service_name)
|
resp = controller_with_delete_exception.delete(service_name)
|
||||||
self.assertEqual(resp[driver.provider_name]['error'],
|
self.assertEqual(resp[driver.provider_name]['error'],
|
||||||
@ -231,9 +226,57 @@ class TestServices(base.TestCase):
|
|||||||
|
|
||||||
controller_with_delete_exception.client.reset_mock()
|
controller_with_delete_exception.client.reset_mock()
|
||||||
controller_with_delete_exception.client.configure_mock(**{
|
controller_with_delete_exception.client.configure_mock(**{
|
||||||
"delete.side_effect": None,
|
'delete.side_effect': None,
|
||||||
"delete.return_value": fake_maxcdn_client_400_return_value
|
'delete.return_value': fake_maxcdn_client_400_return_value
|
||||||
})
|
})
|
||||||
resp = controller_with_delete_exception.delete(service_name)
|
resp = controller_with_delete_exception.delete(service_name)
|
||||||
self.assertEqual(resp[driver.provider_name]['error'],
|
self.assertEqual(resp[driver.provider_name]['error'],
|
||||||
'failed to delete service')
|
'failed to delete service')
|
||||||
|
|
||||||
|
@ddt.data('good-service-name', 'yahooservice')
|
||||||
|
@mock.patch.object(driver.CDNProvider, 'client',
|
||||||
|
new=fake_maxcdn_api_client())
|
||||||
|
def test_map_service_name_no_hash(self, service_name):
|
||||||
|
maxcdn_driver = driver.CDNProvider(self.conf)
|
||||||
|
controller = services.ServiceController(maxcdn_driver)
|
||||||
|
self.assertEqual(controller._map_service_name(service_name),
|
||||||
|
service_name)
|
||||||
|
|
||||||
|
@ddt.data(u'www.düsseldorf-Lörick.com', 'yahoo%_notvalid')
|
||||||
|
@mock.patch.object(driver.CDNProvider, 'client',
|
||||||
|
new=fake_maxcdn_api_client())
|
||||||
|
def test_map_service_name_with_hash(self, service_name):
|
||||||
|
maxcdn_driver = driver.CDNProvider(self.conf)
|
||||||
|
controller = services.ServiceController(maxcdn_driver)
|
||||||
|
# test hashed
|
||||||
|
self.assertNotEqual(controller._map_service_name(service_name),
|
||||||
|
service_name)
|
||||||
|
# test deterministic-ity
|
||||||
|
self.assertEqual(controller._map_service_name(service_name),
|
||||||
|
controller._map_service_name(service_name))
|
||||||
|
|
||||||
|
@mock.patch.object(driver.CDNProvider, 'client',
|
||||||
|
new=fake_maxcdn_api_client())
|
||||||
|
def test_current_customer(self):
|
||||||
|
new_driver = driver.CDNProvider(self.conf)
|
||||||
|
# instantiate
|
||||||
|
controller = services.ServiceController(new_driver)
|
||||||
|
self.assertTrue(controller.current_customer['name'] ==
|
||||||
|
u'<My_fake_company_alias>')
|
||||||
|
|
||||||
|
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider.client')
|
||||||
|
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider')
|
||||||
|
def test_current_customer_error(self, mock_controllerclient, mock_driver):
|
||||||
|
# test create with exceptions
|
||||||
|
driver = mock_driver()
|
||||||
|
driver.attach_mock(mock_controllerclient, 'client')
|
||||||
|
driver.client.configure_mock(**{'get.return_value':
|
||||||
|
fake_maxcdn_client_400_return_value
|
||||||
|
})
|
||||||
|
|
||||||
|
controller = services.ServiceController(mock_driver)
|
||||||
|
# for some reason self.assertRaises doesn't work
|
||||||
|
try:
|
||||||
|
controller.current_customer
|
||||||
|
except RuntimeError as e:
|
||||||
|
self.assertTrue(str(e) == "Get maxcdn current customer failed...")
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
{
|
{
|
||||||
"service_json": {
|
"service_json": {
|
||||||
|
"name" : "mysite.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "parsely.sage.com"},
|
{"domain": "parsely.sage.com"},
|
||||||
{"domain": "rosemary.thyme.net"}
|
{"domain": "rosemary.thyme.net"}
|
||||||
],
|
],
|
||||||
"origins": [
|
"origins": [
|
||||||
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
||||||
]
|
],
|
||||||
|
"flavorRef" : "standard"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (c) 2014 Rackspace, Inc.
|
# Copyright (c) 2014 Rackspace, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,6 +20,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from poppy.provider.mock import services
|
from poppy.provider.mock import services
|
||||||
|
from poppy.transport.pecan.models.request import service
|
||||||
from tests.unit import base
|
from tests.unit import base
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +36,8 @@ class MockProviderServicesTest(base.TestCase):
|
|||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_update(self, service_json):
|
def test_update(self, service_json):
|
||||||
response = self.sc.update(self.test_provider_service_id, service_json)
|
service_obj = service.load_from_json(service_json)
|
||||||
|
response = self.sc.update(self.test_provider_service_id, service_obj)
|
||||||
self.assertTrue(response is not None)
|
self.assertTrue(response is not None)
|
||||||
|
|
||||||
def test_delete(self):
|
def test_delete(self):
|
||||||
@ -47,5 +50,14 @@ class MockProviderServicesTest(base.TestCase):
|
|||||||
|
|
||||||
@ddt.file_data('data_service.json')
|
@ddt.file_data('data_service.json')
|
||||||
def test_create(self, service_json):
|
def test_create(self, service_json):
|
||||||
response = self.sc.create("mock_name", service_json)
|
service_obj = service.load_from_json(service_json)
|
||||||
|
response = self.sc.create(service_obj)
|
||||||
self.assertTrue(response is not None)
|
self.assertTrue(response is not None)
|
||||||
|
|
||||||
|
@ddt.data("my_mock_service.com", u'www.düsseldorf-Lörick.com')
|
||||||
|
def test__map_service_name(self, service_name):
|
||||||
|
self.assertTrue(self.sc._map_service_name(service_name),
|
||||||
|
service_name)
|
||||||
|
|
||||||
|
def test_current_customer(self):
|
||||||
|
self.assertTrue(self.sc.current_customer is None)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"using_all_fields": [
|
"using_all_fields": [
|
||||||
{
|
{
|
||||||
"name" : "mocksite",
|
"service_name" : "mocksite",
|
||||||
"domains": [
|
"domains": [
|
||||||
"{\"domain\": \"www.mocksite.com\"}",
|
"{\"domain\": \"www.mocksite.com\"}",
|
||||||
"{\"domain\": \"blog.mocksite.com\"}"
|
"{\"domain\": \"blog.mocksite.com\"}"
|
||||||
@ -12,6 +12,7 @@
|
|||||||
"caching": [
|
"caching": [
|
||||||
"{\"name\": \"default\", \"ttl\": 3600}"
|
"{\"name\": \"default\", \"ttl\": 3600}"
|
||||||
],
|
],
|
||||||
|
"flavor_id" : "standard",
|
||||||
"restrictions": [
|
"restrictions": [
|
||||||
"{\"rules\": [{\"http_host\": \"www.mocksite.com\", \"name\": \"mocksite.com\"}], \"name\": \"website only\"}"
|
"{\"rules\": [{\"http_host\": \"www.mocksite.com\", \"name\": \"mocksite.com\"}], \"name\": \"website only\"}"
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"using_all_fields": [
|
"using_all_fields": [
|
||||||
{
|
{
|
||||||
"name": "mocksite",
|
"service_name": "mocksite",
|
||||||
"domain": [
|
"domain": [
|
||||||
"{\"domain\": \"www.mocksite.com\"}",
|
"{\"domain\": \"www.mocksite.com\"}",
|
||||||
"{\"domain\": \"blog.mocksite.com\"}"
|
"{\"domain\": \"blog.mocksite.com\"}"
|
||||||
@ -9,6 +9,7 @@
|
|||||||
"origin": [
|
"origin": [
|
||||||
"{\"origin\": \"mocksite.com\", \"ssl\": false, \"port\": 80}"
|
"{\"origin\": \"mocksite.com\", \"ssl\": false, \"port\": 80}"
|
||||||
],
|
],
|
||||||
|
"flavor_id" : "standard",
|
||||||
"caching": [
|
"caching": [
|
||||||
"{\"name\": \"default\", \"ttl\": 3600}"
|
"{\"name\": \"default\", \"ttl\": 3600}"
|
||||||
],
|
],
|
||||||
@ -17,7 +18,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "another_mocksite",
|
"service_name": "another_mocksite",
|
||||||
"domain": [
|
"domain": [
|
||||||
"{\"domain\": \"www.mocksite.co.uk\"}",
|
"{\"domain\": \"www.mocksite.co.uk\"}",
|
||||||
"{\"domain\": \"blog.mocksite.co.uk\"}"
|
"{\"domain\": \"blog.mocksite.co.uk\"}"
|
||||||
@ -25,6 +26,7 @@
|
|||||||
"origin": [
|
"origin": [
|
||||||
"{\"origin\": \"mocksite.co.uk\", \"ssl\": false, \"port\": 80}"
|
"{\"origin\": \"mocksite.co.uk\", \"ssl\": false, \"port\": 80}"
|
||||||
],
|
],
|
||||||
|
"flavor_id" : "premium",
|
||||||
"caching":[
|
"caching":[
|
||||||
"{\"name\": \"default\", \"ttl\": 3600}"
|
"{\"name\": \"default\", \"ttl\": 3600}"
|
||||||
],
|
],
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"provider_details":
|
"provider_details":
|
||||||
{
|
{
|
||||||
"MaxCDN": "{\"id\": 11942, \"access_url\": \"mypullzone.netdata.com\"}",
|
"MaxCDN": "{\"provider_service_id\": 11942, \"access_urls\": [\"mypullzone.netdata.com\"]}",
|
||||||
"Mock": "{\"id\": 73242, \"access_url\": \"mycdn.mock.com\"}",
|
"Mock": "{\"provider_service_id\": 73242, \"access_urls\": [\"mycdn.mock.com\"]}",
|
||||||
"CloudFront": "{\"id\": \"5ABC892\", \"access_url\": \"cf123.cloudcf.com\"}",
|
"CloudFront": "{\"provider_service_id\": \"5ABC892\", \"access_urls\": [\"cf123.cloudcf.com\"]}",
|
||||||
"Fastly": "{\"id\": 3488, \"access_url\": \"mockcf123.fastly.prod.com\"}"
|
"Fastly": "{\"provider_service_id\": 3488, \"access_urls\": [\"mockcf123.fastly.prod.com\"]}"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ import ddt
|
|||||||
import mock
|
import mock
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
from poppy.model import flavor as model_flavor
|
||||||
from poppy.storage.cassandra import driver
|
from poppy.storage.cassandra import driver
|
||||||
from poppy.storage.cassandra import flavors
|
from poppy.storage.cassandra import flavors
|
||||||
from poppy.transport.pecan.models.request import flavor
|
from poppy.transport.pecan.models.request import flavor
|
||||||
@ -70,6 +71,10 @@ class CassandraStorageFlavorsTests(base.TestCase):
|
|||||||
@mock.patch.object(flavors.FlavorsController, 'session')
|
@mock.patch.object(flavors.FlavorsController, 'session')
|
||||||
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
def test_add_flavor(self, value, mock_session, mock_execute):
|
def test_add_flavor(self, value, mock_session, mock_execute):
|
||||||
|
self.fc.get = mock.Mock(side_effect=LookupError(
|
||||||
|
"More than one flavor/no record was retrieved."
|
||||||
|
))
|
||||||
|
|
||||||
# mock the response from cassandra
|
# mock the response from cassandra
|
||||||
mock_execute.execute.return_value = value
|
mock_execute.execute.return_value = value
|
||||||
|
|
||||||
@ -79,6 +84,20 @@ class CassandraStorageFlavorsTests(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(actual_response, None)
|
self.assertEqual(actual_response, None)
|
||||||
|
|
||||||
|
@ddt.file_data('../data/data_create_flavor.json')
|
||||||
|
@mock.patch.object(flavors.FlavorsController, 'session')
|
||||||
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
|
def test_add_flavor_exist(self, value, mock_session, mock_execute):
|
||||||
|
self.fc.get = mock.Mock(return_value=model_flavor.Flavor(
|
||||||
|
flavor_id=value['id']
|
||||||
|
))
|
||||||
|
|
||||||
|
# mock the response from cassandra
|
||||||
|
mock_execute.execute.return_value = value
|
||||||
|
new_flavor = flavor.load_from_json(value)
|
||||||
|
|
||||||
|
self.assertRaises(ValueError, self.fc.add, new_flavor)
|
||||||
|
|
||||||
@ddt.file_data('data_list_flavors.json')
|
@ddt.file_data('data_list_flavors.json')
|
||||||
@mock.patch.object(flavors.FlavorsController, 'session')
|
@mock.patch.object(flavors.FlavorsController, 'session')
|
||||||
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
|
@ -13,12 +13,14 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
import cassandra
|
import cassandra
|
||||||
import ddt
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from poppy.model import service
|
from poppy.model.helpers import provider_details
|
||||||
from poppy.storage.cassandra import driver
|
from poppy.storage.cassandra import driver
|
||||||
from poppy.storage.cassandra import services
|
from poppy.storage.cassandra import services
|
||||||
from poppy.transport.pecan.models.request import service as req_service
|
from poppy.transport.pecan.models.request import service as req_service
|
||||||
@ -63,7 +65,7 @@ class CassandraStorageServiceTests(base.TestCase):
|
|||||||
# mock the response from cassandra
|
# mock the response from cassandra
|
||||||
mock_execute.execute.return_value = []
|
mock_execute.execute.return_value = []
|
||||||
|
|
||||||
self.assertRaises(ValueError, self.sc.get,
|
self.assertRaises(LookupError, self.sc.get,
|
||||||
self.project_id, self.service_name)
|
self.project_id, self.service_name)
|
||||||
|
|
||||||
@ddt.file_data('../data/data_create_service.json')
|
@ddt.file_data('../data/data_create_service.json')
|
||||||
@ -71,10 +73,8 @@ class CassandraStorageServiceTests(base.TestCase):
|
|||||||
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
def test_create_service(self, value, mock_session, mock_execute):
|
def test_create_service(self, value, mock_session, mock_execute):
|
||||||
value.update({'name': self.service_name})
|
value.update({'name': self.service_name})
|
||||||
request_service = req_service.load_from_json(value)
|
service_obj = req_service.load_from_json(value)
|
||||||
service_obj = service.Service.init_from_dict(request_service.to_dict())
|
responses = self.sc.create(self.project_id, service_obj)
|
||||||
responses = self.sc.create(self.project_id, self.service_name,
|
|
||||||
service_obj)
|
|
||||||
|
|
||||||
# Expect the response to be None as there are no providers passed
|
# Expect the response to be None as there are no providers passed
|
||||||
# into the driver to respond to this call
|
# into the driver to respond to this call
|
||||||
@ -82,6 +82,18 @@ class CassandraStorageServiceTests(base.TestCase):
|
|||||||
|
|
||||||
# TODO(amitgandhinz): need to validate the create to cassandra worked.
|
# TODO(amitgandhinz): need to validate the create to cassandra worked.
|
||||||
|
|
||||||
|
@ddt.file_data('../data/data_create_service.json')
|
||||||
|
@mock.patch.object(services.ServicesController, 'session')
|
||||||
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
|
def test_create_service_exist(self, value, mock_session, mock_execute):
|
||||||
|
value.update({'name': self.service_name})
|
||||||
|
service_obj = req_service.load_from_json(value)
|
||||||
|
self.sc.get = mock.Mock(return_value=service_obj)
|
||||||
|
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
self.sc.create,
|
||||||
|
self.project_id, service_obj)
|
||||||
|
|
||||||
@ddt.file_data('data_list_services.json')
|
@ddt.file_data('data_list_services.json')
|
||||||
@mock.patch.object(services.ServicesController, 'session')
|
@mock.patch.object(services.ServicesController, 'session')
|
||||||
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
@ -133,6 +145,47 @@ class CassandraStorageServiceTests(base.TestCase):
|
|||||||
self.assertTrue("CloudFront" in actual_response)
|
self.assertTrue("CloudFront" in actual_response)
|
||||||
self.assertTrue("Fastly" in actual_response)
|
self.assertTrue("Fastly" in actual_response)
|
||||||
|
|
||||||
|
@ddt.file_data('data_provider_details.json')
|
||||||
|
@mock.patch.object(services.ServicesController, 'session')
|
||||||
|
@mock.patch.object(cassandra.cluster.Session, 'execute')
|
||||||
|
def test_update_provider_details(self, provider_details_json,
|
||||||
|
mock_session, mock_execute):
|
||||||
|
provider_details_dict = {}
|
||||||
|
for k, v in provider_details_json.items():
|
||||||
|
provider_detail_dict = json.loads(v)
|
||||||
|
provider_details_dict[k] = provider_details.ProviderDetail(
|
||||||
|
provider_service_id=(
|
||||||
|
provider_detail_dict["provider_service_id"]),
|
||||||
|
access_urls=provider_detail_dict["access_urls"])
|
||||||
|
|
||||||
|
# mock the response from cassandra
|
||||||
|
mock_execute.execute.return_value = None
|
||||||
|
|
||||||
|
self.sc.update_provider_details(
|
||||||
|
self.project_id,
|
||||||
|
self.service_name,
|
||||||
|
provider_details_dict)
|
||||||
|
|
||||||
|
# this is for update_provider_details unittest code coverage
|
||||||
|
arg_provider_details_dict = {}
|
||||||
|
for provider_name in provider_details_dict:
|
||||||
|
arg_provider_details_dict[provider_name] = json.dumps({
|
||||||
|
"id": provider_details_dict[provider_name].provider_service_id,
|
||||||
|
"access_urls": (
|
||||||
|
provider_details_dict[provider_name].access_urls),
|
||||||
|
"status": provider_details_dict[provider_name].status,
|
||||||
|
"name": provider_details_dict[provider_name].name,
|
||||||
|
"error_info": None
|
||||||
|
})
|
||||||
|
args = {
|
||||||
|
'project_id': self.project_id,
|
||||||
|
'service_name': self.service_name,
|
||||||
|
'provider_details': arg_provider_details_dict
|
||||||
|
}
|
||||||
|
|
||||||
|
mock_execute.execute.assert_called_once_with(
|
||||||
|
services.CQL_UPDATE_PROVIDER_DETAILS, args)
|
||||||
|
|
||||||
@mock.patch.object(cassandra.cluster.Cluster, 'connect')
|
@mock.patch.object(cassandra.cluster.Cluster, 'connect')
|
||||||
def test_session(self, mock_service_database):
|
def test_session(self, mock_service_database):
|
||||||
session = self.sc.session
|
session = self.sc.session
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"using_all_fields": {
|
"using_all_fields": {
|
||||||
|
"name": "mocksite.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{"domain": "test.mocksite.com" },
|
{"domain": "test.mocksite.com" },
|
||||||
{"domain": "blog.mocksite.com"}
|
{"domain": "blog.mocksite.com"}
|
||||||
@ -11,6 +12,7 @@
|
|||||||
"ssl": false
|
"ssl": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"flavorRef": "standard",
|
||||||
"caching": [
|
"caching": [
|
||||||
{
|
{
|
||||||
"name": "default",
|
"name": "default",
|
||||||
|
@ -45,7 +45,7 @@ class MockDBStorageFlavorsTests(base.TestCase):
|
|||||||
|
|
||||||
actual_response = self.fc.get(self.flavor_id)
|
actual_response = self.fc.get(self.flavor_id)
|
||||||
|
|
||||||
self.assertEqual(actual_response, None)
|
self.assertEqual(actual_response.flavor_id, "standard")
|
||||||
|
|
||||||
@mock.patch.object(flavors.FlavorsController, 'session')
|
@mock.patch.object(flavors.FlavorsController, 'session')
|
||||||
@ddt.file_data('../data/data_create_flavor.json')
|
@ddt.file_data('../data/data_create_flavor.json')
|
||||||
@ -61,7 +61,8 @@ class MockDBStorageFlavorsTests(base.TestCase):
|
|||||||
actual_response = self.fc.list()
|
actual_response = self.fc.list()
|
||||||
|
|
||||||
# confirm the correct number of results are returned
|
# confirm the correct number of results are returned
|
||||||
self.assertEqual(actual_response, [])
|
self.assertEqual(len(actual_response), 1)
|
||||||
|
self.assertEqual(actual_response[0].flavor_id, "standard")
|
||||||
|
|
||||||
@mock.patch.object(flavors.FlavorsController, 'session')
|
@mock.patch.object(flavors.FlavorsController, 'session')
|
||||||
def test_delete_flavor(self, mock_session):
|
def test_delete_flavor(self, mock_session):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user