Skip to content

Commit

Permalink
Merge branch 'kisamoto-62_add-service-plan-context'
Browse files Browse the repository at this point in the history
[#164389015]

Co-authored-by: Derik Evangelista <[email protected]>
  • Loading branch information
FelisiaM and Derik Evangelista committed Mar 14, 2019
2 parents b371e40 + eff7b25 commit 4c4fa5e
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 2 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ use the `NewFailureResponseBuilder()` to add a custom `Error:` value in the
response, or indicate that the broker should return an empty response rather
than the error message.

## Request Context

When provisioning a service `brokerapi` validates the `service_id` and `plan_id`
in the request, attaching the found instances to the request Context. These
values can be retrieved in a `brokerapi.ServiceBroker` implementation using
utility methods `RetrieveServiceFromContext` and `RetrieveServicePlanFromContext`
as shown below.

```golang
func (sb *ServiceBrokerImplementation) Provision(ctx context.Context,
instanceID string, details brokerapi.ProvisionDetails, asyncAllowed bool) {

service := brokerapi.RetrieveServiceFromContext(ctx)
if service == nil {
// Lookup service
}

// [..]
}
```

## Originating Identity

The request context for every request contains the unparsed
Expand Down
7 changes: 5 additions & 2 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/pivotal-cf/brokerapi/middlewares/originating_identity_header"
"net/http"
"strconv"

"github.com/pivotal-cf/brokerapi/middlewares/originating_identity_header"

"code.cloudfoundry.org/lager"
"github.com/gorilla/mux"
"github.com/pivotal-cf/brokerapi/auth"
Expand Down Expand Up @@ -183,6 +184,7 @@ func (h serviceBrokerHandler) provision(w http.ResponseWriter, req *http.Request
services, _ := h.serviceBroker.Services(req.Context())
for _, service := range services {
if service.ID == details.ServiceID {
req = req.WithContext(AddServiceToContext(req.Context(), &service))
valid = true
break
}
Expand All @@ -199,6 +201,7 @@ func (h serviceBrokerHandler) provision(w http.ResponseWriter, req *http.Request
for _, service := range services {
for _, plan := range service.Plans {
if plan.ID == details.PlanID {
req = req.WithContext(AddServicePlanToContext(req.Context(), &plan))
valid = true
break
}
Expand Down Expand Up @@ -797,4 +800,4 @@ func checkBrokerAPIVersionHdr(req *http.Request) (brokerVersion, error) {
return version, errors.New("X-Broker-API-Version Header must be 2.x")
}
return version, nil
}
}
38 changes: 38 additions & 0 deletions context_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package brokerapi

import "context"

type contextKey string

const (
contextKeyService contextKey = "brokerapi_service"
contextKeyPlan contextKey = "brokerapi_plan"
)

func AddServiceToContext(ctx context.Context, service *Service) context.Context {
if service != nil {
return context.WithValue(ctx, contextKeyService, service)
}
return ctx
}

func RetrieveServiceFromContext(ctx context.Context) *Service {
if value := ctx.Value(contextKeyService); value != nil {
return value.(*Service)
}
return nil
}

func AddServicePlanToContext(ctx context.Context, plan *ServicePlan) context.Context {
if plan != nil {
return context.WithValue(ctx, contextKeyPlan, plan)
}
return ctx
}

func RetrieveServicePlanFromContext(ctx context.Context) *ServicePlan {
if value := ctx.Value(contextKeyPlan); value != nil {
return value.(*ServicePlan)
}
return nil
}
77 changes: 77 additions & 0 deletions context_utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package brokerapi_test

import (
"context"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/pivotal-cf/brokerapi"
)

var _ = Describe("Context Utilities", func() {

type testContextKey string

var (
ctx context.Context
contextValidatorKey testContextKey
contextValidatorValue string
)

BeforeEach(func() {
contextValidatorKey = "context-utilities-test"
contextValidatorValue = "original"
ctx = context.Background()
ctx = context.WithValue(ctx, contextValidatorKey, contextValidatorValue)
})

Describe("Service Context", func() {
Context("when the service is nil", func() {
It("returns the original context", func() {
ctx = brokerapi.AddServiceToContext(ctx, nil)
Expect(ctx.Err()).To(BeZero())
Expect(brokerapi.RetrieveServiceFromContext(ctx)).To(BeZero())
Expect(ctx.Value(contextValidatorKey).(string)).To(Equal(contextValidatorValue))
})
})

Context("when the service is valid", func() {
It("sets and receives the service in the context", func() {
service := &brokerapi.Service{
ID: "9A3095D7-ED3C-45FA-BC9F-592820628723",
Name: "Test Service",
}
ctx = brokerapi.AddServiceToContext(ctx, service)
Expect(ctx.Err()).To(BeZero())
Expect(ctx.Value(contextValidatorKey).(string)).To(Equal(contextValidatorValue))
Expect(brokerapi.RetrieveServiceFromContext(ctx).ID).To(Equal(service.ID))
Expect(brokerapi.RetrieveServiceFromContext(ctx).Name).To(Equal(service.Name))
Expect(brokerapi.RetrieveServiceFromContext(ctx).Metadata).To(BeZero())
})
})
})

Describe("Plan Context", func() {
Context("when the service plan is nil", func() {
It("returns the original context", func() {
ctx = brokerapi.AddServicePlanToContext(ctx, nil)
Expect(ctx.Err()).To(BeZero())
Expect(brokerapi.RetrieveServicePlanFromContext(ctx)).To(BeZero())
Expect(ctx.Value(contextValidatorKey).(string)).To(Equal(contextValidatorValue))
})
})

Context("when the service plan is valid", func() {
It("sets and retrieves the service plan in the context", func() {
plan := &brokerapi.ServicePlan{
ID: "AC257573-8C62-4B1A-AC34-ECA3863F50EC",
}
ctx = brokerapi.AddServicePlanToContext(ctx, plan)
Expect(ctx.Err()).To(BeZero())
Expect(ctx.Value(contextValidatorKey).(string)).To(Equal(contextValidatorValue))
Expect(brokerapi.RetrieveServicePlanFromContext(ctx).ID).To(Equal(plan.ID))
})
})
})
})

0 comments on commit 4c4fa5e

Please sign in to comment.