Beispiel #1
0
 def handle_base_exception(e):
     logger.exception(e)
     if config.TESTING:
         response = ErrorResponse(description=str(e))
     else:
         response = ErrorResponse(description="Unhandled error during request")
     return (to_json_response(response), HTTPStatus.INTERNAL_SERVER_ERROR)
Beispiel #2
0
    def update(instance_id):
        try:
            accepts_incomplete = 'true' == request.args.get(
                "accepts_incomplete", 'false')

            update_details = UpdateDetails(**json.loads(request.data))
            update_details.originating_identity = request.originating_identity
            update_details.authorization_username = request.authorization.username
            broker = get_broker_by_id(update_details.service_id)
            if not broker.check_plan_id(update_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError, JSONDecodeError) as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = broker.update(instance_id, update_details,
                                   accepts_incomplete)
            add_service_id_to_async_response(result, broker.service_id())
        except errors.ErrAsyncRequired as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(
                    error="AsyncRequired",
                    description=
                    "This service plan requires client support for asynchronous service operations."
                )), HTTPStatus.UNPROCESSABLE_ENTITY

        if result.is_async:
            return to_json_response(UpdateResponse(
                result.operation)), HTTPStatus.ACCEPTED
        else:
            return to_json_response(EmptyResponse()), HTTPStatus.OK
Beispiel #3
0
    def deprovision(instance_id):
        try:
            plan_id = request.args["plan_id"]
            service_id = request.args["service_id"]
            accepts_incomplete = 'true' == request.args.get("accepts_incomplete", 'false')

            deprovision_details = DeprovisionDetails(service_id=service_id, plan_id=plan_id)
            deprovision_details.originating_identity = request.originating_identity
            deprovision_details.authorization_username = extract_authorization_username(request)
            if not _check_plan_id(service_broker, deprovision_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError) as e:
            logger.exception(e)
            return to_json_response(ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = service_broker.deprovision(instance_id, deprovision_details, accepts_incomplete)
        except errors.ErrInstanceDoesNotExist as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.GONE
        except errors.ErrAsyncRequired as e:
            logger.exception(e)
            return to_json_response(ErrorResponse(
                error="AsyncRequired",
                description="This service plan requires client support for asynchronous service operations."
            )), HTTPStatus.UNPROCESSABLE_ENTITY

        if result.is_async:
            return to_json_response(DeprovisionResponse(result.operation)), HTTPStatus.ACCEPTED
        else:
            return to_json_response(EmptyResponse()), HTTPStatus.OK
Beispiel #4
0
    def update(instance_id):
        try:
            accepts_incomplete = 'true' == request.args.get("accepts_incomplete", 'false')

            update_details = UpdateDetails(**json.loads(request.data))
            update_details.originating_identity = request.originating_identity
            update_details.authorization_username = extract_authorization_username(request)
            plan_id = update_details.plan_id
            if plan_id and not _check_plan_id(service_broker, plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError, JSONDecodeError) as e:
            logger.exception(e)
            return to_json_response(ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = service_broker.update(instance_id, update_details, accepts_incomplete)
        except errors.ErrInvalidParameters as e:
            return to_json_response(ErrorResponse('InvalidParameters', str(e))), HTTPStatus.BAD_REQUEST
        except errors.ErrAsyncRequired as e:
            logger.exception(e)
            return to_json_response(ErrorResponse(
                error="AsyncRequired",
                description="This service plan requires client support for asynchronous service operations."
            )), HTTPStatus.UNPROCESSABLE_ENTITY

        if result.is_async:
            return to_json_response(UpdateResponse(result.operation, result.dashboard_url)), HTTPStatus.ACCEPTED
        else:
            return to_json_response(UpdateResponse(None, result.dashboard_url)), HTTPStatus.OK
Beispiel #5
0
def check_version():
    from flask import request
    version = request.headers.get("X-Broker-Api-Version", None)
    if not version:
        return to_json_response(
            ErrorResponse(description="No X-Broker-Api-Version found.")
        ), HTTPStatus.BAD_REQUEST
    if MIN_VERSION > version_tuple(version):
        return to_json_response(
            ErrorResponse(
                description="Service broker requires version %d.%d+." %
                MIN_VERSION)), HTTPStatus.PRECONDITION_FAILED
Beispiel #6
0
    def provision(instance_id):
        try:
            accepts_incomplete = 'true' == request.args.get(
                "accepts_incomplete", 'false')
            if not request.is_json:
                er = ErrorResponse(
                    description=
                    'Improper Content-Type header. Expecting "application/json"'
                )
                return to_json_response(er), HTTPStatus.BAD_REQUEST

            provision_details = ProvisionDetails(**json.loads(request.data))
            provision_details.originating_identity = request.originating_identity
            provision_details.authorization_username = request.authorization.username
            broker = get_broker_by_id(provision_details.service_id)
            if not broker.check_plan_id(provision_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError) as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = broker.provision(instance_id, provision_details,
                                      accepts_incomplete)
            add_service_id_to_async_response(result, broker.service_id())
        except errors.ErrInstanceAlreadyExists as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.CONFLICT
        except errors.ErrAsyncRequired as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(
                    error="AsyncRequired",
                    description=
                    "This service plan requires client support for asynchronous service operations."
                )), HTTPStatus.UNPROCESSABLE_ENTITY

        if result.state == ProvisionState.IS_ASYNC:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.ACCEPTED
        elif result.state == ProvisionState.IDENTICAL_ALREADY_EXISTS:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.OK
        elif result.state == ProvisionState.SUCCESSFUL_CREATED:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.CREATED
        else:
            raise errors.ServiceException(
                'IllegalState, ProvisioningState unknown.')
Beispiel #7
0
    def provision(instance_id):
        try:
            accepts_incomplete = 'true' == request.args.get(
                "accepts_incomplete", 'false')

            provision_details = ProvisionDetails(**json.loads(request.data))
            provision_details.originating_identity = request.originating_identity
            provision_details.authorization_username = extract_authorization_username(
                request)

            if not _check_plan_id(service_broker, provision_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError, JSONDecodeError) as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = service_broker.provision(instance_id, provision_details,
                                              accepts_incomplete)
        except errors.ErrInstanceAlreadyExists as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.CONFLICT
        except errors.ErrInvalidParameters as e:
            return to_json_response(ErrorResponse(
                'InvalidParameters', str(e))), HTTPStatus.BAD_REQUEST
        except errors.ErrAsyncRequired as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(
                    error="AsyncRequired",
                    description=
                    "This service plan requires client support for asynchronous service operations."
                )), HTTPStatus.UNPROCESSABLE_ENTITY

        if result.state == ProvisionState.IS_ASYNC:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.ACCEPTED
        elif result.state == ProvisionState.IDENTICAL_ALREADY_EXISTS:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.OK
        elif result.state == ProvisionState.SUCCESSFUL_CREATED:
            return to_json_response(
                ProvisioningResponse(result.dashboard_url,
                                     result.operation)), HTTPStatus.CREATED
        else:
            raise errors.ServiceException(
                'IllegalState, ProvisioningState unknown.')
Beispiel #8
0
    def unbind(instance_id, binding_id):
        try:
            accepts_incomplete = 'true' == request.args.get("accepts_incomplete", 'false')

            plan_id = request.args["plan_id"]
            service_id = request.args["service_id"]

            unbind_details = UnbindDetails(service_id=service_id, plan_id=plan_id)
            unbind_details.originating_identity = request.originating_identity
            unbind_details.authorization_username = extract_authorization_username(request)
            if not _check_plan_id(service_broker, unbind_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError) as e:
            logger.exception(e)
            return to_json_response(ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = service_broker.unbind(instance_id, binding_id, unbind_details, accepts_incomplete)
        except errors.ErrBindingDoesNotExist as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.GONE

        if result.is_async:
            return to_json_response(UnbindResponse(result.operation)), HTTPStatus.ACCEPTED
        else:
            return to_json_response(EmptyResponse()), HTTPStatus.OK
Beispiel #9
0
 def wrapped(*args, **kwargs):
     from flask import request
     if request.get_json(silent=True) is None:
         er = ErrorResponse(
             description=
             'Improper Content-Type header. Expecting "application/json"')
         return to_json_response(er), HTTPStatus.BAD_REQUEST
     else:
         return f(*args, **kwargs)
Beispiel #10
0
    def bind(instance_id, binding_id):
        try:
            accepts_incomplete = 'true' == request.args.get(
                "accepts_incomplete", 'false')

            binding_details = BindDetails(**json.loads(request.data))
            binding_details.originating_identity = request.originating_identity
            binding_details.authorization_username = extract_authorization_username(
                request)
            if not _check_plan_id(service_broker, binding_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError, JSONDecodeError) as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            result = service_broker.bind(instance_id, binding_id,
                                         binding_details, accepts_incomplete)
        except errors.ErrBindingAlreadyExists as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.CONFLICT
        except errors.ErrAppGuidNotProvided as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(
                    error="RequiresApp",
                    description=
                    "This service supports generation of credentials through binding an application only."
                )), HTTPStatus.UNPROCESSABLE_ENTITY

        response = BindResponse(credentials=result.credentials,
                                syslog_drain_url=result.syslog_drain_url,
                                route_service_url=result.route_service_url,
                                volume_mounts=result.volume_mounts)
        if result.state == BindState.SUCCESSFUL_BOUND:
            return to_json_response(response), HTTPStatus.CREATED
        elif result.state == BindState.IDENTICAL_ALREADY_EXISTS:
            return to_json_response(response), HTTPStatus.OK
        elif result.state == BindState.IS_ASYNC:
            return to_json_response(
                BindResponse(operation=result.operation)), HTTPStatus.ACCEPTED
        else:
            raise errors.ServiceException('IllegalState, BindState unknown.')
Beispiel #11
0
 def requires_auth():
     """Check authentication over all provided usernames else sends a 401 response that enables basic auth"""
     from flask import request
     auth = request.authorization
     if auth:
         for credentials in broker_credentials:
             if auth.username == credentials.username and auth.password == credentials.password:
                 return
     return to_json_response(
         ErrorResponse(
             description=
             'Could not verify your access level for that URL.\nYou have to login with proper credentials'
         )), HTTPStatus.UNAUTHORIZED, {
             'WWW-Authenticate': 'Basic realm="Login Required"'
         }
Beispiel #12
0
    def get_instance(instance_id):
        try:
            result = service_broker.get_instance(instance_id)
            response = GetInstanceResponse(
                service_id=result.service_id,
                plan_id=result.plan_id,
                dashboard_url=result.dashboard_url,
                parameters=result.parameters,
            )
            return to_json_response(response), HTTPStatus.OK

        except errors.ErrInstanceDoesNotExist:
            return to_json_response(EmptyResponse()), HTTPStatus.NOT_FOUND
        except errors.ErrConcurrentInstanceAccess:
            error_response = ErrorResponse(error='ConcurrencyError',
                                           description='The Service Broker does not support concurrent requests that mutate the same resource.')
            return to_json_response(error_response), HTTPStatus.UNPROCESSABLE_ENTITY
Beispiel #13
0
def check_originating_identity():
    """
    Check and decode the "X-Broker-API-Originating-Identity" header
    https://github.com/openservicebrokerapi/servicebroker/blob/v2.13/spec.md#originating-identity
    """
    from flask import request, json
    if "X-Broker-API-Originating-Identity" in request.headers:
        try:
            platform, value = request.headers[
                "X-Broker-API-Originating-Identity"].split(None, 1)
            request.originating_identity = {
                'platform': platform,
                'value': json.loads(base64.standard_b64decode(value))
            }
        except ValueError as e:
            return to_json_response(
                ErrorResponse(
                    description=
                    'Improper "X-Broker-API-Originating-Identity" header. ' +
                    str(e))), HTTPStatus.BAD_REQUEST
    else:
        request.originating_identity = None
Beispiel #14
0
    def unbind(instance_id, binding_id):
        try:
            plan_id = request.args["plan_id"]
            service_id = request.args["service_id"]
            unbind_details = UnbindDetails(plan_id, service_id)
            unbind_details.originating_identity = request.originating_identity
            unbind_details.authorization_username = request.authorization.username
            broker = get_broker_by_id(unbind_details.service_id)
            if not broker.check_plan_id(unbind_details.plan_id):
                raise TypeError('plan_id not found in this service.')
        except (TypeError, KeyError) as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        try:
            broker.unbind(instance_id, binding_id, unbind_details)
        except errors.ErrBindingDoesNotExist as e:
            logger.exception(e)
            return to_json_response(EmptyResponse()), HTTPStatus.GONE

        return to_json_response(EmptyResponse()), HTTPStatus.OK
Beispiel #15
0
    def last_operation(instance_id):
        # Not required
        # service_id = request.args.get("service_id", None)
        # plan_id = request.args.get("plan_id", None)

        operation_data = request.args.get("operation", None)
        data = operation_data.split(' ', maxsplit=1)
        service_id = data[0]
        if len(data) == 2:
            operation_data = data[1]
        else:
            operation_data = None

        try:
            broker = get_broker_by_id(service_id)
        except KeyError as e:
            logger.exception(e)
            return to_json_response(
                ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST

        result = broker.last_operation(instance_id, operation_data)
        return to_json_response(
            LastOperationResponse(result.state,
                                  result.description)), HTTPStatus.OK
Beispiel #16
0
 def handle_not_implemented(e):
     logger.exception(e)
     return (
         to_json_response(ErrorResponse(description="Not Implemented")),
         HTTPStatus.NOT_IMPLEMENTED,
     )
Beispiel #17
0
 def error_handler(e):
     logger.exception(e)
     return to_json_response(ErrorResponse(
         description=str(e))), HTTPStatus.INTERNAL_SERVER_ERROR
Beispiel #18
0
 def error_handler_bad_request(e):
     logger.exception(e)
     return to_json_response(
         ErrorResponse(description=str(e))), HTTPStatus.BAD_REQUEST
Beispiel #19
0
 def error_handler_not_implemented(e):
     logger.exception(e)
     return to_json_response(
         ErrorResponse(description=str(e))), HTTPStatus.NOT_IMPLEMENTED
Beispiel #20
0
 def error_handler(e):
     logger.exception(e)
     return to_json_response(ErrorResponse(
         description=constants.DEFAULT_EXCEPTION_ERROR_MESSAGE
     )), HTTPStatus.INTERNAL_SERVER_ERROR
Beispiel #21
0
 def error_handler_not_implemented(e):
     logger.exception(e)
     return to_json_response(ErrorResponse(
         description=constants.DEFAULT_NOT_IMPLEMENTED_ERROR_MESSAGE
     )), HTTPStatus.NOT_IMPLEMENTED
Beispiel #22
0
 def error_handler_bad_request(e):
     logger.exception(e)
     return to_json_response(ErrorResponse(
         description=constants.DEFAULT_BAD_REQUEST_ERROR_MESSAGE
     )), HTTPStatus.BAD_REQUEST