https domains for akamai driver

Closes-Bug: 1403621

Change-Id: Ibb6125dff2ee24f9c60e5d84e404f1a8007012e2
This commit is contained in:
amitgandhinz 2014-12-11 16:18:16 -05:00 committed by tonytan4ever
parent a9be24d12b
commit 8456b609d6
8 changed files with 224 additions and 118 deletions

View File

@ -111,5 +111,6 @@ ccu_api_client_secret = "MY_CCU_API_CLIENT_SECRET"
ccu_api_access_token = "MY_CCU_API_ACCESS_TOKEN"
ccu_api_base_url = "MY_CCU_API_BASE_URL"
akamai_access_url_link = "MY_ACCESS_URL_LINK"
akamai_https_access_url_suffix = "MY_HTTPS_ACCESS_URL_SUFFIX"
akamai_http_config_number = 'MY_AKAMAI_HTTP_CONFIG_NUMBER'
akamai_https_config_number = 'MY_AKAMAI_HTTPS_CONFIG_NUMBER'

View File

@ -54,6 +54,9 @@ AKAMAI_OPTIONS = [
cfg.StrOpt(
'akamai_access_url_link',
help='Akamai domain access_url link'),
cfg.StrOpt(
'akamai_https_access_url_suffix',
help='Akamai domain ssl access url suffix'),
# Akama client specific configuration numbers
cfg.StrOpt(
@ -89,6 +92,9 @@ class CDNProvider(base.Driver):
self.https_conf_number = self.akamai_conf.akamai_https_config_number
self.akamai_access_url_link = self.akamai_conf.akamai_access_url_link
self.akamai_https_access_url_suffix = (
self.akamai_conf.akamai_https_access_url_suffix
)
self.akamai_policy_api_client = requests.Session()
self.akamai_policy_api_client.auth = edgegrid.EdgeGridAuth(

View File

@ -91,9 +91,14 @@ class ServiceController(base.ServiceBase):
# TODO(tonytan4ever): also classify domains based on their
# protocols. http and https domains needs to be created
# with separate base urls.
configuration_number = None
if classified_domain.protocol == 'http':
configuration_number = self.driver.http_conf_number
elif classified_domain.protocol == 'https':
configuration_number = self.driver.https_conf_number
resp = self.policy_api_client.put(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
configuration_number=configuration_number,
policy_name=dp),
data=json.dumps(post_data),
headers=self.request_header)
@ -102,12 +107,20 @@ class ServiceController(base.ServiceBase):
if resp.status_code != 200:
raise RuntimeError(resp.text)
ids.append(dp)
dp_obj = {'policy_name': dp,
'protocol': classified_domain.protocol}
ids.append(dp_obj)
# TODO(tonytan4ever): leave empty links for now
# may need to work with dns integration
LOG.info('Creating policy %s on domain %s complete' %
(dp, classified_domain.domain))
links.append({'href': self.driver.akamai_access_url_link,
provider_access_url = None
if classified_domain.protocol == 'http':
provider_access_url = self.driver.akamai_access_url_link
elif classified_domain.protocol == 'https':
provider_access_url = '.'.join(
[dp, self.driver.akamai_https_access_url_suffix])
links.append({'href': provider_access_url,
'rel': 'access_url',
'domain': dp
})
@ -274,10 +287,15 @@ class ServiceController(base.ServiceBase):
# and creates new policy for the new domains,
# old policies ought to be deleted.
try:
configuration_number = None
if policies[0]['protocol'] == 'http':
configuration_number = self.driver.http_conf_number
elif policies[0]['protocol'] == 'https':
configuration_number = self.driver.https_conf_number
resp = self.policy_api_client.get(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policies[0]),
configuration_number=configuration_number,
policy_name=policies[0]['policy_name']),
headers=self.request_header)
if resp.status_code != 200:
raise RuntimeError(resp.text)
@ -323,7 +341,21 @@ class ServiceController(base.ServiceBase):
dp = self._process_new_domain(classified_domain,
policy_content['rules'])
if dp in policies:
configuration_number = None
if classified_domain.protocol == 'http':
configuration_number = self.driver.http_conf_number
elif classified_domain.protocol == 'https':
configuration_number = self.driver.https_conf_number
# verify the same policy
policy_names = [policy['policy_name'] for policy
in policies]
# Only if a same domain with a same protocol
# do we need to update a existing policy
if dp in policy_names and (
policies[policy_names.index(dp)]['protocol'] == (
classified_domain.protocol)):
# in this case we should update existing policy
# instead of create a new policy
LOG.info('Start to update policy %s' % dp)
@ -337,13 +369,15 @@ class ServiceController(base.ServiceBase):
policy_name=dp),
data=json.dumps(policy_content),
headers=self.request_header)
policies.remove(dp)
dp_obj = {'policy_name': dp,
'protocol': classified_domain.protocol}
policies.remove(dp_obj)
else:
LOG.info('Start to create new policy %s' % dp)
resp = self.policy_api_client.put(
self.policy_api_base_url.format(
configuration_number=(
self.driver.http_conf_number),
configuration_number),
policy_name=dp),
data=json.dumps(policy_content),
headers=self.request_header)
@ -351,12 +385,21 @@ class ServiceController(base.ServiceBase):
LOG.info('akamai response text: %s' % resp.text)
if resp.status_code != 200:
raise RuntimeError(resp.text)
ids.append(dp)
dp_obj = {'policy_name': dp,
'protocol': classified_domain.protocol}
ids.append(dp_obj)
# TODO(tonytan4ever): leave empty links for now
# may need to work with dns integration
LOG.info('Creating/Updateing policy %s on domain %s '
'complete' % (dp, classified_domain.domain))
links.append({'href': self.driver.akamai_access_url_link,
provider_access_url = None
if classified_domain.protocol == 'http':
provider_access_url = (
self.driver.akamai_access_url_link)
elif classified_domain.protocol == 'https':
provider_access_url = '.'.join(
[dp, self.driver.akamai_https_access_url_suffix])
links.append({'href': provider_access_url,
'rel': 'access_url',
'domain': dp
})
@ -365,27 +408,41 @@ class ServiceController(base.ServiceBase):
try:
for policy in policies:
LOG.info('Starting to delete old policy %s' % policy)
configuration_number = None
if policy["protocol"] == 'http':
configuration_number = self.driver.http_conf_number
elif policy["protocol"] == 'https':
configuration_number = self.driver.https_conf_number
LOG.info('Starting to delete old policy %s' %
policy['policy_name'])
resp = self.policy_api_client.delete(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policy))
configuration_number=configuration_number,
policy_name=policy['policy_name']))
LOG.info('akamai response code: %s' % resp.status_code)
LOG.info('akamai response text: %s' % resp.text)
if resp.status_code != 200:
raise RuntimeError(resp.text)
LOG.info('Delete old policy %s complete' % policy)
except Exception as e:
return self.responder.failed(str(e))
LOG.info('Delete old policy %s complete' %
policy['policy_name'])
except Exception:
return self.responder.failed("failed to update service")
else:
# in this case we only need to adjust the existing policies
for policy in policies:
try:
configuration_number = None
if policy["protocol"] == 'http':
configuration_number = self.driver.http_conf_number
elif policy["protocol"] == 'https':
configuration_number = self.driver.https_conf_number
resp = self.policy_api_client.get(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policy),
configuration_number=configuration_number,
policy_name=policy['policy_name']),
headers=self.request_header)
if resp.status_code != 200:
raise RuntimeError(resp.text)
@ -426,18 +483,26 @@ class ServiceController(base.ServiceBase):
LOG.info('Start to update policy %s ' % policy)
resp = self.policy_api_client.put(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policy),
configuration_number=configuration_number,
policy_name=policy['policy_name']),
data=json.dumps(policy_content),
headers=self.request_header)
LOG.info('akamai response code: %s' % resp.status_code)
LOG.info('akamai response text: %s' % resp.text)
LOG.info('Update policy %s complete' % policy)
LOG.info('Update policy %s complete' %
policy['policy_name'])
except Exception:
return self.responder.failed("failed to update service")
links.append({'href': self.driver.akamai_access_url_link,
provider_access_url = None
if policy['protocol'] == 'http':
provider_access_url = (
self.driver.akamai_access_url_link)
elif policy['protocol'] == 'https':
provider_access_url = '.'.join(
[dp, self.driver.akamai_https_access_url_suffix])
links.append({'href': provider_access_url,
'rel': 'access_url',
'domain': policy
'domain': policy['policy_name']
})
ids = policies
return self.responder.updated(json.dumps(ids), links)
@ -460,10 +525,16 @@ class ServiceController(base.ServiceBase):
# TODO(tonytan4ever): needs to look at if service
# domain is an https domain, if it is then a different
# base url is needed
configuration_number = None
if policy["protocol"] == 'http':
configuration_number = self.driver.http_conf_number
elif policy["protocol"] == 'https':
configuration_number = self.driver.https_conf_number
resp = self.policy_api_client.delete(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policy))
configuration_number=configuration_number,
policy_name=policy['policy_name']))
LOG.info('akamai response code: %s' % resp.status_code)
LOG.info('akamai response text: %s' % resp.text)
if resp.status_code != 200:
@ -491,35 +562,27 @@ class ServiceController(base.ServiceBase):
return self.responder.failed(str(e))
for policy in policies:
resp = self.policy_api_client.get(
self.policy_api_base_url.format(
configuration_number=self.driver.http_conf_number,
policy_name=policy),
headers=self.request_header)
if resp.status_code != 200:
url_scheme = None
if policy['protocol'] == 'http':
url_scheme = 'http://'
elif policy['protocol'] == 'https':
url_scheme = 'https://'
actual_purge_url = '.'.join([url_scheme,
policy['policy_name'],
purge_url])
data = {
'objects': [
actual_purge_url
]
}
resp = self.ccu_api_client.post(self.ccu_api_base_url,
data=json.dumps(data),
headers=(
self.request_header
))
if resp.status_code != 201:
raise RuntimeError(resp.text)
else:
url_scheme = 'http'
policy_content = json.loads(resp.text)
# loop over matches to get the correct url scheme
for m_item in policy_content['rules'][0]['matches']:
if m_item['name'] == 'url-scheme':
url_scheme = m_item['value']
break
actual_purge_url = url_scheme + "://www." + policy + (
purge_url)
data = {
'objects': [
actual_purge_url
]
}
resp = self.ccu_api_client.post(self.ccu_api_base_url,
data=json.dumps(data),
headers=(
self.request_header
))
if resp.status_code != 201:
raise RuntimeError(resp.text)
return self.responder.purged(provider_service_id,
purge_url=purge_url)
except Exception as e:

View File

@ -3,8 +3,10 @@
"name" : "mysite.com",
"domains": [
{"domain": "parsely.sage.com"},
{"domain": "densely.sage.com"},
{"domain": "rosemary.thyme.net"}
{"domain": "densely.sage.com",
"protocol": "https"},
{"domain": "rosemary.thyme.net",
"protocol": "http"}
],
"origins": [
{"origin": "mockdomain.com", "ssl": false, "port": 80}
@ -19,7 +21,7 @@
{"domain": "rosemary.thyme.net"}
],
"origins": [
{"origin": "mockdomain.com", "ssl": false, "port": 80},
{"origin": "mockdomain.com", "ssl": true, "port": 443},
{"origin": "mockdomain-image.com",
"rules": [{"name": "img", "request_url": "/img"}] }
],

View File

@ -3,7 +3,8 @@
"name" : "mysite.com",
"domains": [
{"domain": "parsely.sage.com"},
{"domain": "densely.sage.com"},
{"domain": "densely.sage.com",
"protocol": "https"},
{"domain": "rosemary.thyme.net"}
],
"origins": [
@ -19,7 +20,7 @@
{"domain": "rosemary.thyme.net"}
],
"origins": [
{"origin": "mockdomain.com", "ssl": false, "port": 80},
{"origin": "mockdomain.com", "ssl": true, "port": 443},
{"origin": "mockdomain-image.com",
"rules": [{"name": "img", "request_url": "/img"}] }
],
@ -39,6 +40,41 @@
{"origin": "mockdomain-image.com",
"rules": [{"name": "img", "request_url": "/img"}] }
],
"restrictions": [
{
"name": "website only",
"rules": [
{
"name": "mocksite.com",
"http_host": "www.mocksite.com"
}
]
},
{
"name": "graphic only",
"rules": [
{
"name": "mockgraphicsite.com",
"referrer": "www.mocksitegraphic.com"
}
]
}
],
"caching": [
{"name": "default", "ttl": 1200 },
{"name": "img-only",
"ttl": 1800,
"rules": [
{ "name": "jpeg-rules",
"request_url": "/*.jpeg"
},
{ "name": "gif-rules",
"request_url": "/*.gif"
}
]
}
],
"flavor_id" : "standard"
},
"no_origin_with_domains": {

View File

@ -1,31 +0,0 @@
{
"no_url_scheme": {
"rules": [{
"matches": [
{"name": "url-wildcard",
"value": "/*"}
]
}
]
},
"url_scheme_http": {
"rules": [{
"matches": [
{"name": "url-wildcard",
"value": "/*"},
{"name": "url-scheme",
"value": "http"}
]}
]
},
"url_scheme_https": {
"rules": [{
"matches": [
{"name": "url-wildcard",
"value": "/*"},
{"name": "url-scheme",
"value": "https"}
]}
]
}
}

View File

@ -53,14 +53,17 @@ AKAMAI_OPTIONS = [
cfg.StrOpt(
'akamai_access_url_link', default='abc.def.org',
help='Akamai domain access_url link'),
cfg.StrOpt(
'akamai_https_access_url_suffix', default='ssl.abc',
help='Akamai domain ssl access url suffix'),
# Akama client specific configuration numbers
cfg.StrOpt(
'akamai_http_config_number', default=str(random.randint(10000, 99999)),
help='Akamai domain access_url link'),
help='Akamai configuration number for http policies'),
cfg.StrOpt(
'akamai_https_config_number',
default=str(random.randint(10000, 99999)),
help='Akamai domain access_url link'),
help='Akamai configuration number for https policies'),
]

View File

@ -38,6 +38,7 @@ class TestServices(base.TestCase):
mock_driver):
super(TestServices, self).setUp()
self.driver = mock_driver()
self.driver.akamai_https_access_url_suffix = str(uuid.uuid1())
self.controller = services.ServiceController(self.driver)
@ddt.file_data('domains_list.json')
@ -84,7 +85,8 @@ class TestServices(base.TestCase):
self.assertTrue(service_obj.caching == [])
def test_delete_with_exception(self):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
# test exception
exception = RuntimeError('ding')
@ -100,7 +102,8 @@ class TestServices(base.TestCase):
self.assertIn('error', resp[self.driver.provider_name])
def test_delete_with_4xx_return(self):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
# test exception
self.controller.policy_api_client.delete.return_value = mock.Mock(
@ -112,14 +115,16 @@ class TestServices(base.TestCase):
self.assertIn('error', resp[self.driver.provider_name])
def test_delete(self):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
self.controller.delete(provider_service_id)
self.controller.policy_api_client.delete.assert_called_once()
@ddt.file_data('data_update_service.json')
def test_update_with_get_error(self, service_json):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=400,
@ -138,9 +143,41 @@ class TestServices(base.TestCase):
provider_service_id, service_obj, service_obj, service_obj)
self.assertIn('error', resp[self.driver.provider_name])
@ddt.file_data('data_update_service.json')
def test_update_with_service_id_json_load_error(self, service_json):
# This should trigger a json.loads error
provider_service_id = None
service_obj = service.load_from_json(service_json)
resp = self.controller.update(
provider_service_id, service_obj, service_obj, service_obj)
self.assertIn('error', resp[self.driver.provider_name])
@ddt.file_data('data_update_service.json')
def test_update(self, service_json):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=200,
text=json.dumps(dict(rules=[]))
)
controller.policy_api_client.put.return_value = mock.Mock(
status_code=200,
text='Put successful'
)
controller.policy_api_client.delete.return_value = mock.Mock(
status_code=200,
text='Delete successful'
)
service_obj = service.load_from_json(service_json)
resp = controller.update(
provider_service_id, service_obj, service_obj, service_obj)
self.assertIn('id', resp[self.driver.provider_name])
@ddt.file_data('data_update_service.json')
def test_update_with_domain_protocol_change(self, service_json):
provider_service_id = json.dumps([{'policy_name': "densely.sage.com",
'protocol': 'http'}])
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=200,
@ -160,29 +197,22 @@ class TestServices(base.TestCase):
self.assertIn('id', resp[self.driver.provider_name])
def test_purge_all(self):
provider_service_id = json.dumps([str(uuid.uuid1())])
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
controller = services.ServiceController(self.driver)
resp = controller.purge(provider_service_id, None)
self.assertIn('error', resp[self.driver.provider_name])
def test_purge_with_get_exception(self):
provider_service_id = json.dumps([str(uuid.uuid1())])
def test_purge_with_service_id_json_load_error(self):
provider_service_id = None
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=400,
text='Some get error happened'
)
resp = controller.purge(provider_service_id, '/img/abc.jpeg')
resp = controller.purge(provider_service_id, None)
self.assertIn('error', resp[self.driver.provider_name])
@ddt.file_data('policy_detail.json')
def test_purge_with_ccu_exception(self, policy_detail_json):
provider_service_id = json.dumps([str(uuid.uuid1())])
def test_purge_with_ccu_exception(self):
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'http'}])
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=200,
text=json.dumps(policy_detail_json)
)
controller.ccu_api_client.post.return_value = mock.Mock(
status_code=400,
text="purge request post failed"
@ -190,14 +220,10 @@ class TestServices(base.TestCase):
resp = controller.purge(provider_service_id, '/img/abc.jpeg')
self.assertIn('error', resp[self.driver.provider_name])
@ddt.file_data('policy_detail.json')
def test_purge(self, policy_detail_json):
provider_service_id = json.dumps([str(uuid.uuid1())])
def test_purge(self):
provider_service_id = json.dumps([{'policy_name': str(uuid.uuid1()),
'protocol': 'https'}])
controller = services.ServiceController(self.driver)
controller.policy_api_client.get.return_value = mock.Mock(
status_code=200,
text=json.dumps(policy_detail_json)
)
controller.ccu_api_client.post.return_value = mock.Mock(
status_code=201,
text="purge request post complete"