Add MaxCDN driver && unittest
Change-Id: I4b1b51c994cf918b3de898c702869dae475eda95
This commit is contained in:
parent
1f2960cf2f
commit
2ea3f39221
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) 2013 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.
|
||||
|
||||
"""MaxCDN Provider Extension for CDN"""
|
||||
|
||||
from poppy.provider.maxcdn import driver
|
||||
|
||||
# Hoist classes into package namespace
|
||||
Driver = driver.CDNProvider
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2013 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.
|
||||
|
||||
"""Exports MaxCDN poppy controllers.
|
||||
|
||||
Field Mappings:
|
||||
In order to reduce the disk / memory space used,
|
||||
fields name will be, most of the time, the first
|
||||
letter of their long name. Fields mapping will be
|
||||
updated and documented in each controller class.
|
||||
"""
|
||||
|
||||
from poppy.provider.maxcdn import services
|
||||
|
||||
ServiceController = services.ServiceController
|
|
@ -0,0 +1,68 @@
|
|||
# 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.
|
||||
|
||||
"""Max CDN Provider implementation."""
|
||||
|
||||
import maxcdn
|
||||
from oslo.config import cfg
|
||||
|
||||
from poppy.openstack.common import log as logging
|
||||
from poppy.provider import base
|
||||
from poppy.provider.maxcdn import controllers
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
MAXCDN_OPTIONS = [
|
||||
cfg.StrOpt('alias', help='MAXCDN API account alias'),
|
||||
cfg.StrOpt('consumer_key', help='MAXCDN API consumer key'),
|
||||
cfg.StrOpt('consumer_secret', help='MAXCDN API consumer secret'),
|
||||
]
|
||||
|
||||
MAXCDN_GROUP = 'drivers:provider:maxcdn'
|
||||
|
||||
|
||||
class CDNProvider(base.Driver):
|
||||
|
||||
def __init__(self, conf):
|
||||
"""Init constructor."""
|
||||
super(CDNProvider, self).__init__(conf)
|
||||
|
||||
self._conf.register_opts(MAXCDN_OPTIONS,
|
||||
group=MAXCDN_GROUP)
|
||||
self.maxcdn_conf = self._conf[MAXCDN_GROUP]
|
||||
|
||||
self.maxcdn_client = maxcdn.MaxCDN(self.maxcdn_conf.alias,
|
||||
self.maxcdn_conf.consumer_key,
|
||||
self.maxcdn_conf.consumer_secret)
|
||||
|
||||
def is_alive(self):
|
||||
"""For health state."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def provider_name(self):
|
||||
"""For name."""
|
||||
return "MaxCDN"
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
"""client to this provider."""
|
||||
return self.maxcdn_client
|
||||
|
||||
@property
|
||||
def service_controller(self):
|
||||
"""Hook for service controller."""
|
||||
return controllers.ServiceController(self)
|
|
@ -0,0 +1,110 @@
|
|||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from poppy.provider import base
|
||||
|
||||
|
||||
class ServiceController(base.ServiceBase):
|
||||
|
||||
'''MaxCDN Service Controller.
|
||||
|
||||
'''
|
||||
|
||||
@property
|
||||
def client(self):
|
||||
return self.driver.client
|
||||
|
||||
def __init__(self, driver):
|
||||
'''Initialize a service controller object.'''
|
||||
super(ServiceController, self).__init__(driver)
|
||||
|
||||
self.driver = driver
|
||||
|
||||
# This returns the current customer account info
|
||||
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.
|
||||
|
||||
manager needs to pass in pullzone id to delete.
|
||||
'''
|
||||
try:
|
||||
update_response = self.client.put('/zones/pull.json/%s'
|
||||
% pullzone_id,
|
||||
params=service_json)
|
||||
if update_response['code'] != 200:
|
||||
return self.responder.failed('failed to update service')
|
||||
return self.responder.updated(
|
||||
update_response['data']['pullzone']['id'])
|
||||
except Exception:
|
||||
# this exception branch will most likely for a network failure
|
||||
return self.responder.failed('failed to update service')
|
||||
|
||||
def create(self, service_name, service_json):
|
||||
'''MaxCDN create.
|
||||
|
||||
manager needs to pass in a service name to create.
|
||||
'''
|
||||
try:
|
||||
# Create a new pull zone: maxcdn only supports 1 origin
|
||||
origin = service_json['origins'][0]
|
||||
create_response = self.client.post('/zones/pull.json', data={
|
||||
'name': service_name,
|
||||
'url': origin['origin'],
|
||||
'port': origin.get('port', 80),
|
||||
'sslshared': 1 if origin['ssl'] else 0,
|
||||
})
|
||||
|
||||
if create_response['code'] != 201:
|
||||
return self.responder.failed('failed to create service')
|
||||
|
||||
created_zone_info = create_response['data']['pullzone']
|
||||
|
||||
# Add custom domains to this service
|
||||
links = []
|
||||
for domain in service_json['domains']:
|
||||
custom_domain_response = self.client.post(
|
||||
'/zones/pull/%s/customdomains.json'
|
||||
% created_zone_info['id'],
|
||||
{'custom_domain': domain['domain']})
|
||||
links.append(custom_domain_response)
|
||||
# TODO(tonytan4ever): What if it fails during add domains ?
|
||||
return self.responder.created(created_zone_info['id'], links)
|
||||
except Exception:
|
||||
# this exception branch will most likely for a network failure
|
||||
return self.responder.failed('failed to create service')
|
||||
|
||||
def delete(self, pullzone_id):
|
||||
'''MaxCDN create.
|
||||
|
||||
manager needs to pass in a service name to delete.
|
||||
'''
|
||||
try:
|
||||
delete_response = self.client.delete('/zones/pull.json/%s'
|
||||
% pullzone_id)
|
||||
if delete_response['code'] != 200:
|
||||
return self.responder.failed('failed to delete service')
|
||||
return self.responder.deleted(pullzone_id)
|
||||
except Exception:
|
||||
# this exception branch will most likely for a network failure
|
||||
return self.responder.failed('failed to delete service')
|
||||
|
||||
# TODO(tonytan4ever): get service
|
||||
def get(self, service_name):
|
||||
'''Get details of the service, as stored by the provider.'''
|
||||
return {'domains': [], 'origins': [], 'caching': []}
|
|
@ -0,0 +1 @@
|
|||
# official max-cdn is not working for python33 yet. add it later
|
|
@ -3,3 +3,4 @@
|
|||
-r storage/cassandra.txt
|
||||
-r transport/pecan.txt
|
||||
-r provider/fastly.txt
|
||||
-r provider/maxcdn.txt
|
||||
|
|
|
@ -5,4 +5,9 @@ manager = default
|
|||
storage = mockdb
|
||||
|
||||
[drivers:provider:fastly]
|
||||
apikey = "MYAPIKEY"
|
||||
apikey = "MYAPIKEY"
|
||||
|
||||
[drivers:provider:maxcdn]
|
||||
alias = "MYALIAS"
|
||||
consumer_secret = "MYCONSUMER_SECRET"
|
||||
consumer_key = "MYCONSUMERKEY"
|
||||
|
|
|
@ -25,7 +25,7 @@ log_file = poppy.log
|
|||
|
||||
[drivers]
|
||||
# Transport driver module (e.g., falcon, pecan)
|
||||
transport = falcon
|
||||
transport = pecan
|
||||
|
||||
# Manager driver module (e.g. default)
|
||||
manager = default
|
||||
|
|
|
@ -27,7 +27,7 @@ log_file = poppy.log
|
|||
|
||||
[drivers]
|
||||
# Transport driver module (e.g., falcon, pecan)
|
||||
transport = falcon
|
||||
transport = pecan
|
||||
|
||||
# Manager driver module (e.g. default)
|
||||
manager = default
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"service_json": {
|
||||
"domains": [
|
||||
{"domain": "parsely.sage.com"},
|
||||
{"domain": "rosemary.thyme.net"}
|
||||
],
|
||||
"origins": [
|
||||
{"origin": "mockdomain.com", "ssl": false, "port": 80}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
# 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 os
|
||||
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
|
||||
from poppy.provider.maxcdn import driver
|
||||
from tests.unit import base
|
||||
|
||||
|
||||
MAXCDN_OPTIONS = [
|
||||
cfg.StrOpt('alias', help='MAXCDN API account alias'),
|
||||
cfg.StrOpt('consumer_key', help='MAXCDN API consumer key'),
|
||||
cfg.StrOpt('consumer_secret', help='MAXCDN API consumer secret'),
|
||||
]
|
||||
|
||||
|
||||
class TestDriver(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestDriver, self).setUp()
|
||||
|
||||
tests_path = os.path.abspath(os.path.dirname(
|
||||
os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(__file__)
|
||||
))))
|
||||
conf_path = os.path.join(tests_path, 'etc', 'default_functional.conf')
|
||||
cfg.CONF(args=[], default_config_files=[conf_path])
|
||||
|
||||
self.conf = cfg.CONF
|
||||
|
||||
@mock.patch('maxcdn.MaxCDN')
|
||||
@mock.patch.object(driver, 'MAXCDN_OPTIONS', new=MAXCDN_OPTIONS)
|
||||
def test_init(self, mock_connect):
|
||||
provider = driver.CDNProvider(self.conf)
|
||||
mock_connect.assert_called_once_with(
|
||||
provider._conf['drivers:provider:maxcdn'].alias,
|
||||
provider._conf['drivers:provider:maxcdn'].consumer_key,
|
||||
provider._conf['drivers:provider:maxcdn'].consumer_secret)
|
||||
|
||||
@mock.patch.object(driver, 'MAXCDN_OPTIONS', new=MAXCDN_OPTIONS)
|
||||
def test_is_alive(self):
|
||||
provider = driver.CDNProvider(self.conf)
|
||||
self.assertEqual(provider.is_alive(), True)
|
||||
|
||||
@mock.patch.object(driver, 'MAXCDN_OPTIONS', new=MAXCDN_OPTIONS)
|
||||
def test_get_client(self):
|
||||
provider = driver.CDNProvider(self.conf)
|
||||
client = provider.client
|
||||
self.assertNotEqual(client, None)
|
||||
|
||||
@mock.patch('poppy.provider.maxcdn.controllers.ServiceController')
|
||||
@mock.patch.object(driver, 'MAXCDN_OPTIONS', new=MAXCDN_OPTIONS)
|
||||
def test_service_controller(self, MockController):
|
||||
provider = driver.CDNProvider(self.conf)
|
||||
self.assertNotEqual(provider.service_controller, None)
|
|
@ -0,0 +1,239 @@
|
|||
# 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 ddt
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
|
||||
from poppy.provider.maxcdn import driver
|
||||
from poppy.provider.maxcdn import services
|
||||
from tests.unit import base
|
||||
|
||||
|
||||
MAXCDN_OPTIONS = [
|
||||
cfg.StrOpt('alias',
|
||||
default='no_good_alias',
|
||||
help='MAXCDN API account alias'),
|
||||
cfg.StrOpt('consumer_key',
|
||||
default='a_consumer_key',
|
||||
help='MAXCDN API consumer key'),
|
||||
cfg.StrOpt('consumer_secret',
|
||||
default='a_consumer_secret',
|
||||
help='MAXCDN API consumer secret'),
|
||||
]
|
||||
|
||||
|
||||
fake_maxcdn_client_get_return_value = {u'code': 200,
|
||||
u'data':
|
||||
{u'account':
|
||||
{u'status': u'2',
|
||||
u'name': u'<My_fake_company_alias>',
|
||||
u'id': u'32811'
|
||||
}}}
|
||||
|
||||
fake_maxcdn_client_400_return_value = {
|
||||
u'code': 400,
|
||||
u'message': "operation PUT/GET/POST failed due to technical difficulties.."
|
||||
}
|
||||
|
||||
|
||||
class fake_maxcdn_api_client:
|
||||
|
||||
def get(self, url='/account.json'):
|
||||
return {u'code': 200,
|
||||
u'data':
|
||||
{u'account':
|
||||
{u'status': u'2',
|
||||
u'name': u'<My_fake_company_alias>',
|
||||
u'id': u'32811'
|
||||
}}}
|
||||
|
||||
def post(self, url=None, data=None):
|
||||
return {u'code': 201,
|
||||
u'data': {
|
||||
u"pullzone": {
|
||||
u"cdn_url": u"newpullzone1.alias.netdna-cdn.com",
|
||||
u'name': u'newpullzone1',
|
||||
u'id': u'97312'
|
||||
}}}
|
||||
|
||||
def put(self, url=None, params=None):
|
||||
return {u'code': 200,
|
||||
u'data': {
|
||||
u"pullzone": {
|
||||
u"cdn_url": u"newpullzone1.alias.netdna-cdn.com",
|
||||
u'name': u'newpullzone1',
|
||||
u'id': u'97312'
|
||||
}}}
|
||||
|
||||
def delete(self, url=None):
|
||||
return {u'code': 200,
|
||||
}
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestServices(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestServices, self).setUp()
|
||||
|
||||
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',
|
||||
new=fake_maxcdn_api_client())
|
||||
def test_get(self):
|
||||
new_driver = driver.CDNProvider(self.conf)
|
||||
# instantiate
|
||||
controller = services.ServiceController(new_driver)
|
||||
service_name = "test_service_name"
|
||||
self.assertTrue(controller.get(service_name) is not None)
|
||||
|
||||
@ddt.file_data('data_service.json')
|
||||
@mock.patch.object(driver.CDNProvider, 'client',
|
||||
new=fake_maxcdn_api_client())
|
||||
def test_create(self, service_json):
|
||||
new_driver = driver.CDNProvider(self.conf)
|
||||
# instantiate
|
||||
controller = services.ServiceController(new_driver)
|
||||
# test create, everything goes through successfully
|
||||
service_name = "test_service_name"
|
||||
resp = controller.create(service_name, service_json)
|
||||
self.assertIn('id', resp[new_driver.provider_name])
|
||||
self.assertIn('links', resp[new_driver.provider_name])
|
||||
|
||||
@ddt.file_data('data_service.json')
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider.client')
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider')
|
||||
def test_create_with_exception(self, service_json, 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_get_return_value
|
||||
})
|
||||
|
||||
service_name = "test_service_name"
|
||||
|
||||
controller_with_create_exception = services.ServiceController(driver)
|
||||
controller_with_create_exception.client.configure_mock(**{
|
||||
"post.side_effect":
|
||||
RuntimeError('Creating service mysteriously failed.')})
|
||||
resp = controller_with_create_exception.create(
|
||||
service_name,
|
||||
service_json)
|
||||
self.assertIn('error', resp[driver.provider_name])
|
||||
|
||||
controller_with_create_exception.client.reset_mock()
|
||||
controller_with_create_exception.client.configure_mock(**{
|
||||
'post.side_effect': None,
|
||||
"post.return_value": fake_maxcdn_client_400_return_value
|
||||
})
|
||||
resp = controller_with_create_exception.create(
|
||||
service_name,
|
||||
service_json)
|
||||
self.assertIn('error', resp[driver.provider_name])
|
||||
|
||||
@ddt.file_data('data_service.json')
|
||||
@mock.patch.object(driver.CDNProvider, 'client',
|
||||
new=fake_maxcdn_api_client())
|
||||
def test_update(self, service_json):
|
||||
new_driver = driver.CDNProvider(self.conf)
|
||||
# instantiate
|
||||
controller = services.ServiceController(new_driver)
|
||||
# test create, everything goes through successfully
|
||||
service_name = "test_service_name"
|
||||
resp = controller.update(service_name, service_json)
|
||||
self.assertIn('id', resp[new_driver.provider_name])
|
||||
|
||||
@ddt.file_data('data_service.json')
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider.client')
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider')
|
||||
def test_update_with_exception(self, service_json, 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_get_return_value
|
||||
})
|
||||
|
||||
service_name = "test_service_name"
|
||||
|
||||
controller_with_update_exception = services.ServiceController(driver)
|
||||
controller_with_update_exception.client.configure_mock(**{
|
||||
"put.side_effect":
|
||||
RuntimeError('Updating service mysteriously failed.')})
|
||||
resp = controller_with_update_exception.update(
|
||||
service_name,
|
||||
service_json)
|
||||
self.assertIn('error', resp[driver.provider_name])
|
||||
|
||||
controller_with_update_exception.client.reset_mock()
|
||||
controller_with_update_exception.client.configure_mock(**{
|
||||
"put.side_effect": None,
|
||||
"put.return_value": fake_maxcdn_client_400_return_value
|
||||
})
|
||||
resp = controller_with_update_exception.update(
|
||||
service_name,
|
||||
service_json)
|
||||
self.assertIn('error', resp[driver.provider_name])
|
||||
|
||||
@mock.patch.object(driver.CDNProvider, 'client',
|
||||
new=fake_maxcdn_api_client())
|
||||
def test_delete(self):
|
||||
new_driver = driver.CDNProvider(self.conf)
|
||||
# instantiate
|
||||
controller = services.ServiceController(new_driver)
|
||||
# test create, everything goes through successfully
|
||||
service_name = "test_service_name"
|
||||
resp = controller.delete(service_name)
|
||||
self.assertIn('id', resp[new_driver.provider_name])
|
||||
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider.client')
|
||||
@mock.patch('poppy.provider.maxcdn.driver.CDNProvider')
|
||||
def test_delete_with_exception(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_get_return_value
|
||||
})
|
||||
|
||||
service_name = "test_service_name"
|
||||
|
||||
controller_with_delete_exception = services.ServiceController(driver)
|
||||
controller_with_delete_exception.client.configure_mock(**{
|
||||
"delete.side_effect":
|
||||
RuntimeError('Deleting service mysteriously failed.')})
|
||||
resp = controller_with_delete_exception.delete(service_name)
|
||||
self.assertEqual(resp[driver.provider_name]['error'],
|
||||
'failed to delete service')
|
||||
|
||||
controller_with_delete_exception.client.reset_mock()
|
||||
controller_with_delete_exception.client.configure_mock(**{
|
||||
"delete.side_effect": None,
|
||||
"delete.return_value": fake_maxcdn_client_400_return_value
|
||||
})
|
||||
resp = controller_with_delete_exception.delete(service_name)
|
||||
self.assertEqual(resp[driver.provider_name]['error'],
|
||||
'failed to delete service')
|
1
tox.ini
1
tox.ini
|
@ -17,6 +17,7 @@ setenv = VIRTUAL_ENV={envdir}
|
|||
deps = -r{toxinidir}/requirements/requirements.txt
|
||||
-r{toxinidir}/tests/test-requirements.txt
|
||||
commands = pip install git+https://github.com/malini-kamalambal/opencafe.git#egg=cafe
|
||||
pip install git+https://github.com/tonytan4ever/python-maxcdn.git#egg=maxcdn
|
||||
nosetests {posargs}
|
||||
|
||||
[tox:jenkins]
|
||||
|
|
Loading…
Reference in New Issue