Example #1
0
 def last_binding_operation(self, instance_id: str, binding_id: str,
                            operation_data: Optional[str],
                            **kwargs) -> LastOperation:
     instance = self.service_instances.get(instance_id, {})
     if instance.get('state') == self.BINDING:
         instance['state'] = self.BOUND
         return LastOperation(OperationState.SUCCEEDED)
     elif instance.get('state') == self.UNBINDING:
         instance['state'] = self.CREATED
         return LastOperation(OperationState.SUCCEEDED)
Example #2
0
    def last_operation(self, instance_id: str, operation_data: Optional[str],
                       **kwargs) -> LastOperation:
        """
        Further readings `CF Broker API#LastOperation
        <https://docs.cloudfoundry.org/services/api.html#polling>`_

        :param instance_id: Instance id provided by the platform
        :param operation_data: Operation data received from async operation
        :param kwargs: May contain additional information, improves
                       compatibility with upstream versions
        :rtype: LastOperation
        """

        instance = ServiceInstance.query.get(instance_id)

        if not instance:
            raise errors.ErrInstanceDoesNotExist

        if not operation_data:
            raise errors.ErrBadRequest(msg="Missing operation ID")

        operation = instance.operations.filter_by(
            id=int(operation_data)).first()

        if not operation:
            raise errors.ErrBadRequest(
                msg=
                f"Invalid operation id {operation_data} for service {instance_id}"
            )

        return LastOperation(
            state=Operation.States(operation.state),
            description=operation.step_description,
        )
    def catalog(self) -> Service:
      # We should add the ability to inject the service plans
      # this is where cluster admins can create the various t-shirt
      # sizes to support for MongoDB
      
      print("loaded service providers\n".join("{}\t{}".format(k, v) for k, v in self.service_providers.items()))
      plans = []
      tags = ['MongoDB', 'Database' ]
      for provider_name in self.service_providers.keys():
        print("loading plans for provider: %s" % provider_name)
        provider = self.service_providers[provider_name]
        provider_plans = provider.plans()
        for plan in provider_plans:
          self.service_plans[plan.id]= { 'provider_name' : provider_name, 'plans' : provider_plans }
        plans.extend( provider_plans )
        tags.extend( provider.tags() )
            
      # Omitting this, needs nested v2.DashboardClient type
      #     dashboard_client='http://mongodb-open-service-broker:8080',

      catalog = Service(
            id='mongodb-open-service-broker',
            name='mongodb-open-service-broker-service',
            description='This service creates and provides your applications access to MongoDB services.',
            bindable=True,
            plans=plans,
            tags=list(set(tags)),
            plan_updateable=False,
      )
      self.__last_op = LastOperation("catalog", catalog )
      self.__catalog = catalog
      return catalog
Example #4
0
    def test_routes_last_operation(self):
        instance_id = str(uuid4())
        operation_str = str(uuid4())
        self.b1.last_operation.return_value = LastOperation(state=OperationState.IN_PROGRESS)

        _ = self.router.last_operation(instance_id, 's1 ' + operation_str)

        self.b1.last_operation.assert_called_with(instance_id, operation_str)
 def last_operation(self, instance_id: str, operation_data: str) -> LastOperation:
     logger.info("last_opertation") 
     if not instance_id in self.provisioned_services:
       raise errors.ErrInstanceDoesNotExist()
     spec = self.provisioned_services[instance_id]["spec"]
     op = self.provisioned_services[instance_id]["last_op"]
     lo = LastOperation(op, spec)
     return lo
    def test_last_operation_called_just_with_required_fields(self):
        self.broker.last_binding_operation.return_value = LastOperation(OperationState.IN_PROGRESS, 'Running...')

        self.client.get(
            '/v2/service_instances/here-instance_id/service_bindings/binding_id/last_operation',
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.broker.last_binding_operation.assert_called_once_with('here-instance_id', 'binding_id', None)
    def provision(self, instance_id: str, service_details: ProvisionDetails,
                  async_allowed: bool) -> ProvisionedServiceSpec:
        logger.info("provision") 
        provider_name = self.service_plans[service_details.plan_id]['provider_name']
        provider = self.service_providers[provider_name]
        logger.info("provider_name=%s, provider=%s" % ( provider_name, provider) )
        self.provisioned_services[instance_id]={ "provider" : provider,
"plan_id" : service_details.plan_id, "spec" : None, "last_op" : LastOperation("provision","Started") } 
        logger.info("request to provision plan_id=%s" % service_details.plan_id)
        spec = provider.provision(instance_id, service_details, async_allowed)
        self.provisioned_services[instance_id]={ "provider" : provider, "plan_id" : service_details.plan_id, "spec" : spec, "last_op" : LastOperation("provision",spec) }
        return spec
Example #8
0
    def last_operation(self, instance_id: str, operation_data: Optional[str],
                       **kwargs) -> LastOperation:
        instance = self.service_instances.get(instance_id)
        if instance is None:
            raise errors.ErrInstanceDoesNotExist()

        if instance.get('state') == self.CREATING:
            instance['state'] = self.CREATED
            return LastOperation(OperationState.SUCCEEDED)
        elif instance.get('state') == self.DELETING:
            del self.service_instances[instance_id]
            raise errors.ErrInstanceDoesNotExist()
    def test_returns_400_on_invalid_request(self):
        self.broker.last_operation.return_value = LastOperation(
            OperationState.IN_PROGRESS, "Running...")

        query = "service_id=123&plan_id=456&operation=somethingwrong"
        response = self.client.get(
            "/v2/service_instances/here-instance_id/last_operation?%s" % query,
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.assertEqual(response.status_code, http.HTTPStatus.BAD_REQUEST)
    def test_last_operation_called_with_operation_data(self):
        self.broker.last_binding_operation.return_value = LastOperation(OperationState.IN_PROGRESS, 'Running...')

        query = 'service_id=&plan_id=456&operation=service-guid-here%20operation-data'
        self.client.get(
            '/v2/service_instances/here-instance_id/service_bindings/binding_id/last_operation?%s' % query,
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.broker.last_binding_operation.assert_called_once_with('here-instance_id', 'binding_id',
                                                                   'service-guid-here operation-data')
    def test_last_operation_called_with_the_right_values(self):
        self.broker.last_operation.return_value = LastOperation(
            OperationState.IN_PROGRESS, "Running...")

        query = "service_id=&plan_id=456&operation=service-guid-here%20operation-data"
        self.client.get(
            "/v2/service_instances/here-instance_id/last_operation?%s" % query,
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.broker.last_operation.assert_called_once_with(
            "here-instance_id", "service-guid-here operation-data")
    def test_last_operation_called_just_with_required_fields(self):
        self.broker.last_operation.return_value = LastOperation(
            OperationState.IN_PROGRESS, "Running...")

        query = "operation=service-guid-here"
        self.client.get(
            "/v2/service_instances/here-instance_id/last_operation?%s" % query,
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.broker.last_operation.assert_called_once_with(
            "here-instance_id", None)
    def test_returns_200_with_given_state(self):
        self.broker.last_binding_operation.return_value = LastOperation(OperationState.IN_PROGRESS, 'Running...')

        query = 'service_id=123&plan_id=456&operation=service-guid-here%20operation-data'
        response = self.client.get(
            '/v2/service_instances/here-instance_id/service_bindings/binding_id/last_operation?%s' % query,
            headers={
                'X-Broker-Api-Version': '2.13',
                'Authorization': self.auth_header
            })

        self.assertEqual(response.status_code, http.HTTPStatus.OK)
        self.assertEqual(response.json, dict(
            state=OperationState.IN_PROGRESS.value,
            description='Running...'
        ))
    def catalog(self) -> Service:

        self.logger.debug("loaded service providers\n".join(
            "{}\t{}".format(k, v) for k, v in self.service_providers.items()))
        plans = []
        tags = ['MongoDB', 'Database']
        for provider_name in self.service_providers.keys():
            self.logger.debug("loading plans for provider: %s" % provider_name)
            provider = self.service_providers[provider_name]
            self.logger.debug(f'{provider}')
            provider_plans = provider.plans()
            for plan in provider_plans:
                self.logger.debug(f'plan={plan}')
                self.service_plans[plan.id] = {
                    'provider_name': provider_name,
                    'plans': provider_plans
                }
            plans.extend(provider_plans)
            tags.extend(provider.tags())

        # Omitting this, needs nested v2.DashboardClient type
        #     dashboard_client='http://mongodb-open-service-broker:8080',

        catalog = Service(
            id='mongodb-open-service-broker',
            name='mongodb-open-service-broker-service',
            description=
            'The MongoDB Enterprise Open Service Broker. https://mongodb.com/osb',
            bindable=True,
            plans=plans,
            tags=list(set(tags)),
            plan_updateable=False,
        )
        self.__last_op = LastOperation("catalog", catalog)
        self.__catalog = catalog
        return catalog