Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(*): validate parameter default against its definition #254

Merged
merged 4 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ func (b Bundle) Validate() error {

// Validate the parameters
for name, param := range b.Parameters {
err := param.Validate()
err := param.Validate(name, b)
if err != nil {
return pkgErrors.Wrapf(err, "validation failed for parameter %q", name)
}
Expand Down
3 changes: 3 additions & 0 deletions bundle/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ func TestValidateParameters(t *testing.T) {
Version: "0.1.0",
SchemaVersion: "99.98",
InvocationImages: []InvocationImage{img},
Definitions: definition.Definitions{
"param": &definition.Schema{},
},
}

t.Run("bad parameter fails", func(t *testing.T) {
Expand Down
29 changes: 27 additions & 2 deletions bundle/parameters.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package bundle

import "errors"
import (
"fmt"

"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
)

// Parameter defines a single parameter for a CNAB bundle
type Parameter struct {
Expand All @@ -23,10 +28,30 @@ func (p *Parameter) AppliesTo(action string) bool {
}

// Validate a Parameter
func (p *Parameter) Validate() error {
func (p *Parameter) Validate(name string, bun Bundle) error {
if p.Definition == "" {
return errors.New("parameter definition must be provided")
}

// Validate default against definition schema, if exists
schema, ok := bun.Definitions[p.Definition]
if !ok {
return fmt.Errorf("unable to find definition for %s", name)
}
if schema.Default != nil {
var valResult *multierror.Error
valErrs, err := schema.Validate(schema.Default)
if err != nil {
valResult = multierror.Append(valResult, errors.Wrapf(err, "encountered an error validating parameter %s", name))
vdice marked this conversation as resolved.
Show resolved Hide resolved
}
for _, valErr := range valErrs {
valResult = multierror.Append(valResult, fmt.Errorf("encountered an error validating the default value %v for parameter %q: %v", schema.Default, name, valErr.Error))
}
if valResult.ErrorOrNil() != nil {
return valResult
}
}

if p.Destination == nil {
return errors.New("parameter destination must be provided")
}
Expand Down
29 changes: 24 additions & 5 deletions bundle/parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/cnabio/cnab-go/bundle/definition"
)

func TestCanReadParameterNames(t *testing.T) {
Expand Down Expand Up @@ -87,23 +89,40 @@ func TestCanReadParameterDefinition(t *testing.T) {
}

func TestParameterValidate(t *testing.T) {
b := Bundle{
Definitions: map[string]*definition.Schema{
"param-definition": {
Type: "string",
},
},
}
p := Parameter{}

t.Run("empty parameter fails", func(t *testing.T) {
err := p.Validate()
err := p.Validate("param", b)
assert.EqualError(t, err, "parameter definition must be provided")
})

t.Run("empty path fails", func(t *testing.T) {
p.Definition = "paramDef"
err := p.Validate()
p.Definition = "param-definition"
err := p.Validate("param", b)
assert.EqualError(t, err, "parameter destination must be provided")
})

t.Run("unsuccessful validation", func(t *testing.T) {
p.Definition = "param-definition"
p.Destination = &Location{Path: "/path/to/param"}
b.Definitions["param-definition"].Default = 1
err := p.Validate("param", b)
assert.Error(t, err)
assert.Contains(t, err.Error(), `encountered an error validating the default value 1 for parameter "param": type should be string`)
})

t.Run("successful validation", func(t *testing.T) {
p.Definition = "paramDef"
p.Definition = "param-definition"
p.Destination = &Location{Path: "/path/to/param"}
err := p.Validate()
b.Definitions["param-definition"].Default = "foo"
err := p.Validate("param", b)
assert.NoError(t, err)
})
}