feat: Add akamai background job admin endpoint
REQUEST: POST /admin/provider/akamai/background_job { "job_type": "akamai_update_papi_property_for_mod_san", "domain_name": "testabc.cnamecdn.com", "san_cert_name": "secure1.san1.test_cdn.com" } RESPONSE: 202 ACCEPTED Note: The admin endpoints are also exposed as scripts: akamai-property-udpate-mod-san --domain_name <your_domain_name> --san_cert_name <your_san_cert_name> akamai-cert-status-check-and-update --domain_name <your_domain_name> --cert_type "san" --project_id <PROJECT_ID> --flavor_id <FLAVOR_ID> Change-Id: I9211d9f24cbd46c8818993d3ff8493d5fba4bc28
This commit is contained in:
parent
032af4a026
commit
7a2c4c56e4
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright (c) 2015 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 oslo_config import cfg
|
||||||
|
|
||||||
|
from poppy.common import cli
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.provider.akamai.background_jobs.check_cert_status_and_update import \
|
||||||
|
check_cert_status_and_update_flow
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
CLI_OPT = [
|
||||||
|
cfg.StrOpt('domain_name',
|
||||||
|
required=True,
|
||||||
|
help='The domain you want to check cert status on'),
|
||||||
|
cfg.StrOpt('cert_type',
|
||||||
|
default='san',
|
||||||
|
help='Cert type of this cert'),
|
||||||
|
cfg.StrOpt('project_id',
|
||||||
|
required=True,
|
||||||
|
help='project id of this cert'),
|
||||||
|
cfg.StrOpt('flavor_id',
|
||||||
|
default='cdn',
|
||||||
|
help='flavor id of this cert'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@cli.runnable
|
||||||
|
def run():
|
||||||
|
# TODO(kgriffs): For now, we have to use the global config
|
||||||
|
# to pick up common options from openstack.common.log, since
|
||||||
|
# that module uses the global CONF instance exclusively.
|
||||||
|
conf = cfg.ConfigOpts()
|
||||||
|
conf.register_cli_opts(CLI_OPT)
|
||||||
|
conf(prog='akamai-cert-check')
|
||||||
|
|
||||||
|
LOG.info('Starting to check status on domain: %s, for project_id: %s'
|
||||||
|
'flavor_id: %s, cert_type: %s' %
|
||||||
|
(
|
||||||
|
conf.domain_name,
|
||||||
|
conf.project_id,
|
||||||
|
conf.flavor_id,
|
||||||
|
conf.cert_type
|
||||||
|
))
|
||||||
|
|
||||||
|
check_cert_status_and_update_flow.run_check_cert_status_and_update_flow(
|
||||||
|
conf.domain_name,
|
||||||
|
conf.cert_type,
|
||||||
|
conf.flavor_id,
|
||||||
|
conf.project_id
|
||||||
|
)
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Copyright (c) 2015 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
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from poppy.common import cli
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.provider.akamai.background_jobs.update_property import \
|
||||||
|
update_property_flow
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
CLI_OPT = [
|
||||||
|
cfg.StrOpt('domain_name',
|
||||||
|
required=True,
|
||||||
|
help='The domain you want to add in host name (cnameFrom)'),
|
||||||
|
cfg.StrOpt('san_cert_name',
|
||||||
|
required=True,
|
||||||
|
help='Cert type of this cert'),
|
||||||
|
cfg.StrOpt('update_type',
|
||||||
|
default="hostsnames",
|
||||||
|
help='Update type for this update, available types are:'
|
||||||
|
'hostsnames, secureEdgeHost, rules'),
|
||||||
|
cfg.StrOpt('action',
|
||||||
|
default="add",
|
||||||
|
help='What kind of action, do you want "add" or "remove" '
|
||||||
|
'hostnames'),
|
||||||
|
cfg.StrOpt('property_spec',
|
||||||
|
default='akamai_https_san_config_numbers',
|
||||||
|
help='Property spec of the property to be updated'),
|
||||||
|
cfg.StrOpt('san_cert_domain_suffix',
|
||||||
|
default='edgekey.net',
|
||||||
|
help='Property spec of the property to be updated'),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@cli.runnable
|
||||||
|
def run():
|
||||||
|
# TODO(kgriffs): For now, we have to use the global config
|
||||||
|
# to pick up common options from openstack.common.log, since
|
||||||
|
# that module uses the global CONF instance exclusively.
|
||||||
|
conf = cfg.ConfigOpts()
|
||||||
|
conf.register_cli_opts(CLI_OPT)
|
||||||
|
conf(prog='akamai-papi-update')
|
||||||
|
|
||||||
|
LOG.info("%s: %s to %s, on property: %s" % (
|
||||||
|
conf.action,
|
||||||
|
conf.domain_name,
|
||||||
|
conf.san_cert_name,
|
||||||
|
conf.property_spec
|
||||||
|
))
|
||||||
|
|
||||||
|
update_info_list = json.dumps([
|
||||||
|
(conf.action,
|
||||||
|
{
|
||||||
|
"cnameFrom": conf.domain_name,
|
||||||
|
"cnameTo": '.'.join([conf.san_cert_name,
|
||||||
|
conf.san_cert_domain_suffix]),
|
||||||
|
"cnameType": "EDGE_HOSTNAME"
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
update_property_flow.run_update_property_flow(
|
||||||
|
conf.property_spec, conf.update_type, update_info_list)
|
|
@ -55,9 +55,14 @@ class CreateProviderServicesTask(task.Task):
|
||||||
for domain in service_obj.domains:
|
for domain in service_obj.domains:
|
||||||
if domain.certificate == 'san':
|
if domain.certificate == 'san':
|
||||||
cert_for_domain = (
|
cert_for_domain = (
|
||||||
self.storage_controller.get_cert_by_domain(
|
self.storage_controller.get_certs_by_domain(
|
||||||
domain.domain, domain.certificate,
|
domain.domain,
|
||||||
service_obj.flavor_id, project_id))
|
project_id=project_id,
|
||||||
|
flavor_id=service_obj.flavor_id,
|
||||||
|
cert_type=domain.certificate
|
||||||
|
))
|
||||||
|
if cert_for_domain == []:
|
||||||
|
cert_for_domain = None
|
||||||
domain.cert_info = cert_for_domain
|
domain.cert_info = cert_for_domain
|
||||||
except ValueError:
|
except ValueError:
|
||||||
msg = 'Creating service {0} from Poppy failed. ' \
|
msg = 'Creating service {0} from Poppy failed. ' \
|
||||||
|
|
|
@ -46,6 +46,8 @@ def task_controllers(program, controller=None):
|
||||||
return service_controller, service_controller.storage_controller
|
return service_controller, service_controller.storage_controller
|
||||||
if controller == 'dns':
|
if controller == 'dns':
|
||||||
return service_controller, service_controller.dns_controller
|
return service_controller, service_controller.dns_controller
|
||||||
|
if controller == 'providers':
|
||||||
|
return service_controller, bootstrap_obj.manager.providers
|
||||||
if controller == 'ssl_certificate':
|
if controller == 'ssl_certificate':
|
||||||
return service_controller, (
|
return service_controller, (
|
||||||
bootstrap_obj.manager.ssl_certificate_controller)
|
bootstrap_obj.manager.ssl_certificate_controller)
|
||||||
|
|
|
@ -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.manager.base import background_job
|
||||||
from poppy.manager.base import driver
|
from poppy.manager.base import driver
|
||||||
from poppy.manager.base import flavors
|
from poppy.manager.base import flavors
|
||||||
from poppy.manager.base import home
|
from poppy.manager.base import home
|
||||||
|
@ -22,6 +23,7 @@ from poppy.manager.base import ssl_certificate
|
||||||
|
|
||||||
Driver = driver.ManagerDriverBase
|
Driver = driver.ManagerDriverBase
|
||||||
|
|
||||||
|
BackgroundJobController = background_job.BackgroundJobControllerBase
|
||||||
FlavorsController = flavors.FlavorsControllerBase
|
FlavorsController = flavors.FlavorsControllerBase
|
||||||
ServicesController = services.ServicesControllerBase
|
ServicesController = services.ServicesControllerBase
|
||||||
HomeController = home.HomeControllerBase
|
HomeController = home.HomeControllerBase
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# 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 abc
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
from poppy.manager.base import controller
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class BackgroundJobControllerBase(controller.ManagerControllerBase):
|
||||||
|
"""Health controller base class."""
|
||||||
|
|
||||||
|
def __init__(self, manager):
|
||||||
|
super(BackgroundJobControllerBase, self).__init__(manager)
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def post_job(self, job_type, args):
|
||||||
|
"""Returns the health of storage and providers
|
||||||
|
|
||||||
|
:raises: NotImplementedError
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
|
@ -0,0 +1,95 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from poppy.manager import base
|
||||||
|
from poppy.notification.mailgun import driver as n_driver
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.provider.akamai.background_jobs.check_cert_status_and_update import \
|
||||||
|
check_cert_status_and_update_flow
|
||||||
|
from poppy.provider.akamai.background_jobs.update_property import \
|
||||||
|
update_property_flow
|
||||||
|
from poppy.provider.akamai import driver as a_driver
|
||||||
|
|
||||||
|
conf = cfg.CONF
|
||||||
|
conf(project='poppy', prog='poppy', args=[])
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BackgroundJobController(base.BackgroundJobController):
|
||||||
|
|
||||||
|
def __init__(self, manager):
|
||||||
|
super(BackgroundJobController, self).__init__(manager)
|
||||||
|
self.distributed_task_controller = (
|
||||||
|
self._driver.distributed_task.services_controller)
|
||||||
|
self.akamai_san_cert_suffix = (
|
||||||
|
conf[a_driver.AKAMAI_GROUP].akamai_https_access_url_suffix)
|
||||||
|
self.notify_email_list = (
|
||||||
|
conf[n_driver.MAIL_NOTIFICATION_GROUP].recipients)
|
||||||
|
|
||||||
|
def post_job(self, job_type, kwargs):
|
||||||
|
kwargs = kwargs
|
||||||
|
if job_type == "akamai_check_and_update_cert_status":
|
||||||
|
LOG.info('Starting to check status on domain: %s,'
|
||||||
|
'for project_id: %s'
|
||||||
|
'flavor_id: %s, cert_type: %s' %
|
||||||
|
(
|
||||||
|
kwargs.get("domain_name"),
|
||||||
|
kwargs.get("project_id"),
|
||||||
|
kwargs.get("flavor_id"),
|
||||||
|
kwargs.get("cert_type")
|
||||||
|
))
|
||||||
|
self.distributed_task_controller.submit_task(
|
||||||
|
check_cert_status_and_update_flow.
|
||||||
|
check_cert_status_and_update_flow,
|
||||||
|
**kwargs)
|
||||||
|
elif job_type == "akamai_update_papi_property_for_mod_san":
|
||||||
|
LOG.info("%s: %s to %s, on property: %s" % (
|
||||||
|
kwargs.get("action", 'add'),
|
||||||
|
kwargs.get("domain_name"),
|
||||||
|
kwargs.get("san_cert_name"),
|
||||||
|
kwargs.get("property_spec", 'akamai_https_san_config_numbers')
|
||||||
|
))
|
||||||
|
|
||||||
|
t_kwargs = {}
|
||||||
|
|
||||||
|
update_info_list = json.dumps([
|
||||||
|
(kwargs.get("property_spec", 'add'),
|
||||||
|
{
|
||||||
|
"cnameFrom": kwargs.get("domain_name"),
|
||||||
|
"cnameTo": '.'.join([kwargs.get("san_cert_name"),
|
||||||
|
kwargs.get(
|
||||||
|
"san_cert_domain_suffix",
|
||||||
|
self.akamai_san_cert_suffix)]),
|
||||||
|
"cnameType": "EDGE_HOSTNAME"
|
||||||
|
})
|
||||||
|
])
|
||||||
|
|
||||||
|
t_kwargs = {
|
||||||
|
"property_spec": kwargs.get("property_spec",
|
||||||
|
'akamai_https_san_config_numbers'),
|
||||||
|
"update_type": kwargs.get("update_type", 'hostnames'),
|
||||||
|
"update_info_list": update_info_list,
|
||||||
|
"notify_email_list": self.notify_email_list
|
||||||
|
}
|
||||||
|
|
||||||
|
self.distributed_task_controller.submit_task(
|
||||||
|
update_property_flow.update_property_flow,
|
||||||
|
**t_kwargs)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError('job type: %s has not been implemented')
|
|
@ -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.manager.default import background_job
|
||||||
from poppy.manager.default import flavors
|
from poppy.manager.default import flavors
|
||||||
from poppy.manager.default import health
|
from poppy.manager.default import health
|
||||||
from poppy.manager.default import home
|
from poppy.manager.default import home
|
||||||
|
@ -20,6 +21,7 @@ from poppy.manager.default import services
|
||||||
from poppy.manager.default import ssl_certificate
|
from poppy.manager.default import ssl_certificate
|
||||||
|
|
||||||
|
|
||||||
|
BackgroundJob = background_job.BackgroundJobController
|
||||||
Home = home.DefaultHomeController
|
Home = home.DefaultHomeController
|
||||||
Flavors = flavors.DefaultFlavorsController
|
Flavors = flavors.DefaultFlavorsController
|
||||||
Health = health.DefaultHealthController
|
Health = health.DefaultHealthController
|
||||||
|
|
|
@ -44,6 +44,10 @@ class DefaultManagerDriver(base.Driver):
|
||||||
def health_controller(self):
|
def health_controller(self):
|
||||||
return controllers.Health(self)
|
return controllers.Health(self)
|
||||||
|
|
||||||
|
@decorators.lazy_property(write=False)
|
||||||
|
def background_job_controller(self):
|
||||||
|
return controllers.BackgroundJob(self)
|
||||||
|
|
||||||
@decorators.lazy_property(write=False)
|
@decorators.lazy_property(write=False)
|
||||||
def ssl_certificate_controller(self):
|
def ssl_certificate_controller(self):
|
||||||
return controllers.SSLCertificate(self)
|
return controllers.SSLCertificate(self)
|
||||||
|
|
|
@ -239,6 +239,18 @@ class DefaultServicesController(base.ServicesController):
|
||||||
existing_shared_domains[customer_domain] = domain.domain
|
existing_shared_domains[customer_domain] = domain.domain
|
||||||
domain.domain = customer_domain
|
domain.domain = customer_domain
|
||||||
|
|
||||||
|
# old domains need to bind as well
|
||||||
|
elif domain.certificate == 'san':
|
||||||
|
cert_for_domain = (
|
||||||
|
self.storage_controller.get_certs_by_domain(
|
||||||
|
domain.domain,
|
||||||
|
project_id=project_id,
|
||||||
|
flavor_id=service_old.flavor_id,
|
||||||
|
cert_type=domain.certificate))
|
||||||
|
if cert_for_domain == []:
|
||||||
|
cert_for_domain = None
|
||||||
|
domain.cert_info = cert_for_domain
|
||||||
|
|
||||||
service_old_json = json.loads(json.dumps(service_old.to_dict()))
|
service_old_json = json.loads(json.dumps(service_old.to_dict()))
|
||||||
|
|
||||||
# remove fields that cannot be part of PATCH
|
# remove fields that cannot be part of PATCH
|
||||||
|
@ -293,9 +305,13 @@ class DefaultServicesController(base.ServicesController):
|
||||||
|
|
||||||
elif domain.certificate == 'san':
|
elif domain.certificate == 'san':
|
||||||
cert_for_domain = (
|
cert_for_domain = (
|
||||||
self.storage_controller.get_cert_by_domain(
|
self.storage_controller.get_certs_by_domain(
|
||||||
domain.domain, domain.certificate,
|
domain.domain,
|
||||||
service_new.flavor_id, project_id))
|
project_id=project_id,
|
||||||
|
flavor_id=service_new.flavor_id,
|
||||||
|
cert_type=domain.certificate))
|
||||||
|
if cert_for_domain == []:
|
||||||
|
cert_for_domain = None
|
||||||
domain.cert_info = cert_for_domain
|
domain.cert_info = cert_for_domain
|
||||||
|
|
||||||
# retrofit the access url info into
|
# retrofit the access url info into
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Copyright (c) 2015 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 oslo_config import cfg
|
||||||
|
from taskflow import engines
|
||||||
|
from taskflow.patterns import linear_flow
|
||||||
|
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.provider.akamai.background_jobs.check_cert_status_and_update import \
|
||||||
|
check_cert_status_and_update_tasks
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
conf = cfg.CONF
|
||||||
|
conf(project='poppy', prog='poppy', args=[])
|
||||||
|
|
||||||
|
|
||||||
|
def check_cert_status_and_update_flow():
|
||||||
|
flow = linear_flow.Flow('Update Akamai Property').add(
|
||||||
|
check_cert_status_and_update_tasks.GetCertInfoTask(),
|
||||||
|
check_cert_status_and_update_tasks.CheckCertStatusTask(),
|
||||||
|
check_cert_status_and_update_tasks.UpdateCertStatusTask()
|
||||||
|
)
|
||||||
|
return flow
|
||||||
|
|
||||||
|
|
||||||
|
def run_check_cert_status_and_update_flow(domain_name, cert_type, flavor_id,
|
||||||
|
project_id):
|
||||||
|
e = engines.load(
|
||||||
|
check_cert_status_and_update_flow(),
|
||||||
|
store={
|
||||||
|
'domain_name': domain_name,
|
||||||
|
'cert_type': cert_type,
|
||||||
|
'flavor_id': flavor_id,
|
||||||
|
'project_id': project_id
|
||||||
|
},
|
||||||
|
engine='serial')
|
||||||
|
e.run()
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Copyright (c) 2015 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
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from taskflow import task
|
||||||
|
|
||||||
|
from poppy.distributed_task.utils import memoized_controllers
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.transport.pecan.models.request import ssl_certificate
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
conf = cfg.CONF
|
||||||
|
conf(project='poppy', prog='poppy', args=[])
|
||||||
|
|
||||||
|
|
||||||
|
class GetCertInfoTask(task.Task):
|
||||||
|
default_provides = "cert_obj_json"
|
||||||
|
|
||||||
|
def execute(self, domain_name, cert_type, flavor_id, project_id):
|
||||||
|
service_controller, self.storage_controller = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'storage')
|
||||||
|
res = self.storage_controller.get_certs_by_domain(
|
||||||
|
domain_name, project_id=project_id,
|
||||||
|
flavor_id=flavor_id, cert_type=cert_type)
|
||||||
|
if res is None:
|
||||||
|
return ""
|
||||||
|
return json.dumps(res.to_dict())
|
||||||
|
|
||||||
|
|
||||||
|
class CheckCertStatusTask(task.Task):
|
||||||
|
default_provides = "status_change_to"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(CheckCertStatusTask, self).__init__()
|
||||||
|
service_controller, self.providers = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'providers')
|
||||||
|
self.akamai_driver = self.providers['akamai'].obj
|
||||||
|
|
||||||
|
def execute(self, cert_obj_json):
|
||||||
|
if cert_obj_json != "":
|
||||||
|
cert_obj = ssl_certificate.load_from_json(json.loads(cert_obj_json)
|
||||||
|
)
|
||||||
|
latest_sps_id = cert_obj.cert_details['Akamai']['extra_info'].get(
|
||||||
|
'akamai_spsId')
|
||||||
|
|
||||||
|
if latest_sps_id is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
resp = self.akamai_driver.akamai_sps_api_client.get(
|
||||||
|
self.akamai_driver.akamai_sps_api_base_url.format(
|
||||||
|
spsId=latest_sps_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise RuntimeError('SPS API Request Failed'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
|
||||||
|
status = json.loads(resp.text)['requestList'][0]['status']
|
||||||
|
|
||||||
|
# This SAN Cert is on pending status
|
||||||
|
if status != 'SPS Request Complete':
|
||||||
|
LOG.info("SPS Not completed for %s..." %
|
||||||
|
self.cert)
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
LOG.info("SPS completed for %s..." %
|
||||||
|
cert_obj.get_san_edge_name())
|
||||||
|
return "deployed"
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateCertStatusTask(task.Task):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(UpdateCertStatusTask, self).__init__()
|
||||||
|
service_controller, self.storage_controller = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'storage')
|
||||||
|
|
||||||
|
def execute(self, project_id, cert_obj_json, status_change_to):
|
||||||
|
if cert_obj_json != "":
|
||||||
|
cert_obj = ssl_certificate.load_from_json(json.loads(cert_obj_json)
|
||||||
|
)
|
||||||
|
cert_details = cert_obj.cert_details
|
||||||
|
|
||||||
|
if status_change_to == "deployed":
|
||||||
|
cert_details['Akamai']['extra_info']['status'] = 'deployed'
|
||||||
|
cert_details['Akamai'] = json.dumps(cert_details['Akamai'])
|
||||||
|
self.storage_controller.update_cert_info(cert_obj.domain_name,
|
||||||
|
cert_obj.cert_type,
|
||||||
|
cert_obj.flavor_id,
|
||||||
|
cert_details)
|
||||||
|
|
||||||
|
service_obj = (
|
||||||
|
self.storage_controller.
|
||||||
|
get_service_details_by_domain_name(cert_obj.domain_name)
|
||||||
|
)
|
||||||
|
# Update provider details
|
||||||
|
if service_obj is not None:
|
||||||
|
service_obj.provider_details['Akamai'].\
|
||||||
|
domains_certificate_status.\
|
||||||
|
set_domain_certificate_status(cert_obj.domain_name,
|
||||||
|
'deployed')
|
||||||
|
self.storage_controller.update_provider_details(
|
||||||
|
project_id,
|
||||||
|
service_obj.service_id,
|
||||||
|
service_obj.provider_details
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pass
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Copyright (c) 2015 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 oslo_config import cfg
|
||||||
|
from taskflow import engines
|
||||||
|
from taskflow.patterns import linear_flow
|
||||||
|
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
from poppy.provider.akamai.background_jobs.update_property import (
|
||||||
|
update_property_tasks)
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
conf = cfg.CONF
|
||||||
|
conf(project='poppy', prog='poppy', args=[])
|
||||||
|
|
||||||
|
|
||||||
|
def update_property_flow():
|
||||||
|
flow = linear_flow.Flow('Update Akamai Property').add(
|
||||||
|
update_property_tasks.PropertyGetLatestVersionTask(),
|
||||||
|
update_property_tasks.PropertyUpdateTask(),
|
||||||
|
update_property_tasks.PropertyActivateTask()
|
||||||
|
)
|
||||||
|
return flow
|
||||||
|
|
||||||
|
|
||||||
|
def run_update_property_flow(property_spec, update_type, update_info_list):
|
||||||
|
e = engines.load(
|
||||||
|
update_property_flow(),
|
||||||
|
store={
|
||||||
|
"property_spec": property_spec,
|
||||||
|
"update_type": update_type,
|
||||||
|
"update_info_list": update_info_list
|
||||||
|
},
|
||||||
|
engine='serial')
|
||||||
|
e.run()
|
|
@ -0,0 +1,276 @@
|
||||||
|
# Copyright (c) 2015 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
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from taskflow import task
|
||||||
|
|
||||||
|
from poppy.distributed_task.utils import memoized_controllers
|
||||||
|
from poppy.openstack.common import log
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
conf = cfg.CONF
|
||||||
|
conf(project='poppy', prog='poppy', args=[])
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyGetLatestVersionTask(task.Task):
|
||||||
|
default_provides = "new_version_number"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(PropertyGetLatestVersionTask, self).__init__()
|
||||||
|
service_controller, self.providers = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'providers')
|
||||||
|
self.akamai_driver = self.providers['akamai'].obj
|
||||||
|
self.sc = self.akamai_driver.service_controller
|
||||||
|
self.akamai_conf = self.akamai_driver.akamai_conf
|
||||||
|
|
||||||
|
def execute(self, property_spec):
|
||||||
|
"""Get/Create a new Akamai property update version if necessary"""
|
||||||
|
self.property_id = self.akamai_driver.papi_property_id(property_spec)
|
||||||
|
|
||||||
|
LOG.info('Starting to get next version for property: %s'
|
||||||
|
% self.property_id)
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.get(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s' % self.property_id)
|
||||||
|
)
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
else:
|
||||||
|
a_property = json.loads(resp.text)['properties']['items'][0]
|
||||||
|
latestVersion = a_property['latestVersion'] or 0
|
||||||
|
production_version = a_property['productionVersion'] or -1
|
||||||
|
staging_version = a_property['stagingVersion'] or -1
|
||||||
|
|
||||||
|
max_version = max(latestVersion, production_version,
|
||||||
|
staging_version)
|
||||||
|
|
||||||
|
if production_version == -1 and staging_version == -1:
|
||||||
|
# if the max version has not been activated yet
|
||||||
|
# we just reuse the max version
|
||||||
|
LOG.info("New version for : %s is %s" % (self.property_id,
|
||||||
|
str(max_version)))
|
||||||
|
return max_version
|
||||||
|
else:
|
||||||
|
# else now we need to create a new version (bump up a version)
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.get(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/versions/%s' % (
|
||||||
|
self.property_id, str(max_version)))
|
||||||
|
)
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
etag = json.loads(resp.text)['versions']['items'][0]['etag']
|
||||||
|
# create a new version
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.post(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/versions' % (
|
||||||
|
self.property_id)),
|
||||||
|
data=json.dumps({
|
||||||
|
'createFromVersion': max_version,
|
||||||
|
'createFromEtag': etag
|
||||||
|
}),
|
||||||
|
headers={'Content-type': 'application/json'}
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 201:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
LOG.info("New version for : %s is %s" % (self.property_id,
|
||||||
|
str(max_version+1)))
|
||||||
|
return max_version + 1
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyUpdateTask(task.Task):
|
||||||
|
default_provides = 'update_detail'
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(PropertyUpdateTask, self).__init__()
|
||||||
|
service_controller, self.providers = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'providers')
|
||||||
|
self.akamai_driver = self.providers['akamai'].obj
|
||||||
|
self.sc = self.akamai_driver.service_controller
|
||||||
|
self.akamai_conf = self.akamai_driver.akamai_conf
|
||||||
|
|
||||||
|
self.existing_hosts = []
|
||||||
|
self.existing_edgehostnames = []
|
||||||
|
|
||||||
|
def execute(self, property_spec, new_version_number, update_type,
|
||||||
|
update_info_list):
|
||||||
|
"""Update an Akamai property"""
|
||||||
|
self.property_id = self.akamai_driver.papi_property_id(property_spec)
|
||||||
|
|
||||||
|
update_info_list = json.loads(update_info_list)
|
||||||
|
update_detail = ""
|
||||||
|
|
||||||
|
# avoid loading hostnames multiple times
|
||||||
|
if update_type == 'hostnames':
|
||||||
|
if self.existing_hosts == []:
|
||||||
|
LOG.info("Getting Hostnames...")
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.get(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/versions/%s/hostnames' %
|
||||||
|
(self.property_id,
|
||||||
|
str(new_version_number)))
|
||||||
|
)
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
self.existing_hosts = json.loads(resp.text)['hostnames'][
|
||||||
|
'items']
|
||||||
|
# message should be a list assembled hosts dictionary
|
||||||
|
for action, host_info in update_info_list:
|
||||||
|
# add new hosts
|
||||||
|
if action == 'add':
|
||||||
|
cnameToEdgeHostname = host_info['cnameTo']
|
||||||
|
# avoid loading edgehostnames multiple times
|
||||||
|
if self.existing_edgehostnames == []:
|
||||||
|
LOG.info("Getting EdgeHostnames...")
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.\
|
||||||
|
get(
|
||||||
|
self.akamai_driver.
|
||||||
|
akamai_papi_api_base_url.format(
|
||||||
|
middle_part='edgehostnames')
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
self.existing_edgehostnames = (
|
||||||
|
json.loads(resp.text)['edgeHostnames']['items']
|
||||||
|
)
|
||||||
|
|
||||||
|
for edgehostname in self.existing_edgehostnames:
|
||||||
|
if (edgehostname['domainPrefix'] ==
|
||||||
|
cnameToEdgeHostname.replace(
|
||||||
|
edgehostname['domainSuffix'], "")[:-1]):
|
||||||
|
host_info['edgeHostnameId'] = (
|
||||||
|
edgehostname['edgeHostnameId'])
|
||||||
|
|
||||||
|
self.existing_hosts.append(host_info)
|
||||||
|
update_detail = "Add cnameFrom: %s to cnameTo %s" % (
|
||||||
|
host_info['cnameFrom'], host_info['cnameTo'])
|
||||||
|
# remove a hosts
|
||||||
|
elif action == 'remove':
|
||||||
|
for idx, existing_host_info in enumerate(
|
||||||
|
self.existing_hosts):
|
||||||
|
if existing_host_info['cnameFrom'] == (
|
||||||
|
host_info['cnameFrom']):
|
||||||
|
del self.existing_hosts[idx]
|
||||||
|
break
|
||||||
|
update_detail = ("Remove cnameFrom: %s to cnameTo %s"
|
||||||
|
% (host_info['cnameFrom'],
|
||||||
|
host_info['cnameTo']))
|
||||||
|
|
||||||
|
LOG.info('Start Updating Hostnames: %s' %
|
||||||
|
str(self.existing_hosts))
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.put(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/versions/%s/hostnames' % (
|
||||||
|
self.property_id,
|
||||||
|
str(new_version_number))),
|
||||||
|
data=json.dumps(self.existing_hosts),
|
||||||
|
headers={'Content-type': 'application/json'}
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
LOG.info("Updating property hostnames response code: %s" %
|
||||||
|
str(resp.status_code))
|
||||||
|
LOG.info("Updating property hostnames response text: %s" %
|
||||||
|
str(resp.text))
|
||||||
|
else:
|
||||||
|
LOG.info("Update property hostnames successful...")
|
||||||
|
# Handle secureEdgeHost addition
|
||||||
|
elif update_type == 'secureEdgeHost':
|
||||||
|
# Note(tonytan4ever): This will be used when adding custom cert
|
||||||
|
pass
|
||||||
|
elif update_type == 'rules':
|
||||||
|
pass
|
||||||
|
|
||||||
|
return update_detail
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyActivateTask(task.Task):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(PropertyActivateTask, self).__init__()
|
||||||
|
service_controller, self.providers = \
|
||||||
|
memoized_controllers.task_controllers('poppy', 'providers')
|
||||||
|
self.akamai_driver = self.providers['akamai'].obj
|
||||||
|
self.akamai_conf = self.akamai_driver.akamai_conf
|
||||||
|
self.sc = self.akamai_driver.service_controller
|
||||||
|
|
||||||
|
def execute(self, property_spec, new_version_number, update_detail,
|
||||||
|
notify_email_list=[]):
|
||||||
|
"""Update an Akamai property"""
|
||||||
|
self.property_id = self.akamai_driver.papi_property_id(property_spec)
|
||||||
|
|
||||||
|
# This request needs json
|
||||||
|
LOG.info('Starting activating version: %s for property: %s' %
|
||||||
|
(new_version_number,
|
||||||
|
self.property_id))
|
||||||
|
data = {
|
||||||
|
'propertyVersion': new_version_number,
|
||||||
|
'network': 'PRODUCTION',
|
||||||
|
'note': 'Updating configuration for property %s: %s' % (
|
||||||
|
self.property_id, update_detail),
|
||||||
|
'notifyEmails': notify_email_list,
|
||||||
|
}
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.post(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/activations' %
|
||||||
|
self.property_id),
|
||||||
|
data=json.dumps(data),
|
||||||
|
headers={'Content-type': 'application/json'}
|
||||||
|
)
|
||||||
|
# Here activation API call will return a 400,
|
||||||
|
# with all the messageIds need to handle that not as
|
||||||
|
# an exception
|
||||||
|
if resp.status_code != 201 and resp.status_code != 400:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
# else extract out all the warnings
|
||||||
|
# acknowledgementWarning
|
||||||
|
if resp.status_code == 400:
|
||||||
|
LOG.info("response text: %s" % resp.text)
|
||||||
|
warnings = [warning['messageId'] for warning in
|
||||||
|
json.loads(resp.text)['warnings']]
|
||||||
|
data['acknowledgeWarnings'] = warnings
|
||||||
|
resp = self.akamai_driver.akamai_papi_api_client.post(
|
||||||
|
self.akamai_driver.akamai_papi_api_base_url.format(
|
||||||
|
middle_part='properties/%s/activations/' %
|
||||||
|
self.property_id),
|
||||||
|
data=json.dumps(data),
|
||||||
|
headers={'Content-type': 'application/json'}
|
||||||
|
)
|
||||||
|
if resp.status_code != 201:
|
||||||
|
raise RuntimeError('PAPI API request failed.'
|
||||||
|
'Exception: %s' % resp.text)
|
||||||
|
|
||||||
|
# first get the activation id
|
||||||
|
# activation id is inside of activation link itself
|
||||||
|
activation_link = json.loads(resp.text)['activationLink']
|
||||||
|
LOG.info("Activation link: %s" % activation_link)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"activation_link": activation_link
|
||||||
|
}
|
||||||
|
|
||||||
|
def revert(self, property_spec, new_version_number, **kwargs):
|
||||||
|
LOG.info('retrying task: %s ...' % self.name)
|
|
@ -102,14 +102,18 @@ AKAMAI_OPTIONS = [
|
||||||
cfg.StrOpt(
|
cfg.StrOpt(
|
||||||
'group_id',
|
'group_id',
|
||||||
help='Operator groupID'),
|
help='Operator groupID'),
|
||||||
cfg.StrOpt(
|
|
||||||
'property_id',
|
|
||||||
help='Operator propertyID')
|
|
||||||
]
|
]
|
||||||
|
|
||||||
AKAMAI_GROUP = 'drivers:provider:akamai'
|
AKAMAI_GROUP = 'drivers:provider:akamai'
|
||||||
|
|
||||||
|
|
||||||
|
VALID_PROPERTY_SPEC = [
|
||||||
|
"akamai_http_config_number",
|
||||||
|
"akamai_https_shared_config_number",
|
||||||
|
"akamai_https_san_config_numbers",
|
||||||
|
"akamai_https_custom_config_numbers"]
|
||||||
|
|
||||||
|
|
||||||
class CDNProvider(base.Driver):
|
class CDNProvider(base.Driver):
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
|
@ -164,11 +168,20 @@ class CDNProvider(base.Driver):
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
|
|
||||||
self.akamai_sps_api_client = self.akamai_policy_api_client
|
self.akamai_papi_api_base_url = ''.join([
|
||||||
|
str(self.akamai_conf.policy_api_base_url),
|
||||||
|
'papi/v0/{middle_part}/'
|
||||||
|
'?contractId=ctr_%s&groupId=grp_%s' % (
|
||||||
|
self.akamai_conf.contract_id,
|
||||||
|
self.akamai_conf.group_id)
|
||||||
|
])
|
||||||
|
|
||||||
self.san_cert_cnames = self.akamai_conf.san_cert_cnames
|
self.san_cert_cnames = self.akamai_conf.san_cert_cnames
|
||||||
self.san_cert_hostname_limit = self.akamai_conf.san_cert_hostname_limit
|
self.san_cert_hostname_limit = self.akamai_conf.san_cert_hostname_limit
|
||||||
|
|
||||||
|
self.akamai_sps_api_client = self.akamai_policy_api_client
|
||||||
|
self.akamai_papi_api_client = self.akamai_policy_api_client
|
||||||
|
|
||||||
self.mod_san_queue = (
|
self.mod_san_queue = (
|
||||||
zookeeper_queue.ZookeeperModSanQueue(self._conf))
|
zookeeper_queue.ZookeeperModSanQueue(self._conf))
|
||||||
|
|
||||||
|
@ -229,6 +242,16 @@ class CDNProvider(base.Driver):
|
||||||
def papi_api_client(self):
|
def papi_api_client(self):
|
||||||
return self.akamai_papi_api_client
|
return self.akamai_papi_api_client
|
||||||
|
|
||||||
|
def papi_property_id(self, property_spec):
|
||||||
|
if property_spec not in VALID_PROPERTY_SPEC:
|
||||||
|
raise ValueError('No a valid property spec: %s'
|
||||||
|
', valid property specs are: %s'
|
||||||
|
% (property_spec, VALID_PROPERTY_SPEC))
|
||||||
|
prp_number = self.akamai_conf[property_spec]
|
||||||
|
if isinstance(prp_number, list):
|
||||||
|
prp_number = prp_number[0]
|
||||||
|
return 'prp_%s' % self.akamai_conf[property_spec][0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service_controller(self):
|
def service_controller(self):
|
||||||
"""Returns the driver's hostname controller."""
|
"""Returns the driver's hostname controller."""
|
||||||
|
|
|
@ -892,10 +892,13 @@ class ServicesController(base.ServicesController):
|
||||||
CQL_SEARCH_BY_DOMAIN,
|
CQL_SEARCH_BY_DOMAIN,
|
||||||
consistency_level=self._driver.consistency_level)
|
consistency_level=self._driver.consistency_level)
|
||||||
results = self.session.execute(stmt, args)
|
results = self.session.execute(stmt, args)
|
||||||
|
# If there is not service with this domain
|
||||||
|
# return None
|
||||||
|
details = None
|
||||||
for r in results:
|
for r in results:
|
||||||
proj_id = r.get('project_id')
|
proj_id = r.get('project_id')
|
||||||
service = r.get('service_id')
|
service = r.get('service_id')
|
||||||
details = self.get(proj_id, service)
|
details = self.get(proj_id, service)
|
||||||
return details
|
return details
|
||||||
|
|
||||||
def update_provider_details(self, project_id, service_id,
|
def update_provider_details(self, project_id, service_id,
|
||||||
|
|
|
@ -14,11 +14,13 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import random
|
||||||
|
|
||||||
from poppy.model.helpers import domain
|
from poppy.model.helpers import domain
|
||||||
from poppy.model.helpers import origin
|
from poppy.model.helpers import origin
|
||||||
from poppy.model.helpers import provider_details
|
from poppy.model.helpers import provider_details
|
||||||
from poppy.model import service
|
from poppy.model import service
|
||||||
|
from poppy.model import ssl_certificate
|
||||||
from poppy.storage import base
|
from poppy.storage import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,6 +168,9 @@ class ServicesController(base.ServicesController):
|
||||||
if key in self.certs:
|
if key in self.certs:
|
||||||
self.certs[key].cert_details = cert_details
|
self.certs[key].cert_details = cert_details
|
||||||
|
|
||||||
|
def get_service_details_by_domain_name(self, domain_name):
|
||||||
|
pass
|
||||||
|
|
||||||
def create_cert(self, project_id, cert_obj):
|
def create_cert(self, project_id, cert_obj):
|
||||||
key = (cert_obj.flavor_id, cert_obj.domain_name, cert_obj.cert_type)
|
key = (cert_obj.flavor_id, cert_obj.domain_name, cert_obj.cert_type)
|
||||||
if key not in self.certs:
|
if key not in self.certs:
|
||||||
|
@ -173,12 +178,33 @@ class ServicesController(base.ServicesController):
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
def get_certs_by_domain(self, domain_name, project_id=None):
|
def get_certs_by_domain(self, domain_name, project_id=None, flavor_id=None,
|
||||||
|
cert_type=None):
|
||||||
certs = []
|
certs = []
|
||||||
for cert in self.certs:
|
for cert in self.certs:
|
||||||
if domain_name in cert:
|
if domain_name in cert:
|
||||||
certs.append(self.certs[cert])
|
certs.append(self.certs[cert])
|
||||||
if project_id:
|
if project_id:
|
||||||
|
if flavor_id is not None and cert_type is not None:
|
||||||
|
return ssl_certificate.SSLCertificate(
|
||||||
|
"premium",
|
||||||
|
"blog.testabcd.com",
|
||||||
|
"san",
|
||||||
|
project_id=project_id,
|
||||||
|
cert_details={
|
||||||
|
'Akamai': {
|
||||||
|
u'cert_domain': u'secure2.san1.test_123.com',
|
||||||
|
u'extra_info': {
|
||||||
|
u'action': u'Waiting for customer domain '
|
||||||
|
'validation for blog.testabc.com',
|
||||||
|
u'akamai_spsId': str(random.randint(1, 100000)
|
||||||
|
),
|
||||||
|
u'create_at': u'2015-09-29 16:09:12.429147',
|
||||||
|
u'san cert': u'secure2.san1.test_123.com',
|
||||||
|
u'status': u'create_in_progress'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
return [cert for cert in certs if cert.project_id == project_id]
|
return [cert for cert in certs if cert.project_id == project_id]
|
||||||
else:
|
else:
|
||||||
return certs
|
return certs
|
||||||
|
|
|
@ -22,6 +22,7 @@ from poppy.transport.pecan.controllers import base
|
||||||
from poppy.transport.pecan import hooks as poppy_hooks
|
from poppy.transport.pecan import hooks as poppy_hooks
|
||||||
from poppy.transport.pecan.models.response import service as resp_service_model
|
from poppy.transport.pecan.models.response import service as resp_service_model
|
||||||
from poppy.transport.validators import helpers
|
from poppy.transport.validators import helpers
|
||||||
|
from poppy.transport.validators.schemas import background_jobs
|
||||||
from poppy.transport.validators.schemas import domain_migration
|
from poppy.transport.validators.schemas import domain_migration
|
||||||
from poppy.transport.validators.schemas import service_action
|
from poppy.transport.validators.schemas import service_action
|
||||||
from poppy.transport.validators.schemas import service_limit
|
from poppy.transport.validators.schemas import service_limit
|
||||||
|
@ -73,10 +74,40 @@ class DomainMigrationController(base.Controller, hooks.HookController):
|
||||||
return pecan.Response(None, 202)
|
return pecan.Response(None, 202)
|
||||||
|
|
||||||
|
|
||||||
|
class BackgroundJobController(base.Controller, hooks.HookController):
|
||||||
|
__hooks__ = [poppy_hooks.Context(), poppy_hooks.Error()]
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BackgroundJobController, self).__init__(driver)
|
||||||
|
|
||||||
|
@pecan.expose('json')
|
||||||
|
@decorators.validate(
|
||||||
|
request=rule.Rule(
|
||||||
|
helpers.json_matches_service_schema(
|
||||||
|
background_jobs.BackgroundJobSchema.get_schema(
|
||||||
|
"background_jobs", "POST")),
|
||||||
|
helpers.abort_with_message,
|
||||||
|
stoplight_helpers.pecan_getter))
|
||||||
|
def post(self):
|
||||||
|
request_json = json.loads(pecan.request.body.decode('utf-8'))
|
||||||
|
job_type = request_json.pop('job_type')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._driver.manager.background_job_controller.post_job(
|
||||||
|
job_type,
|
||||||
|
request_json
|
||||||
|
)
|
||||||
|
except NotImplementedError as e:
|
||||||
|
pecan.abort(404, str(e))
|
||||||
|
|
||||||
|
return pecan.Response(None, 202)
|
||||||
|
|
||||||
|
|
||||||
class AkamaiController(base.Controller, hooks.HookController):
|
class AkamaiController(base.Controller, hooks.HookController):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(AkamaiController, self).__init__(driver)
|
super(AkamaiController, self).__init__(driver)
|
||||||
self.__class__.service = DomainMigrationController(driver)
|
self.__class__.service = DomainMigrationController(driver)
|
||||||
|
self.__class__.background_job = BackgroundJobController(driver)
|
||||||
|
|
||||||
|
|
||||||
class ProviderController(base.Controller, hooks.HookController):
|
class ProviderController(base.Controller, hooks.HookController):
|
||||||
|
|
|
@ -20,5 +20,8 @@ def load_from_json(json_data):
|
||||||
flavor_id = json_data.get("flavor_id")
|
flavor_id = json_data.get("flavor_id")
|
||||||
domain_name = json_data.get("domain_name")
|
domain_name = json_data.get("domain_name")
|
||||||
cert_type = json_data.get("cert_type")
|
cert_type = json_data.get("cert_type")
|
||||||
|
project_id = json_data.get("project_id")
|
||||||
|
cert_details = json_data.get("cert_details", {})
|
||||||
|
|
||||||
return ssl_certificate.SSLCertificate(flavor_id, domain_name, cert_type)
|
return ssl_certificate.SSLCertificate(flavor_id, domain_name,
|
||||||
|
cert_type, project_id, cert_details)
|
||||||
|
|
|
@ -108,6 +108,7 @@ class Model(collections.OrderedDict):
|
||||||
continue
|
continue
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if 'operator_url' in access_url:
|
if 'operator_url' in access_url:
|
||||||
self['links'].append(link.Model(
|
self['links'].append(link.Model(
|
||||||
access_url['operator_url'],
|
access_url['operator_url'],
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright (c) 2015 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.transport.validators import schema_base
|
||||||
|
|
||||||
|
|
||||||
|
class BackgroundJobSchema(schema_base.SchemaBase):
|
||||||
|
|
||||||
|
'''JSON Schmema validation for /admin/provider/akamai/background_jobs'''
|
||||||
|
|
||||||
|
schema = {
|
||||||
|
'background_jobs': {
|
||||||
|
'POST': {
|
||||||
|
'type': [{
|
||||||
|
'additionalProperties': False,
|
||||||
|
'properties': {
|
||||||
|
'job_type': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True,
|
||||||
|
'enum': ['akamai_check_and_update_cert_status']
|
||||||
|
},
|
||||||
|
'domain_name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True
|
||||||
|
},
|
||||||
|
'project_id': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True
|
||||||
|
},
|
||||||
|
'cert_type': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True,
|
||||||
|
'enum': ['san']
|
||||||
|
},
|
||||||
|
'flavor_id': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'additionalProperties': False,
|
||||||
|
'properties': {
|
||||||
|
'job_type': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True,
|
||||||
|
'enum': ['akamai_update_papi_property_for_mod_san']
|
||||||
|
},
|
||||||
|
'domain_name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True
|
||||||
|
},
|
||||||
|
'san_cert_name': {
|
||||||
|
'type': 'string',
|
||||||
|
'required': True
|
||||||
|
},
|
||||||
|
'update_type': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['hostsnames']
|
||||||
|
},
|
||||||
|
'action': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['add', 'remove']
|
||||||
|
},
|
||||||
|
'property_spec': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['akamai_https_san_config_numbers']
|
||||||
|
},
|
||||||
|
'san_cert_domain_suffix': {
|
||||||
|
'type': 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ upload-dir = doc/build/html
|
||||||
console_scripts =
|
console_scripts =
|
||||||
poppy-server = poppy.cmd.server:run
|
poppy-server = poppy.cmd.server:run
|
||||||
poppy-worker = poppy.cmd.task_flow_worker:run
|
poppy-worker = poppy.cmd.task_flow_worker:run
|
||||||
|
akamai-cert-status-check-and-update = poppy.cmd.akamai_check_and_update_cert_status:run
|
||||||
|
akamai-property-udpate-mod-san = poppy.cmd.akamai_update_papi_property_for_mod_san:run
|
||||||
|
|
||||||
poppy.transport =
|
poppy.transport =
|
||||||
pecan = poppy.transport.pecan:Driver
|
pecan = poppy.transport.pecan:Driver
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
[drivers]
|
[drivers]
|
||||||
providers = mock,maxcdn,cloudfront,fastly
|
providers = mock,maxcdn,akamai,fastly
|
||||||
transport = pecan
|
transport = pecan
|
||||||
manager = default
|
manager = default
|
||||||
storage = mockdb
|
storage = mockdb
|
||||||
dns = default
|
dns = default
|
||||||
|
notifications = mailgun
|
||||||
|
|
||||||
[drivers:storage:cassandra]
|
[drivers:storage:cassandra]
|
||||||
cluster = "192.168.59.103"
|
cluster = "192.168.59.103"
|
||||||
|
@ -18,9 +19,15 @@ alias = "MYALIAS"
|
||||||
consumer_secret = "MYCONSUMER_SECRET"
|
consumer_secret = "MYCONSUMER_SECRET"
|
||||||
consumer_key = "MYCONSUMERKEY"
|
consumer_key = "MYCONSUMERKEY"
|
||||||
|
|
||||||
|
[drivers:provider:akamai]
|
||||||
|
akamai_https_access_url_suffix = "my_https_url_suffix"
|
||||||
|
|
||||||
[drivers:provider:cloudfront]
|
[drivers:provider:cloudfront]
|
||||||
aws_access_key_id = "MY_AWS_ACCESS_KEY_ID"
|
aws_access_key_id = "MY_AWS_ACCESS_KEY_ID"
|
||||||
aws_secret_access_key = "MY_AWS_SECRET_ACCESS_KEY"
|
aws_secret_access_key = "MY_AWS_SECRET_ACCESS_KEY"
|
||||||
|
|
||||||
|
[drivers:notification:mailgun]
|
||||||
|
recipients = "myrecipients@abc.com"
|
||||||
|
|
||||||
[drivers:transport:limits]
|
[drivers:transport:limits]
|
||||||
max_services_per_page = 20
|
max_services_per_page = 20
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"akamai_check_and_update_cert_status": {
|
||||||
|
"job_type": "akamai_check_and_update_cert_status",
|
||||||
|
"domain_name": "www.abc.com",
|
||||||
|
"flavor_id": "mock",
|
||||||
|
"cert_type": "san",
|
||||||
|
"project_id": "000"
|
||||||
|
},
|
||||||
|
"akamai_update_papi_property_for_mod_san": {
|
||||||
|
"job_type": "akamai_update_papi_property_for_mod_san",
|
||||||
|
"domain_name": "www.abc.com",
|
||||||
|
"san_cert_name": "secure1.test_san.com"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"invalid_job_type_name": {
|
||||||
|
"job_type": "nonsense",
|
||||||
|
"flavor_id": "mock"
|
||||||
|
},
|
||||||
|
"missing_cert_type": {
|
||||||
|
"job_type": "akamai_check_and_update_cert_status",
|
||||||
|
"domain_name": "www.abc.com",
|
||||||
|
"flavor_id": "mock",
|
||||||
|
"project_id": "000"
|
||||||
|
},
|
||||||
|
"missing_domain_name": {
|
||||||
|
"job_type": "akamai_check_and_update_cert_status",
|
||||||
|
"cert_type": "san",
|
||||||
|
"flavor_id": "mock",
|
||||||
|
"project_id": "000"
|
||||||
|
},
|
||||||
|
"missing_san_cert_name": {
|
||||||
|
"job_type": "akamai_check_and_update_cert_status",
|
||||||
|
"domain_name": "www.abc.com"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Copyright (c) 2015 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 uuid
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
|
||||||
|
from tests.functional.transport.pecan import base
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class BackgroundJobControllerTest(base.FunctionalTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(BackgroundJobControllerTest, self).setUp()
|
||||||
|
|
||||||
|
self.project_id = str(uuid.uuid1())
|
||||||
|
self.service_name = str(uuid.uuid1())
|
||||||
|
self.flavor_id = str(uuid.uuid1())
|
||||||
|
|
||||||
|
@ddt.file_data("data_post_background_jobs_bad_input.json")
|
||||||
|
def test_post_background_job_negative(self, background_job_json):
|
||||||
|
response = self.app.post('/v1.0/admin/provider/akamai/background_job',
|
||||||
|
headers={'Content-Type': 'application/json',
|
||||||
|
'X-Project-ID': self.project_id},
|
||||||
|
params=json.dumps(background_job_json),
|
||||||
|
expect_errors=True)
|
||||||
|
|
||||||
|
self.assertEqual(400, response.status_code)
|
||||||
|
|
||||||
|
@ddt.file_data("data_post_background_jobs.json")
|
||||||
|
def test_post_background_job_positive(self, background_job_json):
|
||||||
|
response = self.app.post('/v1.0/admin/provider/akamai/background_job',
|
||||||
|
headers={'Content-Type': 'application/json',
|
||||||
|
'X-Project-ID': self.project_id},
|
||||||
|
params=json.dumps(background_job_json))
|
||||||
|
|
||||||
|
self.assertEqual(202, response.status_code)
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2014 Rackspace, Inc.
|
# Copyright (c) 2015 Rackspace, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -0,0 +1,321 @@
|
||||||
|
# Copyright (c) 2015 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 random
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import json
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from poppy.model.helpers import domain
|
||||||
|
from poppy.model.helpers import origin
|
||||||
|
from poppy.model import service
|
||||||
|
from poppy.model import ssl_certificate
|
||||||
|
|
||||||
|
|
||||||
|
class MockBootStrap(mock.Mock):
|
||||||
|
|
||||||
|
def __init__(self, conf):
|
||||||
|
super(MockBootStrap, self).__init__()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def manager(self):
|
||||||
|
return MockManager()
|
||||||
|
|
||||||
|
|
||||||
|
class MockProviderDetails(mock.Mock):
|
||||||
|
|
||||||
|
def __init__(self, service_id):
|
||||||
|
super(MockProviderDetails, self).__init__()
|
||||||
|
self.service_id = service_id
|
||||||
|
|
||||||
|
def __getitem__(self, provider_name):
|
||||||
|
akamai_provider_detail_mock = mock.Mock()
|
||||||
|
akamai_provider_detail_mock.provider_service_id = ''.join([
|
||||||
|
'[{"protocol":',
|
||||||
|
' "https", "certificate": ',
|
||||||
|
'"san", "policy_name": "blog.testabc.com"}]'])
|
||||||
|
akamai_provider_detail_mock.status = 'deployed'
|
||||||
|
return akamai_provider_detail_mock
|
||||||
|
|
||||||
|
|
||||||
|
class MockManager(mock.Mock):
|
||||||
|
def __init__(self):
|
||||||
|
super(MockManager, self).__init__()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def providers(self):
|
||||||
|
akamai_mock_provider = mock.Mock()
|
||||||
|
akamai_mock_provider_obj = mock.Mock()
|
||||||
|
akamai_mock_provider_obj.service_controller = mock.Mock()
|
||||||
|
akamai_mock_provider_obj.akamai_conf = {
|
||||||
|
'property_id': 'prp_12345',
|
||||||
|
'contract_id': "B-ABCDE",
|
||||||
|
'group_id': 12345
|
||||||
|
}
|
||||||
|
akamai_mock_provider_obj.akamai_sps_api_client = MockSPSAPIClient()
|
||||||
|
akamai_mock_provider_obj.akamai_papi_api_client = MockPapiAPIClient()
|
||||||
|
akamai_mock_provider_obj.akamai_sps_api_base_url = (
|
||||||
|
'https://mybaseurl.net/config-secure-provisioning-service/'
|
||||||
|
'v1/sps-requests/{spsId}?'
|
||||||
|
'contractId=None&groupId=None')
|
||||||
|
akamai_mock_provider_obj.akamai_papi_api_base_url = (
|
||||||
|
'https://mybaseurl.net/papi/v0/{middle_part}/'
|
||||||
|
'?contractId=ctr_None&groupId=grp_None')
|
||||||
|
akamai_mock_provider.obj = akamai_mock_provider_obj
|
||||||
|
providers = {
|
||||||
|
'akamai': akamai_mock_provider,
|
||||||
|
}
|
||||||
|
return providers
|
||||||
|
|
||||||
|
@property
|
||||||
|
def services_controller(self):
|
||||||
|
sc = mock.Mock()
|
||||||
|
sc.storage_controller = MockStorageController()
|
||||||
|
return sc
|
||||||
|
|
||||||
|
|
||||||
|
class MockStorageController(mock.Mock):
|
||||||
|
|
||||||
|
def get_certs_by_domain(self, domain_name, project_id=None,
|
||||||
|
flavor_id=None,
|
||||||
|
cert_type=None):
|
||||||
|
|
||||||
|
return ssl_certificate.SSLCertificate(
|
||||||
|
"premium",
|
||||||
|
"blog.testabcd.com",
|
||||||
|
"san",
|
||||||
|
project_id=project_id,
|
||||||
|
cert_details={
|
||||||
|
'Akamai': {
|
||||||
|
u'cert_domain': u'secure2.san1.test_123.com',
|
||||||
|
u'extra_info': {
|
||||||
|
u'action': u'Waiting for customer domain '
|
||||||
|
'validation for blog.testabc.com',
|
||||||
|
u'akamai_spsId': str(random.randint(1, 100000)),
|
||||||
|
u'create_at': u'2015-09-29 16:09:12.429147',
|
||||||
|
u'san cert': u'secure2.san1.test_123.com',
|
||||||
|
u'status': u'create_in_progress'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_service_details_by_domain_name(self, domain_name):
|
||||||
|
r = service.Service(
|
||||||
|
str(uuid.uuid4()),
|
||||||
|
str(uuid.uuid4()),
|
||||||
|
[domain.Domain('wiki.cc', 'https', 'shared')],
|
||||||
|
[origin.Origin('mysite.com')],
|
||||||
|
"strawberry")
|
||||||
|
r.provider_details = MockProviderDetails(r.service_id)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
class MockPapiAPIClient(mock.Mock):
|
||||||
|
def __init__(self):
|
||||||
|
super(MockPapiAPIClient, self).__init__()
|
||||||
|
self.response_200 = mock.Mock(status_code=200)
|
||||||
|
|
||||||
|
def get(self, url):
|
||||||
|
if 'hostnames' in url:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"accountId": "act_1-ABCDE",
|
||||||
|
"contractId": "B-ABCDE",
|
||||||
|
"groupId": "grp_12345",
|
||||||
|
"propertyId": "prp_12345",
|
||||||
|
"propertyName": "ssl.san.test_123.com_pm",
|
||||||
|
"propertyVersion": 2,
|
||||||
|
"etag": str(uuid.uuid4()),
|
||||||
|
"hostnames": {
|
||||||
|
"items": [{
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1052022",
|
||||||
|
"cnameFrom": "www.testxxx.com",
|
||||||
|
"cnameTo": "ssl.test_123.com.edge_host_test.net"
|
||||||
|
}, {
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1126816",
|
||||||
|
"cnameFrom": "secure.san2.test_789.com",
|
||||||
|
"cnameTo": "secure.test_456.com.edge_host_test.net"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if 'edgehostnames' in url:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"accountId": "act_1-ABCDE",
|
||||||
|
"contractId": "B-ABCDE",
|
||||||
|
"groupId": "grp_12345",
|
||||||
|
"edgeHostnames": {
|
||||||
|
"items": [{
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1052022",
|
||||||
|
"domainPrefix": "secure1.san1.test_123.com",
|
||||||
|
"domainSuffix": "edge_host_test.net",
|
||||||
|
"ipVersionBehavior": "IPV4",
|
||||||
|
"secure": True,
|
||||||
|
"edgeHostnameDomain": "secure1.san1.test_123.com"
|
||||||
|
".edge_host_test.net"
|
||||||
|
}, {
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1159587",
|
||||||
|
"domainPrefix": "secure2.san1.test_123.com",
|
||||||
|
"domainSuffix": "edge_host_test.net",
|
||||||
|
"ipVersionBehavior": "IPV4",
|
||||||
|
"secure": True,
|
||||||
|
"edgeHostnameDomain": "secure2.san1.test_123.com"
|
||||||
|
".edge_host_test.net"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if 'activations' in url:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"activationId": "atv_2511473",
|
||||||
|
"status": "SUCCESS"
|
||||||
|
})
|
||||||
|
if 'versions' in url:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"propertyId": "prp_12345",
|
||||||
|
"propertyName": "secure.test_123.com_pm",
|
||||||
|
"accountId": "act_1-ABCDE",
|
||||||
|
"contractId": "B-ABCDE",
|
||||||
|
"groupId": "grp_12345",
|
||||||
|
"versions": {
|
||||||
|
"items": [{
|
||||||
|
"propertyVersion": 1,
|
||||||
|
"etag": str(uuid.uuid4())
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"properties": {
|
||||||
|
"items": [{
|
||||||
|
"accountId": "act_1-ABCDE",
|
||||||
|
"contractId": "B-ABCDE",
|
||||||
|
"groupId": "grp_12345",
|
||||||
|
"propertyId": "prp_12345",
|
||||||
|
"propertyName": "secure.test_123.com_pm",
|
||||||
|
"latestVersion": 2,
|
||||||
|
"stagingVersion": 2,
|
||||||
|
"productionVersion": 1
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.response_200.status_code = 200
|
||||||
|
return self.response_200
|
||||||
|
|
||||||
|
def post(self, url, data=None, headers=None):
|
||||||
|
if 'activations' in url:
|
||||||
|
self.response_200.status_code = 201
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"activationLink": "/papi/v0/properties/prp_227429/"
|
||||||
|
"activations/atv_2511473?contractId"
|
||||||
|
"=ctr_C-2M6JYA&groupId=grp_12345",
|
||||||
|
'warnings': []
|
||||||
|
})
|
||||||
|
if 'versions' in url:
|
||||||
|
self.response_200.status_code = 201
|
||||||
|
return self.response_200
|
||||||
|
|
||||||
|
def put(self, url, data=None, headers=None):
|
||||||
|
if 'hostnames' in url:
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"accountId": "act_1-ABCDE",
|
||||||
|
"contractId": "B-ABCDE",
|
||||||
|
"groupId": "grp_12345",
|
||||||
|
"propertyId": "prp_12345",
|
||||||
|
"propertyName": "ssl.san.test_123.com_pm",
|
||||||
|
"propertyVersion": 2,
|
||||||
|
"etag": str(uuid.uuid4()),
|
||||||
|
"hostnames": {
|
||||||
|
"items": [{
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1052022",
|
||||||
|
"cnameFrom": "secure.san1.test_789.com",
|
||||||
|
"cnameTo": "ssl.test_123.com.edge_host_test.net"
|
||||||
|
}, {
|
||||||
|
"cnameType": "EDGE_HOSTNAME",
|
||||||
|
"edgeHostnameId": "ehn_1126816",
|
||||||
|
"cnameFrom": "secure.san2.test_789.com",
|
||||||
|
"cnameTo": "secure.test_456.com.edge_host_test.net"
|
||||||
|
}, {
|
||||||
|
'cnameTo': 'secure.test_7891.com.edge_host_test.net',
|
||||||
|
'cnameFrom': 'www.blogyyy.com',
|
||||||
|
'edgeHostnameId': 'ehn_1126816',
|
||||||
|
'cnameType': u'EDGE_HOSTNAME'
|
||||||
|
}, {
|
||||||
|
'cnameTo': u'secure.test_7891.com.edge_host_test.net',
|
||||||
|
'cnameFrom': u'www.testxxx.com',
|
||||||
|
'edgeHostnameId': u'ehn_1126816',
|
||||||
|
'cnameType': u'EDGE_HOSTNAME'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return self.response_200
|
||||||
|
|
||||||
|
|
||||||
|
class MockSPSAPIClient(mock.Mock):
|
||||||
|
def __init__(self):
|
||||||
|
super(MockSPSAPIClient, self).__init__()
|
||||||
|
self.response_200 = mock.Mock(status_code=200)
|
||||||
|
|
||||||
|
def get(self, url):
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"requestList":
|
||||||
|
[{"resourceUrl": "/config-secure-provisioning-service/"
|
||||||
|
"v1/sps-requests/1849",
|
||||||
|
"parameters": [{
|
||||||
|
"name": "cnameHostname",
|
||||||
|
"value": "secure.san3.test_123.com"
|
||||||
|
}, {"name": "createType", "value": "san"},
|
||||||
|
{"name": "csr.cn",
|
||||||
|
"value": "secure.san3.test_123.com"},
|
||||||
|
{"name": "csr.c", "value": "US"},
|
||||||
|
{"name": "csr.st", "value": "TX"},
|
||||||
|
{"name": "csr.l", "value": "San Antonio"},
|
||||||
|
{"name": "csr.o", "value": "Rackspace US Inc."},
|
||||||
|
{"name": "csr.ou", "value": "IT"},
|
||||||
|
{"name": "csr.sans",
|
||||||
|
"value": "secure.san3.test_123.com"},
|
||||||
|
{"name": "organization-information.organization-name",
|
||||||
|
"value": "Rackspace US Inc."},
|
||||||
|
{"name": "organization-information.address-line-one",
|
||||||
|
"value": "1 Fanatical Place"},
|
||||||
|
{"name": "organization-information.city",
|
||||||
|
"value": "San Antonio"}],
|
||||||
|
"lastStatusChange": "2015-03-19T21:47:10Z",
|
||||||
|
"spsId": random.randint(1, 10000),
|
||||||
|
"status": "SPS Request Complete",
|
||||||
|
"jobId": random.randint(1, 100000)}]})
|
||||||
|
self.response_200.status_code = 200
|
||||||
|
return self.response_200
|
||||||
|
|
||||||
|
def post(self, url, data=None, headers=None):
|
||||||
|
self.response_200.status_code = 202
|
||||||
|
self.response_200.text = json.dumps({
|
||||||
|
"spsId": 1789,
|
||||||
|
"resourceLocation":
|
||||||
|
"/config-secure-provisioning-service/v1/sps-requests/1856",
|
||||||
|
"Results": {
|
||||||
|
"size": 1,
|
||||||
|
"data": [{
|
||||||
|
"text": None,
|
||||||
|
"results": {
|
||||||
|
"type": "SUCCESS",
|
||||||
|
"jobID": 44434}
|
||||||
|
}]}})
|
||||||
|
return self.response_200
|
||||||
|
|
||||||
|
def put(self, url, data=None, headers=None):
|
||||||
|
return self.response_200
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Copyright (c) 2015 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 mock
|
||||||
|
from taskflow import engines
|
||||||
|
|
||||||
|
from poppy.provider.akamai.background_jobs.check_cert_status_and_update \
|
||||||
|
import check_cert_status_and_update_flow
|
||||||
|
from poppy.provider.akamai.background_jobs.update_property import (
|
||||||
|
update_property_flow)
|
||||||
|
from tests.unit import base
|
||||||
|
from tests.unit.provider.akamai.background_jobs import akamai_mocks
|
||||||
|
|
||||||
|
|
||||||
|
class TestAkamaiBJFlowRuns(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestAkamaiBJFlowRuns, self).setUp()
|
||||||
|
|
||||||
|
bootstrap_patcher = mock.patch(
|
||||||
|
'poppy.bootstrap.Bootstrap',
|
||||||
|
new=akamai_mocks.MockBootStrap
|
||||||
|
)
|
||||||
|
bootstrap_patcher.start()
|
||||||
|
self.addCleanup(bootstrap_patcher.stop)
|
||||||
|
|
||||||
|
def test_check_cert_status_and_update_flow(self):
|
||||||
|
kwargs = {
|
||||||
|
'domain_name': "blog.testabc.com",
|
||||||
|
'cert_type': "san",
|
||||||
|
'flavor_id': "premium",
|
||||||
|
'project_id': "000"
|
||||||
|
}
|
||||||
|
engines.run(check_cert_status_and_update_flow.
|
||||||
|
check_cert_status_and_update_flow(),
|
||||||
|
store=kwargs)
|
||||||
|
|
||||||
|
def test_update_papi_flow(self):
|
||||||
|
kwargs = {
|
||||||
|
"property_spec": "akamai_https_san_config_numbers",
|
||||||
|
"update_type": "hostnames",
|
||||||
|
"update_info_list": json.dumps([
|
||||||
|
(
|
||||||
|
"add",
|
||||||
|
{
|
||||||
|
"cnameFrome": "blog.testabc.com",
|
||||||
|
"cnameTo": 'secure2.san1.test_cdn.com',
|
||||||
|
"cnameType": "EDGE_HOSTNAME"
|
||||||
|
}
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
engines.run(update_property_flow.update_property_flow(),
|
||||||
|
store=kwargs)
|
|
@ -180,11 +180,11 @@ 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_get_cert_by_domain.json')
|
@ddt.file_data('data_get_certs_by_domain.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')
|
||||||
def test_get_cert_by_domain(self, cert_details_json,
|
def test_get_certs_by_domain(self, cert_details_json,
|
||||||
mock_session, mock_execute):
|
mock_session, mock_execute):
|
||||||
# mock the response from cassandra
|
# mock the response from cassandra
|
||||||
mock_execute.execute.return_value = cert_details_json[0]
|
mock_execute.execute.return_value = cert_details_json[0]
|
||||||
actual_response = self.sc.get_certs_by_domain(
|
actual_response = self.sc.get_certs_by_domain(
|
||||||
|
|
Loading…
Reference in New Issue