Skip to content
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ matches some expectation:
Kubernetes resource returned in a `kubectl get` response.
* `assert`: (optional) object containing assertions to make about the
action performed by the test.
* `assert.require`: (optional) a boolean indicating whether a failed assertion
will cause the test scenario's execution to stop. The default behaviour of
`gdt` is to continue execution of subsequent test specs in a test scenario when
an assertion fails.
* `assert.error`: (optional) string to match a returned error from the
Kubernetes API server.
* `assert.len`: (optional) int with the expected number of items returned.
Expand Down
3 changes: 3 additions & 0 deletions assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (

// Expect contains one or more assertions about a kube client call
type Expect struct {
// Require indicates that any failed assertion should stop the execution of
// the test scenario in which the test spec is contained.
Require bool `yaml:"require,omitempty"`
// Error is a string that is expected to be returned as an error string
// from the client call
// TODO(jaypipes): Make this polymorphic to be either a shortcut string
Expand Down
9 changes: 8 additions & 1 deletion eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,14 @@ func (s *Spec) Eval(ctx context.Context) (*api.Result, error) {
}
return res, nil
}
return api.NewResult(api.WithFailures(a.Failures()...)), nil
stopOnFail := false
if s.Assert != nil {
stopOnFail = s.Assert.Require
}
return api.NewResult(
api.WithStopOnFail(stopOnFail),
api.WithFailures(a.Failures()...),
), nil
}

// cleanupAutoNamespace returns a cleanup function that deletes the
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.24.3

require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/gdt-dev/core v1.10.0
github.com/gdt-dev/core v1.10.3
github.com/samber/lo v1.51.0
github.com/stretchr/testify v1.11.1
github.com/theory/jsonpath v0.10.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gdt-dev/core v1.10.0 h1:yX0MG2Tt+O34JGDFWcS63LV47lWpizto4HAyR/ugAC0=
github.com/gdt-dev/core v1.10.0/go.mod h1:Bw8J6kUW0b7MUL8qW5e7qSbxb4SI9EAWQ0a4cAoPVpo=
github.com/gdt-dev/core v1.10.3 h1:4cl8h8/SeL5oBzDFyg7WhZbRcLRBb6SUY57L5Swju2A=
github.com/gdt-dev/core v1.10.3/go.mod h1:Bw8J6kUW0b7MUL8qW5e7qSbxb4SI9EAWQ0a4cAoPVpo=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
Expand Down
21 changes: 21 additions & 0 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package kube
import (
"fmt"
"os"
"strconv"
"strings"

"github.com/gdt-dev/core/api"
Expand Down Expand Up @@ -252,6 +253,16 @@ func (s *Spec) UnmarshalYAML(node *yaml.Node) error {
return err
}
s.Assert = e
case "require":
if valNode.Kind != yaml.MappingNode {
return parse.ExpectedMapAt(valNode)
}
var e *Expect
if err := valNode.Decode(&e); err != nil {
return err
}
e.Require = true
s.Assert = e
case "kube.get", "kube.create", "kube.delete", "kube.apply":
continue
default:
Expand Down Expand Up @@ -394,6 +405,16 @@ func (e *Expect) UnmarshalYAML(node *yaml.Node) error {
key := keyNode.Value
valNode := node.Content[i+1]
switch key {
case "require", "stop-on-fail", "stop_on_fail", "stop.on.fail",
"fail-stop", "fail.stop", "fail_stop":
if valNode.Kind != yaml.ScalarNode {
return parse.ExpectedScalarAt(valNode)
}
req, err := strconv.ParseBool(valNode.Value)
if err != nil {
return parse.ExpectedBoolAt(valNode)
}
e.Require = req
case "error":
if valNode.Kind != yaml.ScalarNode {
return parse.ExpectedScalarAt(valNode)
Expand Down
4 changes: 4 additions & 0 deletions spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ type Spec struct {
// having such a label.
// * the string `--all` to delete all resources of that kind.
KubeDelete string `yaml:"kube.delete,omitempty"`
// Require is an object containing the conditions that the Spec will
// assert. If any condition fails, the test scenario execution will stop
// and be marked as failed.
Require *Expect `yaml:"require,omitempty"`
// Assert houses the various assertions to be made about the kube client
// call (Create, Apply, Get, etc)
// TODO(jaypipes): Make this polymorphic to be either a single assertion
Expand Down
Loading