Skip to content

Commit

Permalink
Use the request validator to decode request in handlers
Browse files Browse the repository at this point in the history
Co-authored-by: Kieron Browne <[email protected]>
  • Loading branch information
danail-branekov and Kieron Browne committed Jun 28, 2023
1 parent a346cc6 commit 21b0875
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 298 deletions.
11 changes: 5 additions & 6 deletions api/handlers/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
. "github.com/onsi/gomega/gstruct"
)

Expand Down Expand Up @@ -182,7 +181,7 @@ var _ = Describe("App", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})

When("creating the process fails", func() {
Expand Down Expand Up @@ -465,7 +464,7 @@ var _ = Describe("App", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})

It("returns the App in the response", func() {
Expand Down Expand Up @@ -588,7 +587,7 @@ var _ = Describe("App", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})

When("setting the current droplet fails", func() {
Expand Down Expand Up @@ -1052,7 +1051,7 @@ var _ = Describe("App", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})
When("the request body is invalid", func() {
BeforeEach(func() {
Expand Down Expand Up @@ -1542,7 +1541,7 @@ var _ = Describe("App", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})

When("the request body is invalid", func() {
Expand Down
74 changes: 27 additions & 47 deletions api/handlers/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strings"

apierrors "code.cloudfoundry.org/korifi/api/errors"
. "code.cloudfoundry.org/korifi/api/handlers"
"code.cloudfoundry.org/korifi/api/handlers"
"code.cloudfoundry.org/korifi/api/handlers/fake"
"code.cloudfoundry.org/korifi/api/payloads"
"code.cloudfoundry.org/korifi/api/repositories"
Expand All @@ -18,7 +18,30 @@ import (
)

var _ = Describe("Build", func() {
var req *http.Request
var (
req *http.Request
requestValidator *fake.RequestValidator
apiHandler *handlers.Build
appRepo *fake.CFAppRepository
buildRepo *fake.CFBuildRepository
packageRepo *fake.CFPackageRepository
)

BeforeEach(func() {
requestValidator = new(fake.RequestValidator)
appRepo = new(fake.CFAppRepository)
buildRepo = new(fake.CFBuildRepository)
packageRepo = new(fake.CFPackageRepository)

apiHandler = handlers.NewBuild(
*serverURL,
buildRepo,
packageRepo,
appRepo,
requestValidator,
)
routerBuilder.LoadRoutes(apiHandler)
})

JustBeforeEach(func() {
routerBuilder.Build().ServeHTTP(rr, req)
Expand All @@ -37,11 +60,7 @@ var _ = Describe("Build", func() {
updatedAt = "1906-04-18T13:12:01Z"
)

var buildRepo *fake.CFBuildRepository

// set up happy path defaults
BeforeEach(func() {
buildRepo = new(fake.CFBuildRepository)
buildRepo.GetBuildReturns(repositories.BuildRecord{
GUID: buildGUID,
State: "STAGING",
Expand All @@ -63,17 +82,6 @@ var _ = Describe("Build", func() {
var err error
req, err = http.NewRequestWithContext(ctx, "GET", "/v3/builds/"+buildGUID, nil)
Expect(err).NotTo(HaveOccurred())

decoderValidator := NewDefaultDecoderValidator()

apiHandler := NewBuild(
*serverURL,
buildRepo,
new(fake.CFPackageRepository),
new(fake.CFAppRepository),
decoderValidator,
)
routerBuilder.LoadRoutes(apiHandler)
})

It("returns the Build", func() {
Expand Down Expand Up @@ -108,13 +116,7 @@ var _ = Describe("Build", func() {
})

Describe("the POST /v3/builds endpoint", func() {
var (
packageRepo *fake.CFPackageRepository
appRepo *fake.CFAppRepository
buildRepo *fake.CFBuildRepository
requestValidator *fake.RequestValidator
expectedLifecycleBuildpacks []string
)
var expectedLifecycleBuildpacks []string

const (
packageGUID = "the-package-guid"
Expand All @@ -132,7 +134,6 @@ var _ = Describe("Build", func() {
)

BeforeEach(func() {
requestValidator = new(fake.RequestValidator)
requestValidator.DecodeAndValidateJSONPayloadStub = decodeAndValidateJSONPayloadStub(&payloads.BuildCreate{
Package: &payloads.RelationshipData{
GUID: packageGUID,
Expand All @@ -141,7 +142,6 @@ var _ = Describe("Build", func() {

expectedLifecycleBuildpacks = []string{"buildpack-a", "buildpack-b"}

packageRepo = new(fake.CFPackageRepository)
packageRepo.GetPackageReturns(repositories.PackageRecord{
Type: "bits",
AppGUID: appGUID,
Expand All @@ -153,7 +153,6 @@ var _ = Describe("Build", func() {
UpdatedAt: updatedAt,
}, nil)

appRepo = new(fake.CFAppRepository)
appRepo.GetAppReturns(repositories.AppRecord{
GUID: appGUID,
SpaceGUID: spaceGUID,
Expand All @@ -166,7 +165,6 @@ var _ = Describe("Build", func() {
},
}, nil)

buildRepo = new(fake.CFBuildRepository)
buildRepo.CreateBuildReturns(repositories.BuildRecord{
GUID: buildGUID,
State: "STAGING",
Expand All @@ -185,15 +183,6 @@ var _ = Describe("Build", func() {
AppGUID: appGUID,
}, nil)

apiHandler := NewBuild(
*serverURL,
buildRepo,
packageRepo,
appRepo,
requestValidator,
)
routerBuilder.LoadRoutes(apiHandler)

var err error
req, err = http.NewRequestWithContext(ctx, "POST", "/v3/builds", strings.NewReader(""))
Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -314,22 +303,13 @@ var _ = Describe("Build", func() {

Describe("the PATCH /v3/builds endpoint", func() {
BeforeEach(func() {
apiHandler := NewBuild(
*serverURL,
new(fake.CFBuildRepository),
new(fake.CFPackageRepository),
new(fake.CFAppRepository),
NewDefaultDecoderValidator(),
)
routerBuilder.LoadRoutes(apiHandler)

var err error
req, err = http.NewRequestWithContext(context.Background(), "PATCH", "/v3/builds/build-guid", strings.NewReader(`{}`))
Expect(err).NotTo(HaveOccurred())
})

It("returns an unprocessable entity error", func() {
expectUnprocessableEntityError(`Labels and annotations are not supported for builds.`)
expectUnprocessableEntityError("Labels and annotations are not supported for builds.")
})
})
})
51 changes: 28 additions & 23 deletions api/handlers/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package handlers_test

import (
"errors"
"fmt"
"net/http"
"strings"
"time"

apierrors "code.cloudfoundry.org/korifi/api/errors"
"code.cloudfoundry.org/korifi/api/handlers"
"code.cloudfoundry.org/korifi/api/handlers/fake"
"code.cloudfoundry.org/korifi/api/payloads"
"code.cloudfoundry.org/korifi/api/repositories"
"code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
. "code.cloudfoundry.org/korifi/tests/matchers"
Expand All @@ -19,20 +19,20 @@ import (

var _ = Describe("Deployment", func() {
var (
req *http.Request
deploymentsRepo *fake.CFDeploymentRepository
runnerInfoRepo *fake.RunnerInfoRepository
runnerName string
requestValidator *fake.RequestValidator
req *http.Request
deploymentsRepo *fake.CFDeploymentRepository
runnerInfoRepo *fake.RunnerInfoRepository
runnerName string
)

BeforeEach(func() {
requestValidator = new(fake.RequestValidator)
deploymentsRepo = new(fake.CFDeploymentRepository)
runnerInfoRepo = new(fake.RunnerInfoRepository)
runnerName = "statefulset-runner"

decoderValidator := handlers.NewDefaultDecoderValidator()

apiHandler := handlers.NewDeployment(*serverURL, decoderValidator, deploymentsRepo, runnerInfoRepo, runnerName)
apiHandler := handlers.NewDeployment(*serverURL, requestValidator, deploymentsRepo, runnerInfoRepo, runnerName)
routerBuilder.LoadRoutes(apiHandler)

runnerInfoRepo.GetRunnerInfoReturns(repositories.RunnerInfoRecord{
Expand Down Expand Up @@ -60,18 +60,19 @@ var _ = Describe("Deployment", func() {
},
}, nil)

req = createHttpRequest("POST", "/v3/deployments", strings.NewReader(fmt.Sprintf(`{
"droplet": {
"guid": "%s"
},
"relationships": {
"app": {
"data": {
"guid": "%s"
}
}
}
}`, dropletGUID, appGUID)))
req = createHttpRequest("POST", "/v3/deployments", strings.NewReader("the-payload"))
requestValidator.DecodeAndValidateJSONPayloadStub = decodeAndValidateJSONPayloadStub(&payloads.DeploymentCreate{
Droplet: payloads.DropletGUID{
Guid: dropletGUID,
},
Relationships: &payloads.DeploymentRelationships{
App: &payloads.Relationship{
Data: &payloads.RelationshipData{
GUID: appGUID,
},
},
},
})
})

When("runner is not capable of rolling deploy", func() {
Expand Down Expand Up @@ -117,6 +118,10 @@ var _ = Describe("Deployment", func() {
})

It("creates the deployment with the repository", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Expect(bodyString(actualReq)).To(Equal("the-payload"))

Expect(deploymentsRepo.CreateDeploymentCallCount()).To(Equal(1))
_, actualAuthInfo, createMessage := deploymentsRepo.CreateDeploymentArgsForCall(0)
Expect(actualAuthInfo).To(Equal(authInfo))
Expand All @@ -128,11 +133,11 @@ var _ = Describe("Deployment", func() {

When("the request payload is invalid", func() {
BeforeEach(func() {
req = createHttpRequest("POST", "/v3/deployments", strings.NewReader("invalid-payload"))
requestValidator.DecodeAndValidateJSONPayloadReturns(errors.New("boom"))
})

It("returns a bad request error", func() {
expectBadRequestError()
It("returns an error", func() {
expectUnknownError()
})
})

Expand Down
13 changes: 6 additions & 7 deletions api/handlers/domain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
)

var _ = Describe("Domain", func() {
Expand Down Expand Up @@ -70,14 +69,14 @@ var _ = Describe("Domain", func() {
}, nil)

var err error
req, err = http.NewRequestWithContext(ctx, "POST", "/v3/domains", strings.NewReader("the-json-payload"))
req, err = http.NewRequestWithContext(ctx, "POST", "/v3/domains", strings.NewReader("the-json-body"))
Expect(err).NotTo(HaveOccurred())
})

It("creates a domain", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
request, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(request.Body)).Should(gbytes.Say("the-json-payload"))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Expect(bodyString(actualReq)).To(Equal("the-json-body"))

Expect(domainRepo.CreateDomainCallCount()).To(Equal(1))
_, actualAuthInfo, createMessage := domainRepo.CreateDomainArgsForCall(0)
Expand Down Expand Up @@ -210,14 +209,14 @@ var _ = Describe("Domain", func() {
}, nil)

var err error
req, err = http.NewRequestWithContext(ctx, "PATCH", "/v3/domains/my-domain", strings.NewReader("the-json-payload"))
req, err = http.NewRequestWithContext(ctx, "PATCH", "/v3/domains/my-domain", strings.NewReader("the-json-body"))
Expect(err).NotTo(HaveOccurred())
})

It("updates the domain", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
request, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(request.Body)).Should(gbytes.Say("the-json-payload"))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Expect(bodyString(actualReq)).To(Equal("the-json-body"))

Expect(domainRepo.UpdateDomainCallCount()).To(Equal(1))
_, _, updateMessage := domainRepo.UpdateDomainArgsForCall(0)
Expand Down
3 changes: 1 addition & 2 deletions api/handlers/droplet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
)

var _ = Describe("Droplet", func() {
Expand Down Expand Up @@ -190,7 +189,7 @@ var _ = Describe("Droplet", func() {
It("validates the payload", func() {
Expect(requestValidator.DecodeAndValidateJSONPayloadCallCount()).To(Equal(1))
actualReq, _ := requestValidator.DecodeAndValidateJSONPayloadArgsForCall(0)
Eventually(gbytes.BufferReader(actualReq.Body)).Should(gbytes.Say("the-json-body"))
Expect(bodyString(actualReq)).To(Equal("the-json-body"))
})

It("updates the droplet", func() {
Expand Down
9 changes: 9 additions & 0 deletions api/handlers/handlers_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers_test
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
Expand Down Expand Up @@ -140,3 +141,11 @@ func decodeAndValidateURLValuesStub[P any, I keyedPayloadImpl[P]](desiredPayload
return nil
}
}

func bodyString(r *http.Request) string {
GinkgoHelper()

bodyBytes, err := io.ReadAll(r.Body)
Expect(err).NotTo(HaveOccurred())
return string(bodyBytes)
}
Loading

0 comments on commit 21b0875

Please sign in to comment.