From b6d1ef71ae579ca9c0ee4b422373b715b57831c0 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Mon, 9 Oct 2023 22:54:16 +0530 Subject: [PATCH] warnings Signed-off-by: Shubham Gupta --- config/crd/bases/kuttl.dev_teststeps.yaml | 19 +++++++++++++++++++ pkg/apis/testharness/v1beta1/commands.go | 6 +++--- pkg/apis/testharness/v1beta1/test_types.go | 11 +++++++---- .../v1beta1/zz_generated.deepcopy.go | 13 ++++++++++++- pkg/test/step.go | 18 ++++++++++++++++-- 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/config/crd/bases/kuttl.dev_teststeps.yaml b/config/crd/bases/kuttl.dev_teststeps.yaml index 6c181411..d5458013 100644 --- a/config/crd/bases/kuttl.dev_teststeps.yaml +++ b/config/crd/bases/kuttl.dev_teststeps.yaml @@ -37,6 +37,25 @@ spec: type: string shouldFail: type: boolean + warnings: + items: + description: ExpectedOutput defines the criteria that command + output should meet. + properties: + expected: + description: Value is the expected value or pattern that should + be matched against the command's output. + type: string + match: + description: MatchType is the type of match that should be + applied for validation. This could be "Equals", "Contains", + or "Wildcard". + type: string + required: + - expected + - match + type: object + type: array type: object type: array assert: diff --git a/pkg/apis/testharness/v1beta1/commands.go b/pkg/apis/testharness/v1beta1/commands.go index 2cb52be4..17fbc8f0 100644 --- a/pkg/apis/testharness/v1beta1/commands.go +++ b/pkg/apis/testharness/v1beta1/commands.go @@ -11,12 +11,12 @@ func (c *CommandOutput) ValidateCommandOutput(stdoutOutput, stderrOutput strings var errs []string if c.Stdout != nil { - if err := c.Stdout.validateOutput("stdout", stdoutOutput.String()); err != nil { + if err := c.Stdout.ValidateOutput("stdout", stdoutOutput.String()); err != nil { errs = append(errs, err.Error()) } } if c.Stderr != nil { - if err := c.Stderr.validateOutput("stderr", stderrOutput.String()); err != nil { + if err := c.Stderr.ValidateOutput("stderr", stderrOutput.String()); err != nil { errs = append(errs, err.Error()) } } @@ -26,7 +26,7 @@ func (c *CommandOutput) ValidateCommandOutput(stdoutOutput, stderrOutput strings return nil } -func (e *ExpectedOutput) validateOutput(outputType string, actualValue string) error { +func (e *ExpectedOutput) ValidateOutput(outputType string, actualValue string) error { expectedValue := e.ExpectedValue matchType := e.MatchType if matchType == "" { diff --git a/pkg/apis/testharness/v1beta1/test_types.go b/pkg/apis/testharness/v1beta1/test_types.go index 96d25112..e3469035 100644 --- a/pkg/apis/testharness/v1beta1/test_types.go +++ b/pkg/apis/testharness/v1beta1/test_types.go @@ -102,8 +102,9 @@ type TestSuite struct { // Apply holds infos for an apply statement type Apply struct { - File string `json:"file,omitempty"` - ShouldFail bool `json:"shouldFail,omitempty"` + File string `json:"file,omitempty"` + ShouldFail bool `json:"shouldFail,omitempty"` + Warnings *[]ExpectedOutput `json:"warnings,omitempty"` } // UnmarshalJSON implements the json.Unmarshaller interface. @@ -113,14 +114,16 @@ func (apply *Apply) UnmarshalJSON(value []byte) error { return json.Unmarshal(value, &apply.File) } data := struct { - File string `json:"file,omitempty"` - ShouldFail bool `json:"shouldFail,omitempty"` + File string `json:"file,omitempty"` + ShouldFail bool `json:"shouldFail,omitempty"` + Warnings *[]ExpectedOutput `json:"warnings,omitempty"` }{} if err := json.Unmarshal(value, &data); err != nil { return err } apply.File = data.File apply.ShouldFail = data.ShouldFail + apply.Warnings = data.Warnings return nil } diff --git a/pkg/apis/testharness/v1beta1/zz_generated.deepcopy.go b/pkg/apis/testharness/v1beta1/zz_generated.deepcopy.go index 2b6738e0..d052e66a 100644 --- a/pkg/apis/testharness/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/testharness/v1beta1/zz_generated.deepcopy.go @@ -27,6 +27,15 @@ import ( // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Apply) DeepCopyInto(out *Apply) { *out = *in + if in.Warnings != nil { + in, out := &in.Warnings, &out.Warnings + *out = new([]ExpectedOutput) + if **in != nil { + in, out := *in, *out + *out = make([]ExpectedOutput, len(*in)) + copy(*out, *in) + } + } return } @@ -284,7 +293,9 @@ func (in *TestStep) DeepCopyInto(out *TestStep) { if in.Apply != nil { in, out := &in.Apply, &out.Apply *out = make([]Apply, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.Assert != nil { in, out := &in.Assert, &out.Assert diff --git a/pkg/test/step.go b/pkg/test/step.go index c0fee5fe..2f02ad86 100644 --- a/pkg/test/step.go +++ b/pkg/test/step.go @@ -34,6 +34,7 @@ var fileNameRegex = regexp.MustCompile(`^(?:\d+-)?([^-\.]+)(-[^\.]+)?(?:\.yaml)? type apply struct { object client.Object shouldFail bool + warnings *[]harness.ExpectedOutput } type asserts struct { @@ -250,7 +251,7 @@ func (s *Step) Create(test *testing.T, namespace string) []error { for _, apply := range s.Apply { err := doApply(test, s.SkipDelete, s.Logger, s.Timeout, dClient, cl, apply.object, namespace) - if err != nil && !apply.shouldFail { + if err != nil && !apply.shouldFail && !expectedWarnings(err.Error(), apply.warnings) { errs = append(errs, err) } // if there was no error but we expected one @@ -263,6 +264,19 @@ func (s *Step) Create(test *testing.T, namespace string) []error { return errs } +func expectedWarnings(actualWarning string, warnings *[]harness.ExpectedOutput) bool { + if warnings == nil { + return false + } + + for _, warning := range *warnings { + if err := warning.ValidateOutput("", actualWarning); err != nil { + return false + } + } + return true +} + // GetTimeout gets the timeout defined for the test step. func (s *Step) GetTimeout() int { timeout := s.Timeout @@ -649,7 +663,7 @@ func (s *Step) LoadYAML(file string) error { return fmt.Errorf("step %q apply path %s: %w", s.Name, exApply, err) } for _, a := range aa { - applies = append(applies, apply{object: a, shouldFail: applyPath.ShouldFail}) + applies = append(applies, apply{object: a, shouldFail: applyPath.ShouldFail, warnings: applyPath.Warnings}) } } // process configured step asserts