def service_bind(instance_id, binding_id, binding):
    """
    Binds to a service
    When the broker receives a bind request from the client, it should return information which helps an application
    to utilize the provisioned resource. This information is generically referred to as credentials. Applications
    should be issued unique credentials whenever possible, so one application access can be revoked without affecting
    other bound applications.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param binding_id: The binding_id of a service binding is provided by the Cloud Controller.
    :type binding_id: str
    :param binding: 
    :type binding: dict | bytes

    :rtype: BindingResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            binding = BindingRequest.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400
        return 'Not implemented. Pending selection and integration of an ET identity service', 501
Exemple #2
0
def store_manifest(manifest_id, manifest):
    """
    takes deployment description of a software service and associates with a service and plan
    takes deployment description of a software service and associates with a service and plan that is already
    registered in the service catalog.
    :param manifest_id: The manifest_id of a manifest to be associated with a plan of a servicetype.
    :type manifest_id: str
    :param manifest: the manifest to store
    :type manifest: dict | bytes

    :rtype: ServiceResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            manifest = Manifest.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400
        if manifest.manifest_content.find(
                '</br>') > 0:  # TODO(dizz) remove this check in R4
            return "Manifest content contains '</br>'. Please remove these and replace with '\n'", 400
        manifest.id = manifest_id

        result, code = STORE.add_manifest(manifest)

        if code == 200:
            return Empty(), code
        else:
            return result, code
def update_service_instance(instance_id, plan, accept_incomplete=None):
    """
    Updating a Service Instance
    Brokers that implement this endpoint can enable users to modify attributes of an existing service instance.
    The first attribute supports users modifying is the service plan. This effectively enables users to upgrade
    or downgrade their service instance to other plans. To see how users make these requests.&#39;
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param plan: New Plan information.
    :type plan: dict | bytes
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: Empty
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            plan = UpdateRequest.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400
        return 'Not implemented :-(', 501
def last_operation_status(instance_id, service_id=None, plan_id=None, operation=None):
    """
    Gets the current state of the last operation upon the specified resource.
    When a broker returns status code 202 ACCEPTED for provision, update, or deprovision, the client will
    begin to poll the /v2/service_instances/:guid/last_operation endpoint to obtain the state of the last requested
    operation. The broker response must contain the field state and an optional field description.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used for
    future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param service_id: ID of the service from the catalog.
    :type service_id: str
    :param plan_id: ID of the plan from the catalog.
    :type plan_id: str
    :param operation: A broker-provided identifier for the operation. When a value for operation is included
    with asynchronous responses for Provision, Update, and Deprovision requests, the broker client should provide
    the same value using this query parameter as a URL-encoded string.;
    :type operation: str

    :rtype: LastOperation
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        # just re-use the method and return it's content and http status code.
        # version check not required here as it's done in the proxied call
        srv_inst, code = instance_info(instance_id=instance_id)
        if code == 404:
            return srv_inst + 'No service status therefore.', code
        else:
            return srv_inst.state, code
def instance_info(instance_id):
    """
    Returns information about the service instance.
    Returns information about the service instance. This is a simple read operation against the broker database and
    is provided as a developer/consumer convienence.
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str

    :rtype: ServiceInstance
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        entity = {
            'entity_id': instance_id,
            'entity_req': {},
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM}

        entity, context = RetrieveInstance(entity, context).start()
        # what's returned should be type ServiceInstance
        return entity['entity_res'], context['status'][1]
def all_instance_info():
    """
    Returns information about the service instance.
    Returns all service instances that are accessible to the end-user on this service manager.

    :rtype: List[ServiceInstance]
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        entity = {'entity_id': None, 'entity_req': {}, 'entity_res': None}
        context = {'STORE': STORE, 'RM': RM}
        entity, context = RetrieveAllInstances(entity, context).start()
        return entity['entity_res'], context['status'][1]
def all_instance_info():
    """
    Returns information about the service instance.
    Returns all service instances that are accessible to the end-user on this service manager.

    :rtype: List[ServiceInstance]
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        instances = STORE.get_service_instance()
        insts = list()
        for inst in instances:
            insts.append(_get_instance(inst))

        return insts, 200
Exemple #8
0
def catalog():
    """
    Gets services registered within the broker
    \&quot;The first endpoint that a broker must implement is the service catalog. The client will initially fetch
    this endpoint from all brokers and make adjustments to the user-facing service catalog stored in the a
    client database. \\n\&quot;

    :rtype: Catalog
    """
    # get all services from the service collection

    ok, message, code = _version_ok()

    if not ok:
        return message, code
    else:
        services = STORE.get_service()
        return Catalog(services=services), 200
def create_service_instance(instance_id, service, accept_incomplete=False):
    """
    Provisions a service instance
    When the broker receives a provision request from a client, it should synchronously take whatever action is
    necessary to create a new service resource for the developer. The result of provisioning varies by service
    type, although there are a few common actions that work for many services. Supports asynchronous operations.&#39;
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used for
    future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str
    :param service: Service information.
    :type service: dict | bytes
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: ServiceResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            service_inst_req = ServiceRequest.from_dict(
                connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400

        entity = {
            'entity_id': instance_id,
            'entity_req': service_inst_req,
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM}

        if accept_incomplete:
            AsychExe([CreateInstance(entity, context)]).start()
            return 'accepted', 201
        else:
            # we have the result of the operation in entity, good/bad status in context
            entity, context = CreateInstance(entity, context).start()
            if config.esm_measure_insts == 'YES':
                # entity, context = #
                MeasureInstance(entity, context).start()
            # Response is ServiceResponse not a service instance
            return entity['entity_res'], context['status'][1]
def deprovision_service_instance(instance_id,
                                 service_id,
                                 plan_id,
                                 accept_incomplete=False):
    """
    Deprovisions a service instance.
    &#39;When a broker receives a deprovision request from a client, it should delete any resources it
    created during the provision. Usually this means that all resources are immediately reclaimed for
    future provisions.&#39;
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str
    :param service_id: service ID to be deprovisioned
    :type service_id: str
    :param plan_id: plan ID of the service to be deprovisioned
    :type plan_id: str
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: UpdateOperationResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        entity = {
            'entity_id': instance_id,
            'entity_req': {
                'service_id': service_id,
                'plan_id': plan_id
            },
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM}

        # XXX if there's bindings remove first?
        if accept_incomplete:
            AsychExe([DeleteInstance(entity, context)]).start()
            return 'accepted', 201
        else:
            entity, context = DeleteInstance(entity, context).start()
            # response is UpdateOperationResponse
            return entity['entity_res'], context['status'][1]
def update_service_instance(instance_id, plan, accept_incomplete=False):
    """
    Updating a Service Instance
    Brokers that implement this endpoint can enable users to modify attributes of an existing service instance.
    The first attribute supports users modifying is the service plan. This effectively enables users to upgrade
    or downgrade their service instance to other plans. To see how users make these requests.&#39;
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param plan: New Plan information.
    :type plan: dict | bytes
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: Empty
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            plan = UpdateRequest.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400

        entity = {
            'entity_id': instance_id,
            'entity_req': {
                'plan': plan
            },
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM}

        if accept_incomplete:
            AsychExe([UpdateInstance(entity, context)]).start()
            return 'accepted', 201
        else:
            # we have the result of the operation in entity, good/bad status in context
            entity, context = UpdateInstance(entity, context).start()
            # response should be Empty
            return entity['entity_res'], context['status'][1]
def last_operation_status(instance_id,
                          service_id=None,
                          plan_id=None,
                          operation=None):
    """
    Gets the current state of the last operation upon the specified resource.
    When a broker returns status code 202 ACCEPTED for provision, update, or deprovision, the client will
    begin to poll the /v2/service_instances/:guid/last_operation endpoint to obtain the state of the last requested
    operation. The broker response must contain the field state and an optional field description.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used for
    future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param service_id: ID of the service from the catalog.
    :type service_id: str
    :param plan_id: ID of the plan from the catalog.
    :type plan_id: str
    :param operation: A broker-provided identifier for the operation. When a value for operation is included
    with asynchronous responses for Provision, Update, and Deprovision requests, the broker client should provide
    the same value using this query parameter as a URL-encoded string.;
    :type operation: str

    :rtype: LastOperation
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        entity = {
            'entity_id': instance_id,
            'entity_req': {
                'service_id': service_id,
                'plan_id': plan_id,
                'operation': operation
            },
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM}

        entity, context = RetrieveInstanceLastOp(entity, context).start()
        # response should be LastOperation
        return entity['entity_res'], context['status'][1]
Exemple #13
0
def register_service(service):
    """
    Registers the service with the catalog.
    \&quot;Service providers need a means to register their service with a service broker. This provides this
    functionality. Also using PUT a service provider can update their registration. Note that this requires the
    complete content and will REPLACE the existing service information registered with the broker.\&quot;
    :param service: the service description to register
    :type service: dict | bytes

    :rtype: Empty
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if connexion.request.is_json:
            service = ServiceType.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400
        STORE.add_service(service=service)
        return Empty()
def deprovision_service_instance(instance_id, service_id, plan_id, accept_incomplete=None):
    """
    Deprovisions a service instance.
    &#39;When a broker receives a deprovision request from a client, it should delete any resources it
    created during the provision. Usually this means that all resources are immediately reclaimed for
    future provisions.&#39;
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str
    :param service_id: service ID to be deprovisioned
    :type service_id: str
    :param plan_id: plan ID of the service to be deprovisioned
    :type plan_id: str
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: UpdateOperationResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        # XXX if there's bindings remove first?
        # XXX what about undo?
        # check that the instance exists first
        instance = STORE.get_service_instance(instance_id=instance_id)
        if len(instance) == 1:
            mani_id = instance[0].context['manifest_id']
            mani = STORE.get_manifest(manifest_id=mani_id)
            if len(mani) < 1:
                return 'no service manifest found.', 404

            RM.delete(instance_id=instance_id, manifest_type=mani[0].manifest_type)
            STORE.delete_service_instance(instance_id)
            # we don't delete the last_operation explicitly as its embedded in the service_instance document
            # STORE.delete_last_operation(instance_id)

            return Empty(), 200
        else:
            return Empty(), 404
def service_unbind(instance_id, binding_id, service_id, plan_id):
    """
    Unbinds a service
    When a broker receives an unbind request from the client, it should delete any resources it created in bind.
    Usually this means that an application immediately cannot access the resource.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param binding_id: The binding_id of a service binding is provided by the Cloud Controller.
    :type binding_id: str
    :param service_id: ID of the service from the catalog.
    :type service_id: str
    :param plan_id: ID of the plan from the catalog.
    :type plan_id: str

    :rtype: Empty
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        return 'Not implemented. Pending selection and integration of an ET identity service', 501
def service_unbind(instance_id, binding_id, service_id, plan_id):
    """
    Unbinds a service
    When a broker receives an unbind request from the client, it should delete any resources it created in bind.
    Usually this means that an application immediately cannot access the resource.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param binding_id: The binding_id of a service binding is provided by the Cloud Controller.
    :type binding_id: str
    :param service_id: ID of the service from the catalog.
    :type service_id: str
    :param plan_id: ID of the plan from the catalog.
    :type plan_id: str

    :rtype: Empty
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        # if AAA is enabled and the service is bindable:
        #    create project, user and role bindings
        entity = {
            'entity_id': instance_id,
            'entity_req': {
                'binding_id': binding_id,
                'service_id': service_id,
                'plan_id': plan_id
            },
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM, 'AUTH': AUTH}

        entity, context = UnbindInstance(entity, context).start()
        # response should be Empty
        return entity['entity_res'], context['status'][1]
def service_bind(instance_id, binding_id, binding):
    """
    Binds to a service
    When the broker receives a bind request from the client, it should return information which helps an application
    to utilize the provisioned resource. This information is generically referred to as credentials. Applications
    should be issued unique credentials whenever possible, so one application access can be revoked without affecting
    other bound applications.
    :param instance_id: The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.
    :type instance_id: str
    :param binding_id: The binding_id of a service binding is provided by the Cloud Controller.
    :type binding_id: str
    :param binding: 
    :type binding: dict | bytes

    :rtype: BindingResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        # if AAA is enabled and the service is bindable:
        #    create project, user and role bindings
        entity = {
            'entity_id': instance_id,
            'entity_req': {
                'binding_id': binding_id,
                'binding': binding
            },
            'entity_res': None
        }
        context = {'STORE': STORE, 'RM': RM, 'AUTH': AUTH}

        entity, context = BindInstance(entity, context).start()
        # response should be a BindingResponse
        return entity['entity_res'], context['status'][1]
def instance_info(instance_id):
    """
    Returns information about the service instance.
    Returns information about the service instance. This is a simple read operation against the broker database and
    is provided as a developer/consumer convienence.
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used
    for future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str

    :rtype: ServiceInstance
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        # service instance should already be recorded
        srv_inst = STORE.get_service_instance(instance_id)
        if len(srv_inst) < 1:
            return 'no service instance found.', 404
        srv_inst = srv_inst[0]

        srv_inst = _get_instance(srv_inst)

        return srv_inst, 200
def create_service_instance(instance_id, service, accept_incomplete=None):
    """
    Provisions a service instance
    When the broker receives a provision request from a client, it should synchronously take whatever action is
    necessary to create a new service resource for the developer. The result of provisioning varies by service
    type, although there are a few common actions that work for many services. Supports asynchronous operations.&#39;
    :param instance_id: &#39;The instance_id of a service instance is provided by the client. This ID will be used for
    future requests (bind and deprovision), so the broker must use it to correlate the resource it creates.&#39;
    :type instance_id: str
    :param service: Service information.
    :type service: dict | bytes
    :param accept_incomplete: Indicates that the client is supporting asynchronous operations
    :type accept_incomplete: bool

    :rtype: ServiceResponse
    """
    ok, message, code = _version_ok()
    if not ok:
        return message, code
    else:
        if len(STORE.get_service_instance(instance_id=instance_id)) == 1:
            return 'Service instance with id {id} already exists'.format(id=instance_id), 409

        if connexion.request.is_json:
            service = ServiceRequest.from_dict(connexion.request.get_json())
        else:
            return "Supplied body content is not or is mal-formed JSON", 400

        # look up manifest based on plan id
        # based on the manifest type, select the driver
        # send the manifest for creation to the target system
        # store the ID along with refs to service, plan and manifest

        # get the manifest for the service/plan
        svc_type = STORE.get_service(service.service_id)[0]
        if svc_type is None:
            return 'Unrecognised service requested to be instantiated', 404

        plans = svc_type.plans
        plan = [p for p in plans if p.id == service.plan_id]
        if len(plan) <= 0:
            return 'Plan {p_id} found.'.format(p_id=service.plan_id), 404

        mani = STORE.get_manifest(plan_id=plan[0].id)
        if len(mani) <= 0:
            return 'no manifest for service {plan} found.'.format(plan=service.plan_id), 404
        mani = mani[0]

        if accept_incomplete:  # given docker-compose runs in detached mode this is not needed - only timing can verify
            # XXX put this in a thread to allow for asynch processing?
            RM.create(instance_id=instance_id, content=mani.manifest_content,
                      c_type=mani.manifest_type, parameters=service.parameters)
        else:
            RM.create(instance_id=instance_id, content=mani.manifest_content,
                      c_type=mani.manifest_type, parameters=service.parameters)

        last_op = LastOperation(  # stored within the service instance doc
            state='creating',
            description='service instance is being created'
        )

        # store the instance Id with manifest id
        srv_inst = ServiceInstance(
            service_type=svc_type,
            state=last_op,
            context={
                'id': instance_id,
                'manifest_id': mani.id,
            }
        )

        STORE.add_service_instance(srv_inst)

        if accept_incomplete:
            STORE.add_last_operation(instance_id=instance_id, last_operation=last_op)

        return 'created', 200