diff --git a/cmd/argo/commands/lint_test.go b/cmd/argo/commands/lint_test.go index ac2858e220b1..6c2226fc554d 100644 --- a/cmd/argo/commands/lint_test.go +++ b/cmd/argo/commands/lint_test.go @@ -172,4 +172,45 @@ spec: assert.False(t, fatal, "should not have exited") }) + + workflowCaseSensitivePath := filepath.Join(subdir, "workflowCaseSensitive.yaml") + err = os.WriteFile(workflowCaseSensitivePath, []byte(` +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: hello-world- +spec: + entrypoInt: whalesay + templates: + - name: whalesay + container: + image: docker/whalesay + command: [ cowsay ] + args: [ "hello world" ] + resources: + limits: + memory: 32Mi + cpu: 100m +`), 0644) + require.NoError(t, err) + + t.Run("linting a workflow with case sensitive fields and strict enabled", func(t *testing.T) { + defer func() { logrus.StandardLogger().ExitFunc = nil }() + var fatal bool + logrus.StandardLogger().ExitFunc = func(int) { fatal = true } + + runLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", true) + + assert.True(t, fatal, "should have exited") + }) + + t.Run("linting a workflow with case sensitive fields and strict disabled", func(t *testing.T) { + defer func() { logrus.StandardLogger().ExitFunc = nil }() + var fatal bool + logrus.StandardLogger().ExitFunc = func(int) { fatal = true } + + runLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", false) + + assert.False(t, fatal, "should not have exited") + }) } diff --git a/go.mod b/go.mod index 4c7f99556590..0a2b87d7aeb1 100644 --- a/go.mod +++ b/go.mod @@ -294,7 +294,7 @@ require ( k8s.io/component-helpers v0.26.15 // indirect k8s.io/metrics v0.26.15 // indirect moul.io/http2curl/v2 v2.3.0 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kustomize/v4 v4.5.7 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect diff --git a/test/e2e/cli_test.go b/test/e2e/cli_test.go index c1a1bfd926b7..9451cbee8181 100644 --- a/test/e2e/cli_test.go +++ b/test/e2e/cli_test.go @@ -1111,7 +1111,7 @@ func (s *CLISuite) TestTemplateCommands() { s.Given().RunCli([]string{"template", "lint", "testdata/workflow-templates"}, func(t *testing.T, output string, err error) { assert.Error(t, err) assert.Contains(t, output, "invalid-workflowtemplate.yaml") - assert.Contains(t, output, `unknown field "entrypoints"`) + assert.Contains(t, output, `unknown field "spec.entrypoints"`) assert.Contains(t, output, "linting errors found!") }) }) diff --git a/workflow/common/parse.go b/workflow/common/parse.go index 29d5de552e95..efe907584dc7 100644 --- a/workflow/common/parse.go +++ b/workflow/common/parse.go @@ -8,6 +8,8 @@ import ( log "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + kjson "sigs.k8s.io/json" "sigs.k8s.io/yaml" wf "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow" @@ -96,7 +98,19 @@ func toWorkflowTypeYAML(body []byte, kind string, strict bool) (metav1.Object, e func toWorkflowTypeJSON(body []byte, kind string, strict bool) (metav1.Object, error) { v := objectForKind(kind) if strict { - return v, jsonpkg.UnmarshalStrict(body, v) + var strictErrs []error + strictJSONErrs, err := kjson.UnmarshalStrict(body, v) + if err != nil { + // fatal decoding error, not due to strictness + return v, err + } + strictErrs = append(strictErrs, strictJSONErrs...) + + if len(strictErrs) > 0 { + // return the successfully decoded object along with the strict errors + return v, runtime.NewStrictDecodingError(strictErrs) + } + return v, err } return v, jsonpkg.Unmarshal(body, v)