
- Add stevedore capability to load different metrics drivers, once their corresponding classes are built into poppy. Partially Implements: blueprint analytics Change-Id: Icb25ddccd0582bb6db34827995bce0f9af2087f0
1008 lines
41 KiB
Python
1008 lines
41 KiB
Python
# Copyright (c) 2014 Rackspace, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import json
|
|
import random
|
|
import uuid
|
|
|
|
import ddt
|
|
import mock
|
|
from oslo_config import cfg
|
|
import requests
|
|
import six
|
|
|
|
from poppy.distributed_task.taskflow.task import common
|
|
from poppy.distributed_task.taskflow.task import create_service_tasks
|
|
from poppy.distributed_task.taskflow.task import delete_service_tasks
|
|
from poppy.distributed_task.taskflow.task import purge_service_tasks
|
|
from poppy.distributed_task.taskflow.task import update_service_tasks
|
|
from poppy.distributed_task.utils import memoized_controllers
|
|
from poppy.manager.default import driver
|
|
|
|
|
|
from poppy.manager.default import services
|
|
from poppy.model import flavor
|
|
from poppy.model.helpers import provider_details
|
|
from poppy.transport.pecan.models.request import service
|
|
from tests.unit import base
|
|
|
|
|
|
class Elapsed(object):
|
|
def __init__(self, time):
|
|
self.time = time
|
|
|
|
def total_seconds(self):
|
|
return self.time
|
|
|
|
|
|
class Response(object):
|
|
|
|
def __init__(self, resp_status, resp_json=None):
|
|
self.resp_status = resp_status
|
|
self.resp_json = resp_json
|
|
|
|
def headers(self):
|
|
return {}
|
|
|
|
@property
|
|
def ok(self):
|
|
return self.resp_status
|
|
|
|
def json(self):
|
|
return self.resp_json
|
|
|
|
@property
|
|
def elapsed(self):
|
|
return Elapsed(0.1)
|
|
|
|
|
|
class MonkeyPatchControllers(object):
|
|
|
|
def __init__(self, service_controller,
|
|
dns_controller,
|
|
storage_controller, func):
|
|
self.service_controller = service_controller
|
|
self.dns_controller = dns_controller
|
|
self.storage_controller = storage_controller
|
|
self.func = func
|
|
|
|
def __enter__(self):
|
|
def monkey_task_controllers(program, controller=None):
|
|
|
|
if controller == 'storage':
|
|
return self.service_controller, self.storage_controller
|
|
if controller == 'dns':
|
|
return self.service_controller, self.dns_controller
|
|
else:
|
|
return self.service_controller
|
|
|
|
memoized_controllers.task_controllers = monkey_task_controllers
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
memoized_controllers.task_controllers = self.func
|
|
|
|
|
|
@ddt.ddt
|
|
class DefaultManagerServiceTests(base.TestCase):
|
|
|
|
@mock.patch('poppy.bootstrap.Bootstrap')
|
|
@mock.patch('poppy.notification.base.driver.NotificationDriverBase')
|
|
@mock.patch('poppy.dns.base.driver.DNSDriverBase')
|
|
@mock.patch('poppy.storage.base.driver.StorageDriverBase')
|
|
@mock.patch('poppy.distributed_task.base.driver.DistributedTaskDriverBase')
|
|
@mock.patch('poppy.metrics.base.driver.MetricsDriverBase')
|
|
def setUp(self, mock_distributed_task, mock_storage,
|
|
mock_dns, mock_notification, mock_bootstrap, mock_metrics):
|
|
# NOTE(TheSriram): the mock.patch decorator applies mocks
|
|
# in the reverse order of the arguments present
|
|
super(DefaultManagerServiceTests, self).setUp()
|
|
|
|
# create mocked config and driver
|
|
conf = cfg.ConfigOpts()
|
|
|
|
_DRIVER_DNS_OPTIONS = [
|
|
cfg.IntOpt(
|
|
'retries',
|
|
default=5,
|
|
help='Total number of Retries after '
|
|
'Exponentially Backing Off'),
|
|
cfg.IntOpt(
|
|
'min_backoff_range',
|
|
default=20,
|
|
help='Minimum Number of seconds to sleep between retries'),
|
|
cfg.IntOpt(
|
|
'max_backoff_range',
|
|
default=30,
|
|
help='Maximum Number of seconds to sleep between retries'),
|
|
]
|
|
|
|
_PROVIDER_OPTIONS = [
|
|
cfg.IntOpt(
|
|
'default_cache_ttl',
|
|
default=86400,
|
|
help='Default ttl to be set, when no caching '
|
|
'rules are specified'),
|
|
]
|
|
_MAX_SERVICE_OPTIONS = [
|
|
cfg.IntOpt('max_services_per_project', default=20,
|
|
help='Default max service per project_id')
|
|
]
|
|
_DRIVER_DNS_GROUP = 'driver:dns'
|
|
_PROVIDER_GROUP = 'drivers:provider'
|
|
_MAX_SERVICE_GROUP = 'drivers:storage'
|
|
|
|
conf.register_opts(_PROVIDER_OPTIONS, group=_PROVIDER_GROUP)
|
|
conf.register_opts(_DRIVER_DNS_OPTIONS, group=_DRIVER_DNS_GROUP)
|
|
conf.register_opts(_MAX_SERVICE_OPTIONS, group=_MAX_SERVICE_GROUP)
|
|
self.max_services_per_project = \
|
|
conf[_MAX_SERVICE_GROUP].max_services_per_project
|
|
self.bootstrap_obj = mock_bootstrap(conf)
|
|
|
|
# mock a stevedore provider extension
|
|
def get_provider_by_name(name):
|
|
name_p_name_mapping = {
|
|
'maxcdn': 'MaxCDN',
|
|
'cloudfront': 'CloudFront',
|
|
'fastly': 'Fastly',
|
|
'mock': 'Mock'
|
|
}
|
|
return mock.Mock(obj=mock.Mock(provider_name=(
|
|
name_p_name_mapping[name])))
|
|
mock_providers = mock.MagicMock()
|
|
mock_providers.__getitem__.side_effect = get_provider_by_name
|
|
manager_driver = driver.DefaultManagerDriver(conf,
|
|
mock_storage,
|
|
mock_providers,
|
|
mock_dns,
|
|
mock_distributed_task,
|
|
mock_notification,
|
|
mock_metrics)
|
|
|
|
# stubbed driver
|
|
self.sc = services.DefaultServicesController(manager_driver)
|
|
self.bootstrap_obj.manager = manager_driver
|
|
self.bootstrap_obj.manager.services_controller = self.sc
|
|
self.project_id = str(uuid.uuid4())
|
|
self.service_name = str(uuid.uuid4())
|
|
self.service_id = str(uuid.uuid4())
|
|
self.auth_token = str(uuid.uuid4())
|
|
self.service_json = {
|
|
"name": self.service_name,
|
|
"domains": [
|
|
{"domain": "www.mywebsite.com"},
|
|
{"domain": "blog.mywebsite.com"},
|
|
],
|
|
"origins": [
|
|
{
|
|
"origin": "mywebsite.com",
|
|
"port": 80,
|
|
"ssl": False
|
|
}
|
|
],
|
|
"caching": [
|
|
{"name": "default",
|
|
"ttl": 3600},
|
|
{"name": "home",
|
|
"ttl": 17200,
|
|
"rules": [
|
|
{"name": "index", "request_url": "/index.htm"}
|
|
]
|
|
},
|
|
{"name": "images",
|
|
"ttl": 12800,
|
|
"rules": [
|
|
{"name": "pictures",
|
|
"request_url": "/pictures.htm"}
|
|
]
|
|
}
|
|
],
|
|
"flavor_id": "standard",
|
|
"log_delivery": {
|
|
"enabled": False
|
|
},
|
|
}
|
|
|
|
self.service_obj = service.load_from_json(self.service_json)
|
|
|
|
@mock.patch('poppy.bootstrap.Bootstrap')
|
|
def mock_purge_service(self, mock_bootstrap, hard=False):
|
|
mock_bootstrap.return_value = self.bootstrap_obj
|
|
purge_provider = purge_service_tasks.PurgeProviderServicesTask()
|
|
provider_details = json.dumps(
|
|
dict([(k, v.to_dict()) for k, v
|
|
in self.provider_details.items()]))
|
|
responders = \
|
|
purge_provider.execute(json.dumps(self.service_obj.to_dict()),
|
|
json.dumps(hard),
|
|
provider_details,
|
|
str(None))
|
|
error_update = common.UpdateProviderDetailErrorTask()
|
|
changed_provider_details_dict = error_update.execute(responders,
|
|
self.service_id,
|
|
provider_details,
|
|
hard)
|
|
not_empty_update = common.UpdateProviderDetailIfNotEmptyTask()
|
|
not_empty_update.execute(changed_provider_details_dict,
|
|
self.project_id,
|
|
self.service_id)
|
|
|
|
@mock.patch('poppy.bootstrap.Bootstrap')
|
|
def mock_delete_service(self, mock_bootstrap):
|
|
mock_bootstrap.return_value = self.bootstrap_obj
|
|
delete_provider = delete_service_tasks.DeleteProviderServicesTask()
|
|
provider_details = json.dumps(
|
|
dict([(k, v.to_dict()) for k, v
|
|
in self.provider_details.items()]))
|
|
responders = delete_provider.execute(provider_details)
|
|
delete_dns = delete_service_tasks.DeleteServiceDNSMappingTask()
|
|
dns_responders = delete_dns.execute(provider_details, 0, responders,
|
|
self.project_id, self.service_id)
|
|
|
|
gather_provider = delete_service_tasks.GatherProviderDetailsTask()
|
|
changed_provider_dict = gather_provider.execute(responders,
|
|
dns_responders,
|
|
provider_details)
|
|
update_provider = common.UpdateProviderDetailIfNotEmptyTask()
|
|
update_provider.execute(changed_provider_dict, self.project_id,
|
|
self.service_id)
|
|
|
|
delete_service = delete_service_tasks.DeleteStorageServiceTask()
|
|
delete_service.execute(self.project_id, self.service_id)
|
|
|
|
def mock_create_service(self, provider_details_json):
|
|
@mock.patch('poppy.bootstrap.Bootstrap')
|
|
def bootstrap_mock_create(mock_bootstrap):
|
|
mock_bootstrap.return_value = self.bootstrap_obj
|
|
|
|
create_provider = create_service_tasks.CreateProviderServicesTask()
|
|
responders = create_provider.execute(
|
|
json.dumps(provider_details_json),
|
|
self.project_id,
|
|
self.service_id)
|
|
create_dns = create_service_tasks.CreateServiceDNSMappingTask()
|
|
dns_responder = create_dns.execute(responders, 0, self.project_id,
|
|
self.service_id)
|
|
gather_provider = create_service_tasks.GatherProviderDetailsTask()
|
|
log_responder = \
|
|
create_service_tasks.CreateLogDeliveryContainerTask()
|
|
provider_details_dict = \
|
|
gather_provider.execute(responders,
|
|
dns_responder,
|
|
log_responder)
|
|
update_provider_details = common.UpdateProviderDetailTask()
|
|
update_provider_details.execute(provider_details_dict,
|
|
self.project_id, self.service_id)
|
|
|
|
bootstrap_mock_create()
|
|
|
|
def mock_update_service(self, provider_details_json):
|
|
@mock.patch('poppy.bootstrap.Bootstrap')
|
|
def bootstrap_mock_update(mock_bootstrap):
|
|
mock_bootstrap.return_value = self.bootstrap_obj
|
|
service_old = json.dumps(self.service_json)
|
|
update_provider = update_service_tasks.UpdateProviderServicesTask()
|
|
service_updates = self.service_json.copy()
|
|
service_updates['log_delivery'] = {
|
|
'enabled': True
|
|
}
|
|
service_updates_json = json.dumps(service_updates)
|
|
responders = update_provider.execute(
|
|
service_old,
|
|
service_updates_json
|
|
)
|
|
update_dns = update_service_tasks.UpdateServiceDNSMappingTask()
|
|
|
|
dns_responder = update_dns.execute(responders, 0, service_old,
|
|
service_updates_json,
|
|
self.project_id,
|
|
self.service_id)
|
|
|
|
log_delivery_update = \
|
|
update_service_tasks.UpdateLogDeliveryContainerTask()
|
|
log_responder = log_delivery_update.execute(self.project_id,
|
|
self.auth_token,
|
|
service_old,
|
|
service_updates_json)
|
|
|
|
gather_provider = update_service_tasks.GatherProviderDetailsTask()
|
|
|
|
provider_details_dict = \
|
|
gather_provider.execute(responders,
|
|
dns_responder,
|
|
log_responder,
|
|
self.project_id,
|
|
self.service_id,
|
|
service_old)
|
|
|
|
update_provider_details = \
|
|
update_service_tasks.UpdateProviderDetailsTask_Errors()
|
|
update_provider_details.execute(provider_details_dict,
|
|
self.project_id,
|
|
self.service_id,
|
|
service_old,
|
|
service_updates_json)
|
|
|
|
bootstrap_mock_update()
|
|
|
|
def test_defaults_caching(self):
|
|
service_json = {
|
|
'caching': []
|
|
}
|
|
self.sc._append_defaults(service_json, operation='create')
|
|
changed_service_json = {
|
|
'caching': [
|
|
{
|
|
'name': 'default',
|
|
'rules': [
|
|
{
|
|
'name': 'default',
|
|
'request_url': '/*'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
|
|
self.assertTrue(isinstance(service_json['caching'][0]['ttl'],
|
|
six.integer_types))
|
|
del service_json['caching'][0]['ttl']
|
|
self.assertEqual(service_json, changed_service_json)
|
|
|
|
def test_create(self):
|
|
# 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")]
|
|
)
|
|
|
|
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.Mock(
|
|
return_value={
|
|
'Cloudfront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [
|
|
{
|
|
'href': 'www.mysite.com',
|
|
'rel': 'access_url'}],
|
|
'status': "deploy_in_progress"}})
|
|
service_controller = mock.Mock(
|
|
create=return_mock)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=service_controller)
|
|
)
|
|
elif name == "fastly":
|
|
return_mock = mock.Mock(
|
|
return_value={
|
|
'Fastly': {'error': "fail to create service",
|
|
'error_detail': 'Fastly Create failed'
|
|
' because of XYZ'}})
|
|
|
|
service_controller = mock.Mock(
|
|
create=return_mock)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=service_controller)
|
|
)
|
|
else:
|
|
return_mock = mock.Mock(
|
|
return_value={
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [
|
|
{
|
|
'href': 'www.mysite.com',
|
|
'rel': 'access_url'}]}})
|
|
service_controller = mock.Mock(
|
|
create=return_mock)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=service_controller)
|
|
)
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
self.sc.storage_controller.get_service_limit = mock.Mock(
|
|
return_value=self.max_services_per_project)
|
|
|
|
self.sc.storage_controller.get_service_count = mock.Mock(
|
|
return_value=1)
|
|
|
|
service_obj = self.sc.create(self.project_id,
|
|
self.auth_token,
|
|
self.service_json)
|
|
|
|
# ensure the manager calls the storage driver with the appropriate data
|
|
self.sc.storage_controller.create.assert_called_once_with(
|
|
self.project_id,
|
|
service_obj)
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_create_service_worker(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get('id', None)
|
|
access_urls = provider_detail_dict.get('access_urls', None)
|
|
status = provider_detail_dict.get('status', u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return_mock = {
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [{'href': 'www.mysite.com',
|
|
'rel': 'access_url'}],
|
|
'status': 'deploy_in_progress'
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=service_controller)
|
|
)
|
|
elif name == 'fastly':
|
|
return_mock = {
|
|
'Fastly': {'error': "fail to create servcice",
|
|
'error_detail': 'Fastly Create failed'
|
|
' because of XYZ'}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='MaxCDN',
|
|
service_controller=service_controller)
|
|
)
|
|
else:
|
|
return_mock = {
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [
|
|
{'href': 'www.mysite.com',
|
|
'rel': 'access_url'}]
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=service_controller)
|
|
)
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
self.mock_create_service(provider_details_json)
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_update_service_worker_success_and_failure(self,
|
|
provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get('id', None)
|
|
access_urls = provider_detail_dict.get('access_urls', None)
|
|
status = provider_detail_dict.get('status', u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return_mock = {
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [{'href': 'www.mysite.com',
|
|
'rel': 'access_url'}],
|
|
'status': 'deploy_in_progress'
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=service_controller)
|
|
)
|
|
elif name == 'fastly':
|
|
return_mock = {
|
|
'Fastly': {'error': "fail to create servcice",
|
|
'error_detail': 'Fastly Create failed'
|
|
' because of XYZ'}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='MaxCDN',
|
|
service_controller=service_controller)
|
|
)
|
|
else:
|
|
return_mock = {
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
'links': [
|
|
{'href': 'www.mysite.com',
|
|
'rel': 'access_url'}]
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
create=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=service_controller)
|
|
)
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
conf = cfg.CONF
|
|
conf(project='poppy', prog='poppy', args=[])
|
|
LOG_DELIVERY_OPTIONS = [
|
|
cfg.ListOpt('preferred_dcs', default=['DC1', 'DC2'],
|
|
help='Preferred DCs to create container'),
|
|
]
|
|
|
|
LOG_DELIVERY_GROUP = 'log_delivery'
|
|
conf.register_opts(LOG_DELIVERY_OPTIONS, group=LOG_DELIVERY_GROUP)
|
|
region = random.choice(conf['log_delivery']['preferred_dcs'])
|
|
|
|
catalog_json = {
|
|
'access': {
|
|
'serviceCatalog': [
|
|
{
|
|
'type': 'object-store',
|
|
'endpoints': [
|
|
{
|
|
'region': region,
|
|
'publicURL': 'public',
|
|
'internalURL': 'private'
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
|
|
# NOTE(TheSriram): Successful update
|
|
with mock.patch.object(requests,
|
|
'post',
|
|
return_value=Response(True, catalog_json)):
|
|
with mock.patch.object(requests,
|
|
'put',
|
|
return_value=Response(True)):
|
|
self.mock_update_service(provider_details_json)
|
|
|
|
# NOTE(TheSriram): Unsuccessful update due to keystone
|
|
with mock.patch.object(requests,
|
|
'post',
|
|
return_value=Response(False, catalog_json)):
|
|
with mock.patch.object(requests,
|
|
'put',
|
|
return_value=Response(True)):
|
|
self.mock_update_service(provider_details_json)
|
|
|
|
# NOTE(TheSriram): Unsuccessful update due to swift
|
|
with mock.patch.object(requests,
|
|
'post',
|
|
return_value=Response(True, catalog_json)):
|
|
with mock.patch.object(requests,
|
|
'put',
|
|
return_value=Response(False)):
|
|
self.mock_update_service(provider_details_json)
|
|
|
|
@ddt.file_data('service_update.json')
|
|
def test_update(self, update_json):
|
|
provider_details_dict = {
|
|
"MaxCDN": {"id": 11942, "access_urls": ["mypullzone.netdata.com"]},
|
|
"Mock": {"id": 73242, "access_urls": ["mycdn.mock.com"]},
|
|
"CloudFront": {
|
|
"id": "5ABC892", "access_urls": ["cf123.cloudcf.com"]},
|
|
"Fastly": {
|
|
"id": 3488, "access_urls": ["mockcf123.fastly.prod.com"]}
|
|
}
|
|
providers_details = {}
|
|
for name in provider_details_dict:
|
|
details = provider_details_dict[name]
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=details['id'],
|
|
access_urls=details['access_urls'],
|
|
status=details.get('status', u'unknown'))
|
|
providers_details[name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
self.sc.storage_controller.get_provider_details.return_value = (
|
|
providers_details
|
|
)
|
|
|
|
service_obj = service.load_from_json(self.service_json)
|
|
service_obj.status = u'deployed'
|
|
self.sc.storage_controller.get.return_value = service_obj
|
|
service_updates = json.dumps([
|
|
{
|
|
"op": "replace",
|
|
"path": "/domains/0",
|
|
"value": {"domain": "added.mocksite4.com"}
|
|
}
|
|
])
|
|
|
|
self.sc.update(self.project_id,
|
|
self.service_id,
|
|
self.auth_token,
|
|
service_updates)
|
|
|
|
# ensure the manager calls the storage driver with the appropriate data
|
|
self.sc.storage_controller.update.assert_called_once()
|
|
|
|
# and that the providers are notified.
|
|
providers.map.assert_called_once()
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_delete(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get('id', None)
|
|
access_urls = provider_detail_dict.get('access_urls', [])
|
|
status = provider_detail_dict.get('status', u'unknown')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
self.service_obj.provider_details = self.provider_details
|
|
sc = self.sc.storage_controller
|
|
sc.get.return_value = self.service_obj
|
|
|
|
self.sc.delete(self.project_id, self.service_id)
|
|
|
|
# ensure the manager calls the storage driver with the appropriate data
|
|
|
|
sc.get.assert_called_once_with(self.project_id, self.service_id)
|
|
sc.update.assert_called_once_with(self.project_id,
|
|
self.service_id,
|
|
self.service_obj)
|
|
|
|
# break into 2 lines.
|
|
sc = self.sc.storage_controller
|
|
sc.get_provider_details.assert_called_once_with(
|
|
self.project_id,
|
|
self.service_id)
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_detele_service_worker_success(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get("id", None)
|
|
access_urls = provider_detail_dict.get("access_urls", None)
|
|
status = provider_detail_dict.get("status", u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return_mock = {
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
delete=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=service_controller)
|
|
)
|
|
elif name == 'maxcdn':
|
|
return_mock = {
|
|
'MaxCDN': {'id': "pullzone345"}
|
|
}
|
|
service_controller = mock.Mock(
|
|
delete=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='MaxCDN',
|
|
service_controller=service_controller)
|
|
)
|
|
else:
|
|
return_mock = {
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}
|
|
}
|
|
service_controller = mock.Mock(
|
|
delete=mock.Mock(return_value=return_mock)
|
|
)
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=service_controller)
|
|
)
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
self.mock_delete_service()
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_delete_service_worker_with_error(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get("id", None)
|
|
access_urls = provider_detail_dict.get("access_urls", None)
|
|
status = provider_detail_dict.get("status", u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=mock.Mock(
|
|
delete=mock.Mock(
|
|
return_value={
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
elif name == 'maxcdn':
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='MaxCDN',
|
|
service_controller=mock.Mock(
|
|
delete=mock.Mock(return_value={
|
|
'MaxCDN': {'error': "fail to create servcice",
|
|
'error_detail':
|
|
'MaxCDN delete service'
|
|
' failed because of XYZ'}})
|
|
)
|
|
))
|
|
else:
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=mock.Mock(
|
|
delete=mock.Mock(
|
|
return_value={
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
self.mock_delete_service()
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_purge(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get('id', None)
|
|
access_urls = provider_detail_dict.get('access_urls', [])
|
|
status = provider_detail_dict.get('status', u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
self.sc.storage_controller.get_provider_details.return_value = (
|
|
self.provider_details
|
|
)
|
|
|
|
self.service_obj.provider_details = self.provider_details
|
|
self.sc.storage_controller.get.return_value = (
|
|
self.service_obj
|
|
)
|
|
|
|
self.sc.purge(self.project_id, self.service_id)
|
|
|
|
# ensure the manager calls the storage driver with the appropriate data
|
|
sc = self.sc.storage_controller
|
|
sc.get_provider_details.assert_called_once_with(
|
|
self.project_id,
|
|
self.service_id,
|
|
)
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_purge_service_worker_success(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get("id", None)
|
|
access_urls = provider_detail_dict.get("access_urls", None)
|
|
status = provider_detail_dict.get("status", u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=mock.Mock(
|
|
purge=mock.Mock(
|
|
return_value={
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
elif name == 'maxcdn':
|
|
return mock.Mock(obj=mock.Mock(
|
|
provider_name='MaxCDN',
|
|
service_controller=mock.Mock(
|
|
purge=mock.Mock(return_value={
|
|
'MaxCDN': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6'
|
|
}
|
|
})
|
|
)
|
|
))
|
|
else:
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=mock.Mock(
|
|
purge=mock.Mock(
|
|
return_value={
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
self.mock_purge_service(hard=True)
|
|
self.mock_purge_service(hard=False)
|
|
|
|
@ddt.file_data('data_provider_details.json')
|
|
def test_purge_service_worker_with_error(self, provider_details_json):
|
|
self.provider_details = {}
|
|
for provider_name in provider_details_json:
|
|
provider_detail_dict = json.loads(
|
|
provider_details_json[provider_name]
|
|
)
|
|
provider_service_id = provider_detail_dict.get("id", None)
|
|
access_urls = provider_detail_dict.get("access_urls", None)
|
|
status = provider_detail_dict.get("status", u'deployed')
|
|
provider_detail_obj = provider_details.ProviderDetail(
|
|
provider_service_id=provider_service_id,
|
|
access_urls=access_urls,
|
|
status=status)
|
|
self.provider_details[provider_name] = provider_detail_obj
|
|
|
|
providers = self.sc._driver.providers
|
|
|
|
def get_provider_extension_by_name(name):
|
|
if name == 'cloudfront':
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name='CloudFront',
|
|
service_controller=mock.Mock(
|
|
purge=mock.Mock(
|
|
return_value={
|
|
'CloudFront': {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
else:
|
|
return mock.Mock(
|
|
obj=mock.Mock(
|
|
provider_name=name.title(),
|
|
service_controller=mock.Mock(
|
|
purge=mock.Mock(
|
|
return_value={
|
|
name.title(): {
|
|
'id':
|
|
'08d2e326-377e-11e4-b531-3c15c2b8d2d6',
|
|
}}),
|
|
)))
|
|
|
|
providers.__getitem__.side_effect = get_provider_extension_by_name
|
|
|
|
with MonkeyPatchControllers(self.sc,
|
|
self.sc.dns_controller,
|
|
self.sc.storage_controller,
|
|
memoized_controllers.task_controllers):
|
|
self.mock_purge_service(hard=True)
|
|
self.mock_purge_service(hard=False)
|