func()

in pkg/broker/api.go [459:555]


func (b *AwsBroker) Unbind(request *osb.UnbindRequest, c *broker.RequestContext) (*broker.UnbindResponse, error) {
	glog.V(10).Infof("request=%+v", *request)

	// Get the binding
	binding, err := b.db.DataStorePort.GetServiceBinding(request.BindingID)
	if err != nil {
		desc := fmt.Sprintf("Failed to get the service binding %s: %v", request.BindingID, err)
		return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
	} else if binding == nil {
		desc := fmt.Sprintf("The service binding %s was not found.", request.BindingID)
		return nil, newHTTPStatusCodeError(http.StatusGone, "", desc)
	}

	service, err := b.db.DataStorePort.GetServiceDefinition(request.ServiceID)
	if err != nil {
		desc := fmt.Sprintf("Failed to get the service %s: %v", request.ServiceID, err)
		return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
	} else if service == nil {
		desc := fmt.Sprintf("The service %s was not found.", request.ServiceID)
		return nil, newHTTPStatusCodeError(http.StatusBadRequest, "", desc)
	}

	// Get the instance
	instance, err := b.db.DataStorePort.GetServiceInstance(binding.InstanceID)
	if err != nil {
		desc := fmt.Sprintf("Failed to get the service instance %s: %v", binding.InstanceID, err)
		return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
	} else if instance == nil {
		desc := fmt.Sprintf("The service instance %s was not found.", binding.InstanceID)
		return nil, newHTTPStatusCodeError(http.StatusBadRequest, "", desc)
	}

	sess := b.GetSession(b.keyid, b.secretkey, b.region, b.accountId, b.profile, instance.Params)

	if bindViaLambda(service) {

		// Get the CFN stack outputs
		resp, err := b.Clients.NewCfn(sess).Client.DescribeStacks(&cloudformation.DescribeStacksInput{
			StackName: aws.String(instance.StackID),
		})
		if err != nil {
			desc := fmt.Sprintf("Failed to describe the CloudFormation stack %s: %v", instance.StackID, err)
			return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
		}

		// Get the credentials from the CFN stack outputs
		credentials, err := getCredentials(service, resp.Stacks[0].Outputs, b.Clients.NewSsm(sess))
		if err != nil {
			desc := fmt.Sprintf("Failed to get the credentials from CloudFormation stack %s: %v", instance.StackID, err)
			return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
		}

		// Copy in the instance and binding IDs because we can
		// use this as a stable reference to uniquely identify
		// dynamically created resources (for exmaple, you can
		// use these in the Path prefix of an IAM User).
		credentials["INSTANCE_ID"] = binding.InstanceID
		credentials["BINDING_ID"] = binding.ID
		_, err = invokeLambdaBindFunc(sess, b.Clients.NewLambda, credentials, "unbind")
		if err != nil {
			desc := fmt.Sprintf("Error running lambda function for unbind from: %vo", err)
			return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
		}
	}

	if binding.PolicyArn != "" {
		// Detach the scoped policy from the role
		_, err = b.Clients.NewIam(sess).DetachRolePolicy(&iam.DetachRolePolicyInput{
			PolicyArn: aws.String(binding.PolicyArn),
			RoleName:  aws.String(binding.RoleName),
		})
		if err != nil {
			if aerr, ok := err.(awserr.Error); ok && aerr.Code() == iam.ErrCodeNoSuchEntityException {
				glog.Infof("The policy %s was already detached from role %s.", binding.PolicyArn, binding.RoleName)
			} else {
				desc := fmt.Sprintf("Failed to detach the policy %s from role %s: %v", binding.PolicyArn, binding.RoleName, err)
				return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
			}
		}
	}

	// Delete the binding
	err = b.db.DataStorePort.DeleteServiceBinding(binding.ID)
	if err != nil {
		desc := fmt.Sprintf("Failed to delete the service binding %s: %v", binding.ID, err)
		return nil, newHTTPStatusCodeError(http.StatusInternalServerError, "", desc)
	}

	b.metrics.Actions.With(
		prom.Labels{
			"action":  "unbind",
			"service": service.Name,
			"plan":    "",
		}).Inc()

	return &broker.UnbindResponse{}, nil
}