Beispiel #1
0
    def test_returns_202_if_update_is_in_progress(self):
        self.broker.update.return_value = UpdateServiceSpec(True, "operation")

        response = self.client.patch(
            "/v2/service_instances/abc?accepts_incomplete=true",
            data=json.dumps({
                "service_id": "service-guid-here",
                "plan_id": "plan-guid-here",
                "previous_values": {
                    "plan_id": "old-plan-guid-here",
                    "service_id": "service-guid-here",
                    "organization_id": "org-guid-here",
                    "space_id": "space-guid-here"
                }
            }),
            headers={
                'X-Broker-Api-Version': '2.13',
                'Content-Type': 'application/json',
                'Authorization': self.auth_header
            })

        self.assertEqual(response.status_code, http.HTTPStatus.ACCEPTED)
        self.assertEqual(response.json, dict(
            operation="operation"
        ))
Beispiel #2
0
    def test_routes_update(self):
        operation_str = str(uuid4())
        self.b1.update.return_value = UpdateServiceSpec(is_async=True, operation=operation_str)

        update = self.router.update(str(uuid4()), UpdateDetails('s1', 'p1'), True)

        self.assertEqual('s1 ' + operation_str, update.operation)
        self.assertTrue(self.b1.update.called)
Beispiel #3
0
    def test_update_can_change_dashboard_url(self):
        new_dashboard_url = 'https://new.dashboard/'
        self.broker.update.return_value = UpdateServiceSpec(
            is_async=False, operation=None, dashboard_url=new_dashboard_url)

        response = self.client.patch(
            "/v2/service_instances/here-service-instance-id",
            data=json.dumps({
                "service_id": "service-guid-here",
            }),
            headers={
                'X-Broker-Api-Version': '2.13',
                'Content-Type': 'application/json',
                'Authorization': self.auth_header
            })

        self.assertEqual(dict(dashboard_url=new_dashboard_url), response.json)
Beispiel #4
0
    def test_update_ignores_unknown_parameters(self):
        self.broker.update.return_value = UpdateServiceSpec(False, "operation")

        self.client.patch(
            "/v2/service_instances/here-service-instance-id?accepts_incomplete=true",
            data=json.dumps({
                "service_id": "service-guid-here",
                "plan_id": "plan-guid-here",
                "unknown": "unknown",
                "parameters": {
                    "parameter1": 1
                },
                "previous_values": {
                    "unknown": "unknown",
                    "plan_id": "old-plan-guid-here",
                    "service_id": "service-guid-here",
                    "organization_id": "org-guid-here",
                    "space_id": "space-guid-here"
                }
            }),
            headers={
                'X-Broker-Api-Version': '2.13',
                'Content-Type': 'application/json',
                'Authorization': self.auth_header
            })

        actual_service_id, actual_details, actual_async = self.broker.update.call_args[
            0]
        self.assertEqual(actual_service_id, "here-service-instance-id")
        self.assertEqual(actual_async, True)

        self.assertIsInstance(actual_details, UpdateDetails)
        self.assertIsInstance(actual_details.previous_values, PreviousValues)
        self.assertEqual(actual_details.service_id, "service-guid-here")
        self.assertEqual(actual_details.plan_id, "plan-guid-here")
        self.assertEqual(actual_details.parameters, dict(parameter1=1))
        self.assertEqual(actual_details.previous_values.plan_id,
                         "old-plan-guid-here")
        self.assertEqual(actual_details.previous_values.service_id,
                         "service-guid-here")
        self.assertEqual(actual_details.previous_values.organization_id,
                         "org-guid-here")
        self.assertEqual(actual_details.previous_values.space_id,
                         "space-guid-here")
Beispiel #5
0
    def test_returns_200_if_updated(self):
        self.broker.update.return_value = UpdateServiceSpec(False, "operation")

        response = self.client.patch(
            "/v2/service_instances/abc",
            data=json.dumps({
                "service_id": "service-guid-here",
                "plan_id": "plan-guid-here",
                "previous_values": {
                    "plan_id": "old-plan-guid-here",
                    "service_id": "service-guid-here",
                    "organization_id": "org-guid-here",
                    "space_id": "space-guid-here"
                }
            }),
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.assertEqual(response.status_code, http.HTTPStatus.OK)
        self.assertEqual(response.json, dict())
Beispiel #6
0
    def test_update_called_called_just_with_required_fields(self):
        self.broker.update.return_value = UpdateServiceSpec(False, "operation")

        _ = self.client.patch(
            "/v2/service_instances/here-service-instance-id",
            data=json.dumps({
                "service_id": "service-guid-here",
            }),
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        actual_instance_id, actual_details, actual_async = self.broker.update.call_args[0]
        self.assertEqual(actual_instance_id, "here-service-instance-id")
        self.assertEqual(actual_async, False)

        self.assertIsInstance(actual_details, UpdateDetails)
        self.assertEqual(actual_details.service_id, "service-guid-here")

        self.assertIsNone(actual_details.plan_id)
        self.assertIsNone(actual_details.parameters)
        self.assertIsNone(actual_details.previous_values)
Beispiel #7
0
    def update(self, instance_id: str, details: UpdateDetails,
               async_allowed: bool, **kwargs) -> UpdateServiceSpec:
        if not async_allowed:
            raise errors.ErrAsyncRequired()

        params = details.parameters or {}

        instance = ServiceInstance.query.get(instance_id)

        if not instance:
            raise errors.ErrBadRequest("Service instance does not exist")

        if instance.deactivated_at:
            raise errors.ErrBadRequest(
                "Cannot update instance because it was already canceled")

        if instance.has_active_operations():
            raise errors.ErrBadRequest(
                "Instance has an active operation in progress")

        domain_names = parse_domain_options(params)
        noop = True
        if domain_names is not None:
            self.logger.info("validating CNAMEs")
            validators.CNAME(domain_names).validate()

            self.logger.info("validating unique domains")
            validators.UniqueDomains(domain_names).validate(instance)
            noop = noop and (sorted(domain_names) == sorted(
                instance.domain_names))
            if instance.instance_type == "cdn_service_instance" and noop:
                instance.new_certificate = instance.current_certificate
            instance.domain_names = domain_names

        if instance.instance_type == "cdn_service_instance":
            # N.B. we're using "param" in params rather than
            # params.get("param") because the OSBAPI spec
            # requires we do not mess with params that were not
            # specified, so unset and set to None have different meanings
            noop = False

            if details.plan_id != CDN_PLAN_ID:
                raise ClientError("Updating service plan is not supported")

            if "origin" in params:
                if params["origin"]:
                    origin_hostname = params["origin"]
                    validators.Hostname(origin_hostname).validate()
                else:
                    origin_hostname = config.DEFAULT_CLOUDFRONT_ORIGIN
                instance.cloudfront_origin_hostname = origin_hostname

            if "path" in params:
                if params["path"]:
                    cloudfront_origin_path = params["path"]
                else:
                    cloudfront_origin_path = ""
                instance.cloudfront_origin_path = cloudfront_origin_path
            if "forward_cookies" in params:
                forward_cookie_policy, forwarded_cookies = parse_cookie_options(
                    params)
                instance.forward_cookie_policy = forward_cookie_policy
                instance.forwarded_cookies = forwarded_cookies

            if "forward_headers" in params:
                forwarded_headers = parse_header_options(params)
            else:
                # .copy() so sqlalchemy recognizes the field has changed
                forwarded_headers = instance.forwarded_headers.copy()
            if instance.cloudfront_origin_hostname == config.DEFAULT_CLOUDFRONT_ORIGIN:
                forwarded_headers.append("HOST")
            forwarded_headers = normalize_header_list(forwarded_headers)
            instance.forwarded_headers = forwarded_headers
            if "insecure_origin" in params:
                origin_protocol_policy = "https-only"
                if params["insecure_origin"]:
                    if (instance.cloudfront_origin_hostname ==
                            config.DEFAULT_CLOUDFRONT_ORIGIN):
                        raise errors.ErrBadRequest(
                            "Cannot use insecure_origin with default origin")
                    origin_protocol_policy = "http-only"
                instance.origin_protocol_policy = origin_protocol_policy
            if "error_responses" in params:
                instance.error_responses = params["error_responses"]
                validators.ErrorResponseConfig(
                    instance.error_responses).validate()

            queue = queue_all_cdn_update_tasks_for_operation
        elif instance.instance_type == "alb_service_instance":
            if details.plan_id != ALB_PLAN_ID:
                raise ClientError("Updating service plan is not supported")
            queue = queue_all_alb_update_tasks_for_operation
        elif instance.instance_type == "migration_service_instance":
            if details.plan_id == CDN_PLAN_ID:
                noop = False
                validate_migration_to_cdn_params(params)
                instance = change_instance_type(instance, CDNServiceInstance,
                                                db.session)
                update_cdn_params_for_migration(instance, params)
                db.session.add(instance.current_certificate)
                queue = queue_all_cdn_broker_migration_tasks_for_operation
            elif details.plan_id == ALB_PLAN_ID:
                noop = False
                validate_migration_to_alb_params(params)
                instance = change_instance_type(instance, ALBServiceInstance,
                                                db.session)
                update_alb_params_for_migration(instance, params)
                db.session.add(instance.current_certificate)
                queue = queue_all_domain_broker_migration_tasks_for_operation
            else:
                raise ClientError(
                    "Updating to this service plan is not supported")
        if noop:
            return UpdateServiceSpec(False)

        operation = Operation(
            state=Operation.States.IN_PROGRESS.value,
            service_instance=instance,
            action=Operation.Actions.UPDATE.value,
            step_description="Queuing tasks",
        )
        db.session.add(operation)
        db.session.add(instance)
        db.session.commit()

        queue(operation.id, cf_logging.FRAMEWORK.context.get_correlation_id())

        return UpdateServiceSpec(True, operation=str(operation.id))