From 8c344e26bf945afe7afb14a87b7dda857a7b0240 Mon Sep 17 00:00:00 2001 From: Donny Xia Date: Thu, 13 May 2021 12:05:30 -0700 Subject: [PATCH 1/5] add error types for kptfile validation and image --- .../missing-fn-image/.expected/config.yaml | 2 +- .../.expected/config.yaml | 2 +- .../missing-fn-image/.expected/config.yaml | 2 +- internal/errors/resolver/docker.go | 41 +++++++++++++ internal/errors/resolver/pkg.go | 4 +- internal/errors/resolver/validation.go | 41 +++++++++++++ internal/fnruntime/container.go | 24 +++++++- .../util/addmergecomment/addmergecomment.go | 14 +++++ .../addmergecomment/addmergecomment_test.go | 14 +++++ pkg/api/kptfile/v1alpha2/validation.go | 58 ++++++++++++++++--- 10 files changed, 187 insertions(+), 15 deletions(-) create mode 100644 internal/errors/resolver/docker.go create mode 100644 internal/errors/resolver/validation.go diff --git a/e2e/testdata/fn-eval/missing-fn-image/.expected/config.yaml b/e2e/testdata/fn-eval/missing-fn-image/.expected/config.yaml index bde0350440..6093efcd87 100644 --- a/e2e/testdata/fn-eval/missing-fn-image/.expected/config.yaml +++ b/e2e/testdata/fn-eval/missing-fn-image/.expected/config.yaml @@ -17,7 +17,7 @@ exitCode: 1 image: gcr.io/kpt-fn/dne # non-existing image args: namespace: staging -stdErr: "error: function image \"gcr.io/kpt-fn/dne\" doesn't exist" +stdErr: 'Function image "gcr.io/kpt-fn/dne" doesn''t exist' stdOut: | [RUNNING] "gcr.io/kpt-fn/dne" [FAIL] "gcr.io/kpt-fn/dne" diff --git a/e2e/testdata/fn-render/invalid-inline-fnconfig/.expected/config.yaml b/e2e/testdata/fn-render/invalid-inline-fnconfig/.expected/config.yaml index de59673705..89dcbcda4b 100644 --- a/e2e/testdata/fn-render/invalid-inline-fnconfig/.expected/config.yaml +++ b/e2e/testdata/fn-render/invalid-inline-fnconfig/.expected/config.yaml @@ -13,4 +13,4 @@ # limitations under the License. exitCode: 1 -stdErr: 'Error: invalid pipeline: function "gcr.io/kpt-fn/set-label:unstable": functionConfig must be a valid KRM resource with `apiVersion` and `kind` fields' +stdErr: "functionConfig must be a valid KRM resource with `apiVersion` and `kind` fields" diff --git a/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml b/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml index d6c6df1fa0..8df30f753c 100644 --- a/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml +++ b/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml @@ -13,7 +13,7 @@ # limitations under the License. exitCode: 1 -stdErr: "Error: function image \"gcr.io/kpt-fn/set-label1\" doesn't exist" +stdErr: 'Error: Function image "gcr.io/kpt-fn/set-label1" doesn''t exist' stdOut: | [RUNNING] "gcr.io/kpt-fn/set-namespace:unstable" [PASS] "gcr.io/kpt-fn/set-namespace:unstable" diff --git a/internal/errors/resolver/docker.go b/internal/errors/resolver/docker.go new file mode 100644 index 0000000000..e043f9fd86 --- /dev/null +++ b/internal/errors/resolver/docker.go @@ -0,0 +1,41 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resolver + +import ( + "errors" + + "github.com/GoogleContainerTools/kpt/internal/fnruntime" +) + +//nolint:gochecknoinits +func init() { + AddErrorResolver(&dockerImageErrorResolver{}) +} + +// dockerImageErrorResolver is an implementation of the ErrorResolver interface +// to resolve docker image errors. +type dockerImageErrorResolver struct{} + +func (*dockerImageErrorResolver) Resolve(err error) (ResolvedResult, bool) { + var dockerImageError *fnruntime.DockerImageError + if !errors.As(err, &dockerImageError) { + return ResolvedResult{}, false + } + return ResolvedResult{ + Message: dockerImageError.Error(), + ExitCode: 1, + }, true +} diff --git a/internal/errors/resolver/pkg.go b/internal/errors/resolver/pkg.go index dc69f0559e..d43fea8404 100644 --- a/internal/errors/resolver/pkg.go +++ b/internal/errors/resolver/pkg.go @@ -53,13 +53,13 @@ func (*pkgErrorResolver) Resolve(err error) (ResolvedResult, bool) { if errors.Is(kptfileError, os.ErrNotExist) { return ResolvedResult{ - Message: ExecuteTemplate(noKptfileMsg, tmplArgs), + Message: ExecuteTemplate(noKptfileMsg, tmplArgs), ExitCode: 1, }, true } return ResolvedResult{ - Message: ExecuteTemplate(kptfileReadErrMsg, tmplArgs), + Message: ExecuteTemplate(kptfileReadErrMsg, tmplArgs), ExitCode: 1, }, true } diff --git a/internal/errors/resolver/validation.go b/internal/errors/resolver/validation.go new file mode 100644 index 0000000000..5dbe4451de --- /dev/null +++ b/internal/errors/resolver/validation.go @@ -0,0 +1,41 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resolver + +import ( + "errors" + + kptfile "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1alpha2" +) + +//nolint:gochecknoinits +func init() { + AddErrorResolver(&kptfileValidateErrorResolver{}) +} + +// kptfileValidateErrorResolver is an implementation of the ErrorResolver interface +// to resolve Kptfile validation error. +type kptfileValidateErrorResolver struct{} + +func (*kptfileValidateErrorResolver) Resolve(err error) (ResolvedResult, bool) { + var validateError *kptfile.ValidateError + if !errors.As(err, &validateError) { + return ResolvedResult{}, false + } + return ResolvedResult{ + Message: validateError.Error(), + ExitCode: 1, + }, true +} diff --git a/internal/fnruntime/container.go b/internal/fnruntime/container.go index 84fc2b3d14..55d5010e93 100644 --- a/internal/fnruntime/container.go +++ b/internal/fnruntime/container.go @@ -163,7 +163,10 @@ func (f *ContainerFn) prepareImage() error { var output []byte var err error if output, err = cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to check local function image %q: %w", f.Image, err) + return &DockerImageError{ + Image: f.Image, + Output: string(output), + } } if strings.Contains(string(output), strings.Split(f.Image, ":")[0]) { // image exists locally @@ -178,8 +181,23 @@ func (f *ContainerFn) prepareImage() error { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() cmd = exec.CommandContext(ctx, dockerBin, args...) - if _, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("function image %q doesn't exist", f.Image) + if output, err := cmd.CombinedOutput(); err != nil { + return &DockerImageError{ + Image: f.Image, + Output: string(output), + } } return nil } + +// DockerImageError is an error type which will be returned when +// the container run time cannot verify docker image. +type DockerImageError struct { + Image string + Output string +} + +func (e *DockerImageError) Error() string { + return fmt.Sprintf(`Function image %q doesn't exist. +Please verify the correctness and existence of the image name.`, e.Image) +} diff --git a/internal/util/addmergecomment/addmergecomment.go b/internal/util/addmergecomment/addmergecomment.go index 4b6aff88c4..03a43f1cee 100644 --- a/internal/util/addmergecomment/addmergecomment.go +++ b/internal/util/addmergecomment/addmergecomment.go @@ -1,3 +1,17 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package addmergecomment import ( diff --git a/internal/util/addmergecomment/addmergecomment_test.go b/internal/util/addmergecomment/addmergecomment_test.go index 94858297a8..14662e4104 100644 --- a/internal/util/addmergecomment/addmergecomment_test.go +++ b/internal/util/addmergecomment/addmergecomment_test.go @@ -1,3 +1,17 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package addmergecomment import ( diff --git a/pkg/api/kptfile/v1alpha2/validation.go b/pkg/api/kptfile/v1alpha2/validation.go index 579bc995da..7b1b736b56 100644 --- a/pkg/api/kptfile/v1alpha2/validation.go +++ b/pkg/api/kptfile/v1alpha2/validation.go @@ -46,7 +46,17 @@ func (p *Pipeline) validate() error { fns = append(fns, p.Validators...) for i := range fns { f := fns[i] - err := f.validate() + // fnIdx is the index of this function in corresponding function + // type + fnIdx := i + // fnType is the type of this function + fnType := "mutators" + if i >= len(p.Mutators) { + // this function is a validator + fnIdx = i - len(p.Mutators) + fnType = "validators" + } + err := f.validate(fnType, fnIdx) if err != nil { return fmt.Errorf("function %q: %w", f.Image, err) } @@ -54,16 +64,24 @@ func (p *Pipeline) validate() error { return nil } -func (f *Function) validate() error { +func (f *Function) validate(fnType string, idx int) error { err := validateFunctionName(f.Image) if err != nil { - return fmt.Errorf("'image' is invalid: %w", err) + return &ValidateError{ + Field: fmt.Sprintf("pipeline.%s[%d].image", fnType, idx), + Value: f.Image, + Reason: err.Error(), + } } var configFields []string if f.ConfigPath != "" { if err := validatePath(f.ConfigPath); err != nil { - return fmt.Errorf("'configPath' %q is invalid: %w", f.ConfigPath, err) + return &ValidateError{ + Field: fmt.Sprintf("pipeline.%s[%d].configPath", fnType, idx), + Value: f.ConfigPath, + Reason: err.Error(), + } } configFields = append(configFields, "configPath") } @@ -73,13 +91,19 @@ func (f *Function) validate() error { if !IsNodeZero(&f.Config) { config := yaml.NewRNode(&f.Config) if _, err := config.GetMeta(); err != nil { - return fmt.Errorf("functionConfig must be a valid KRM resource with `apiVersion` and `kind` fields") + return &ValidateError{ + Field: fmt.Sprintf("pipeline.%s[%d].config", fnType, idx), + Reason: "functionConfig must be a valid KRM resource with `apiVersion` and `kind` fields", + } } configFields = append(configFields, "config") } if len(configFields) > 1 { - return fmt.Errorf("following fields are mutually exclusive: 'config', 'configMap', 'configPath'. Got %q", - strings.Join(configFields, ", ")) + return &ValidateError{ + Field: fmt.Sprintf("pipeline.%s[%d]", fnType, idx), + Reason: fmt.Sprintf("following fields are mutually exclusive: 'config', 'configMap', 'configPath'. Got %q", + strings.Join(configFields, ", ")), + } } return nil @@ -148,3 +172,23 @@ func validatePath(p string) error { } return nil } + +// ValidateError is the error returned when validation fails. +type ValidateError struct { + // Field is the field that causes error + Field string + // Value is the value of invalid field + Value string + // Reason is the reson for the error + Reason string +} + +func (e *ValidateError) Error() string { + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Kptfile is invalid:\nField: `%s`\n", e.Field)) + if e.Value != "" { + sb.WriteString(fmt.Sprintf("Value: %q\n", e.Value)) + } + sb.WriteString(fmt.Sprintf("Reason: %s\n", e.Reason)) + return sb.String() +} From 2748188f86790aff112710e685769334244b7d98 Mon Sep 17 00:00:00 2001 From: Donny Xia Date: Mon, 17 May 2021 11:30:43 -0700 Subject: [PATCH 2/5] code review --- .../resolver/{docker.go => container.go} | 16 ++++---- internal/errors/resolver/pkg.go | 7 ++++ internal/errors/resolver/validation.go | 41 ------------------- internal/fnruntime/container.go | 13 +++--- pkg/api/kptfile/v1alpha2/validation.go | 26 +++++------- 5 files changed, 31 insertions(+), 72 deletions(-) rename internal/errors/resolver/{docker.go => container.go} (65%) delete mode 100644 internal/errors/resolver/validation.go diff --git a/internal/errors/resolver/docker.go b/internal/errors/resolver/container.go similarity index 65% rename from internal/errors/resolver/docker.go rename to internal/errors/resolver/container.go index e043f9fd86..6f2dedeb77 100644 --- a/internal/errors/resolver/docker.go +++ b/internal/errors/resolver/container.go @@ -22,20 +22,20 @@ import ( //nolint:gochecknoinits func init() { - AddErrorResolver(&dockerImageErrorResolver{}) + AddErrorResolver(&containerImageErrorResolver{}) } -// dockerImageErrorResolver is an implementation of the ErrorResolver interface -// to resolve docker image errors. -type dockerImageErrorResolver struct{} +// containerImageErrorResolver is an implementation of the ErrorResolver interface +// to resolve container image errors. +type containerImageErrorResolver struct{} -func (*dockerImageErrorResolver) Resolve(err error) (ResolvedResult, bool) { - var dockerImageError *fnruntime.DockerImageError - if !errors.As(err, &dockerImageError) { +func (*containerImageErrorResolver) Resolve(err error) (ResolvedResult, bool) { + var containerImageError *fnruntime.ContainerImageError + if !errors.As(err, &containerImageError) { return ResolvedResult{}, false } return ResolvedResult{ - Message: dockerImageError.Error(), + Message: containerImageError.Error(), ExitCode: 1, }, true } diff --git a/internal/errors/resolver/pkg.go b/internal/errors/resolver/pkg.go index d43fea8404..1578d99319 100644 --- a/internal/errors/resolver/pkg.go +++ b/internal/errors/resolver/pkg.go @@ -19,6 +19,7 @@ import ( "github.com/GoogleContainerTools/kpt/internal/errors" "github.com/GoogleContainerTools/kpt/internal/pkg" + kptfile "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1alpha2" ) //nolint:gochecknoinits @@ -44,6 +45,7 @@ type pkgErrorResolver struct{} func (*pkgErrorResolver) Resolve(err error) (ResolvedResult, bool) { var kptfileError *pkg.KptfileError + var validateError *kptfile.ValidateError if errors.As(err, &kptfileError) { path := kptfileError.Path tmplArgs := map[string]interface{}{ @@ -62,6 +64,11 @@ func (*pkgErrorResolver) Resolve(err error) (ResolvedResult, bool) { Message: ExecuteTemplate(kptfileReadErrMsg, tmplArgs), ExitCode: 1, }, true + } else if errors.As(err, &validateError) { + return ResolvedResult{ + Message: validateError.Error(), + ExitCode: 1, + }, true } return ResolvedResult{}, false diff --git a/internal/errors/resolver/validation.go b/internal/errors/resolver/validation.go deleted file mode 100644 index 5dbe4451de..0000000000 --- a/internal/errors/resolver/validation.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2021 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package resolver - -import ( - "errors" - - kptfile "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1alpha2" -) - -//nolint:gochecknoinits -func init() { - AddErrorResolver(&kptfileValidateErrorResolver{}) -} - -// kptfileValidateErrorResolver is an implementation of the ErrorResolver interface -// to resolve Kptfile validation error. -type kptfileValidateErrorResolver struct{} - -func (*kptfileValidateErrorResolver) Resolve(err error) (ResolvedResult, bool) { - var validateError *kptfile.ValidateError - if !errors.As(err, &validateError) { - return ResolvedResult{}, false - } - return ResolvedResult{ - Message: validateError.Error(), - ExitCode: 1, - }, true -} diff --git a/internal/fnruntime/container.go b/internal/fnruntime/container.go index 55d5010e93..df5ec2ad20 100644 --- a/internal/fnruntime/container.go +++ b/internal/fnruntime/container.go @@ -163,7 +163,7 @@ func (f *ContainerFn) prepareImage() error { var output []byte var err error if output, err = cmd.CombinedOutput(); err != nil { - return &DockerImageError{ + return &ContainerImageError{ Image: f.Image, Output: string(output), } @@ -182,7 +182,7 @@ func (f *ContainerFn) prepareImage() error { defer cancel() cmd = exec.CommandContext(ctx, dockerBin, args...) if output, err := cmd.CombinedOutput(); err != nil { - return &DockerImageError{ + return &ContainerImageError{ Image: f.Image, Output: string(output), } @@ -190,14 +190,13 @@ func (f *ContainerFn) prepareImage() error { return nil } -// DockerImageError is an error type which will be returned when +// ContainerImageError is an error type which will be returned when // the container run time cannot verify docker image. -type DockerImageError struct { +type ContainerImageError struct { Image string Output string } -func (e *DockerImageError) Error() string { - return fmt.Sprintf(`Function image %q doesn't exist. -Please verify the correctness and existence of the image name.`, e.Image) +func (e *ContainerImageError) Error() string { + return fmt.Sprintf("Function image %q doesn't exist.", e.Image) } diff --git a/pkg/api/kptfile/v1alpha2/validation.go b/pkg/api/kptfile/v1alpha2/validation.go index 7b1b736b56..703f9a1071 100644 --- a/pkg/api/kptfile/v1alpha2/validation.go +++ b/pkg/api/kptfile/v1alpha2/validation.go @@ -41,22 +41,16 @@ func (p *Pipeline) validate() error { if p == nil { return nil } - fns := []Function{} - fns = append(fns, p.Mutators...) - fns = append(fns, p.Validators...) - for i := range fns { - f := fns[i] - // fnIdx is the index of this function in corresponding function - // type - fnIdx := i - // fnType is the type of this function - fnType := "mutators" - if i >= len(p.Mutators) { - // this function is a validator - fnIdx = i - len(p.Mutators) - fnType = "validators" + for i := range p.Mutators { + f := p.Mutators[i] + err := f.validate("mutators", i) + if err != nil { + return fmt.Errorf("function %q: %w", f.Image, err) } - err := f.validate(fnType, fnIdx) + } + for i := range p.Validators { + f := p.Validators[i] + err := f.validate("validators", i) if err != nil { return fmt.Errorf("function %q: %w", f.Image, err) } @@ -101,7 +95,7 @@ func (f *Function) validate(fnType string, idx int) error { if len(configFields) > 1 { return &ValidateError{ Field: fmt.Sprintf("pipeline.%s[%d]", fnType, idx), - Reason: fmt.Sprintf("following fields are mutually exclusive: 'config', 'configMap', 'configPath'. Got %q", + Reason: fmt.Sprintf("only one of 'config', 'configMap', 'configPath' can be specified. Got %q", strings.Join(configFields, ", ")), } } From 3db84fe4bd0b03e7fdae9eb59f94ce2c121e92bc Mon Sep 17 00:00:00 2001 From: Donny Xia Date: Mon, 17 May 2021 12:57:47 -0700 Subject: [PATCH 3/5] update error message --- e2e/testdata/fn-render/multiple-fnconfig/.expected/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/testdata/fn-render/multiple-fnconfig/.expected/config.yaml b/e2e/testdata/fn-render/multiple-fnconfig/.expected/config.yaml index 5f3e6ce046..188ee54259 100644 --- a/e2e/testdata/fn-render/multiple-fnconfig/.expected/config.yaml +++ b/e2e/testdata/fn-render/multiple-fnconfig/.expected/config.yaml @@ -13,4 +13,4 @@ # limitations under the License. exitCode: 1 -stdErr: "following fields are mutually exclusive: 'config', 'configMap', 'configPath'. Got \"configPath, configMap\"" +stdErr: 'only one of ''config'', ''configMap'', ''configPath'' can be specified. Got "configPath, configMap"' From 7d514ebe77c46490a83323962d1b93ebbbf1563e Mon Sep 17 00:00:00 2001 From: Donny Xia Date: Mon, 17 May 2021 14:03:28 -0700 Subject: [PATCH 4/5] code review --- internal/errors/resolver/pkg.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/errors/resolver/pkg.go b/internal/errors/resolver/pkg.go index 1578d99319..c05079be35 100644 --- a/internal/errors/resolver/pkg.go +++ b/internal/errors/resolver/pkg.go @@ -64,7 +64,8 @@ func (*pkgErrorResolver) Resolve(err error) (ResolvedResult, bool) { Message: ExecuteTemplate(kptfileReadErrMsg, tmplArgs), ExitCode: 1, }, true - } else if errors.As(err, &validateError) { + } + if errors.As(err, &validateError) { return ResolvedResult{ Message: validateError.Error(), ExitCode: 1, From 0b401fcefc53c82659508d93cc29dff09c12d2e9 Mon Sep 17 00:00:00 2001 From: Donny Xia Date: Mon, 17 May 2021 15:23:43 -0700 Subject: [PATCH 5/5] update image-nonexist test case --- e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml | 2 +- e2e/testdata/fn-render/missing-fn-image/Kptfile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml b/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml index 8df30f753c..fc5ed75bcd 100644 --- a/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml +++ b/e2e/testdata/fn-render/missing-fn-image/.expected/config.yaml @@ -13,7 +13,7 @@ # limitations under the License. exitCode: 1 -stdErr: 'Error: Function image "gcr.io/kpt-fn/set-label1" doesn''t exist' +stdErr: 'Error: Function image "gcr.io/kpt-fn/dne" doesn''t exist' stdOut: | [RUNNING] "gcr.io/kpt-fn/set-namespace:unstable" [PASS] "gcr.io/kpt-fn/set-namespace:unstable" diff --git a/e2e/testdata/fn-render/missing-fn-image/Kptfile b/e2e/testdata/fn-render/missing-fn-image/Kptfile index 7cc1617fed..2c18b4fddf 100644 --- a/e2e/testdata/fn-render/missing-fn-image/Kptfile +++ b/e2e/testdata/fn-render/missing-fn-image/Kptfile @@ -7,6 +7,6 @@ pipeline: - image: gcr.io/kpt-fn/set-namespace:unstable configMap: namespace: staging - - image: gcr.io/kpt-fn/set-labels1 # non-existing image + - image: gcr.io/kpt-fn/dne # non-existing image configMap: - tier: backend \ No newline at end of file + tier: backend