Skip to content

Commit

Permalink
Use pointers for relationships
Browse files Browse the repository at this point in the history
E.g. AppCreate payload has relationships.space.data.guid. If we use
pointers all the way down, we get the correct error message if the json
only contains some of the path. So providing `relationships.space` would
error with `data` being required.

Issue: #1996
Co-authored-by: Kieron Browne <[email protected]>
  • Loading branch information
danail-branekov and Kieron Browne committed Jun 27, 2023
1 parent 17c5b66 commit ffcd6af
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 37 deletions.
4 changes: 2 additions & 2 deletions api/handlers/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ var _ = Describe("App", func() {
BeforeEach(func() {
payload = &payloads.AppCreate{
Name: appName,
Relationships: payloads.AppRelationships{
Space: payloads.Relationship{
Relationships: &payloads.AppRelationships{
Space: &payloads.Relationship{
Data: &payloads.RelationshipData{
GUID: spaceGUID,
},
Expand Down
8 changes: 4 additions & 4 deletions api/payloads/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,27 @@ var DefaultLifecycleConfig = config.DefaultLifecycleConfig{
type AppCreate struct {
Name string `json:"name"`
EnvironmentVariables map[string]string `json:"environment_variables"`
Relationships AppRelationships `json:"relationships"`
Relationships *AppRelationships `json:"relationships"`
Lifecycle *Lifecycle `json:"lifecycle"`
Metadata Metadata `json:"metadata"`
}

func (c AppCreate) Validate() error {
return validation.ValidateStruct(&c,
validation.Field(&c.Name, payload_validation.StrictlyRequired),
validation.Field(&c.Relationships, payload_validation.StrictlyRequired),
validation.Field(&c.Relationships, validation.NotNil),
validation.Field(&c.Lifecycle),
validation.Field(&c.Metadata),
)
}

type AppRelationships struct {
Space Relationship `json:"space"`
Space *Relationship `json:"space"`
}

func (r AppRelationships) Validate() error {
return validation.ValidateStruct(&r,
validation.Field(&r.Space, payload_validation.StrictlyRequired),
validation.Field(&r.Space, validation.NotNil),
)
}

Expand Down
18 changes: 14 additions & 4 deletions api/payloads/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ var _ = Describe("App payload validation", func() {
BeforeEach(func() {
payload = payloads.AppCreate{
Name: "my-app",
Relationships: payloads.AppRelationships{
Space: payloads.Relationship{
Relationships: &payloads.AppRelationships{
Space: &payloads.Relationship{
Data: &payloads.RelationshipData{
GUID: "app-guid",
},
Expand Down Expand Up @@ -83,11 +83,21 @@ var _ = Describe("App payload validation", func() {

When("relationships are not set", func() {
BeforeEach(func() {
payload.Relationships = payloads.AppRelationships{}
payload.Relationships = nil
})

It("returns an unprocessable entity error", func() {
expectUnprocessableEntityError(validatorErr, "relationships cannot be blank")
expectUnprocessableEntityError(validatorErr, "relationships is required")
})
})

When("relationships space is not set", func() {
BeforeEach(func() {
payload.Relationships.Space = nil
})

It("returns an unprocessable entity error", func() {
expectUnprocessableEntityError(validatorErr, "relationships.space is required")
})
})

Expand Down
6 changes: 3 additions & 3 deletions api/payloads/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ type DropletGUID struct {
}

type DeploymentCreate struct {
Droplet DropletGUID `json:"droplet"`
Relationships DeploymentRelationships `json:"relationships" validate:"required"`
Droplet DropletGUID `json:"droplet"`
Relationships *DeploymentRelationships `json:"relationships" validate:"required"`
}

type DeploymentRelationships struct {
App Relationship `json:"app" validate:"required"`
App *Relationship `json:"app" validate:"required"`
}

func (c *DeploymentCreate) ToMessage() repositories.CreateDeploymentMessage {
Expand Down
22 changes: 16 additions & 6 deletions api/payloads/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ var _ = Describe("DeploymentCreate", func() {
Droplet: payloads.DropletGUID{
Guid: "the-droplet",
},
Relationships: payloads.DeploymentRelationships{
App: payloads.Relationship{
Relationships: &payloads.DeploymentRelationships{
App: &payloads.Relationship{
Data: &payloads.RelationshipData{
GUID: "the-app",
},
Expand Down Expand Up @@ -57,13 +57,23 @@ var _ = Describe("DeploymentCreate", func() {
})
})

When("the app relationship is not specified", func() {
When("the relationship is not specified", func() {
BeforeEach(func() {
createDeployment.Relationships = payloads.DeploymentRelationships{}
createDeployment.Relationships = nil
})

It("says app data is required", func() {
expectUnprocessableEntityError(validatorErr, "Data is a required field")
It("says relationships is required", func() {
expectUnprocessableEntityError(validatorErr, "Relationships is a required field")
})
})

When("the relationship app is not specified", func() {
BeforeEach(func() {
createDeployment.Relationships.App = nil
})

It("says app is required", func() {
expectUnprocessableEntityError(validatorErr, "App is a required field")
})
})

Expand Down
16 changes: 7 additions & 9 deletions api/payloads/lifecycle.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
package payloads

import (
payload_validation "code.cloudfoundry.org/korifi/api/payloads/validation"
"github.com/jellydator/validation"
)

type Lifecycle struct {
Type string `json:"type" validate:"required"`
Data LifecycleData `json:"data" validate:"required"`
Type string `json:"type"`
Data *LifecycleData `json:"data"`
}

func (l Lifecycle) Validate() error {
return validation.ValidateStruct(&l,
validation.Field(&l.Type, payload_validation.StrictlyRequired),
validation.Field(&l.Data, payload_validation.StrictlyRequired),
validation.Field(&l.Type, validation.Required),
validation.Field(&l.Data, validation.NotNil),
)
}

type LifecycleData struct {
Buildpacks []string `json:"buildpacks" validate:"required"`
Stack string `json:"stack" validate:"required"`
Buildpacks []string `json:"buildpacks"`
Stack string `json:"stack"`
}

func (d LifecycleData) Validate() error {
return validation.ValidateStruct(&d,
validation.Field(&d.Buildpacks, payload_validation.StrictlyRequired),
validation.Field(&d.Stack, payload_validation.StrictlyRequired),
validation.Field(&d.Stack, validation.Required),
)
}
14 changes: 7 additions & 7 deletions api/payloads/lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var _ = Describe("Lifecycle", func() {

payload = payloads.Lifecycle{
Type: "buildpack",
Data: payloads.LifecycleData{
Data: &payloads.LifecycleData{
Buildpacks: []string{"foo", "bar"},
Stack: "baz",
},
Expand Down Expand Up @@ -50,23 +50,23 @@ var _ = Describe("Lifecycle", func() {
})
})

When("stack is not set", func() {
When("lifecycle data is not set", func() {
BeforeEach(func() {
payload.Data.Stack = ""
payload.Data = nil
})

It("returns an appropriate error", func() {
expectUnprocessableEntityError(validatorErr, "data.stack cannot be blank")
expectUnprocessableEntityError(validatorErr, "data is required")
})
})

When("buildpacks are not set", func() {
When("stack is not set", func() {
BeforeEach(func() {
payload.Data.Buildpacks = nil
payload.Data.Stack = ""
})

It("returns an appropriate error", func() {
expectUnprocessableEntityError(validatorErr, "data.buildpacks cannot be blank")
expectUnprocessableEntityError(validatorErr, "data.stack cannot be blank")
})
})
})
4 changes: 2 additions & 2 deletions api/payloads/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func (p RouteCreate) ToMessage(domainNamespace, domainName string) repositories.
}

type RouteRelationships struct {
Domain Relationship `json:"domain" validate:"required"`
Space Relationship `json:"space" validate:"required"`
Domain Relationship `json:"domain"`
Space Relationship `json:"space"`
}

func (r RouteRelationships) Validate() error {
Expand Down

0 comments on commit ffcd6af

Please sign in to comment.