diff --git a/api/filters/replacement/replacement.go b/api/filters/replacement/replacement.go index a9330fa1467..5ad976ff84d 100644 --- a/api/filters/replacement/replacement.go +++ b/api/filters/replacement/replacement.go @@ -4,13 +4,13 @@ package replacement import ( - "errors" "fmt" "strings" "sigs.k8s.io/kustomize/api/internal/utils" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/errors" "sigs.k8s.io/kustomize/kyaml/resid" kyaml_utils "sigs.k8s.io/kustomize/kyaml/utils" "sigs.k8s.io/kustomize/kyaml/yaml" @@ -105,7 +105,7 @@ func getRefinedValue(options *types.FieldOptions, rn *yaml.RNode) (*yaml.RNode, func applyReplacement(nodes []*yaml.RNode, value *yaml.RNode, targetSelectors []*types.TargetSelector) ([]*yaml.RNode, error) { for _, selector := range targetSelectors { if selector.Select == nil { - return nil, errors.New("target must specify resources to select") + return nil, errors.Errorf("target must specify resources to select") } if len(selector.FieldPaths) == 0 { selector.FieldPaths = []string{types.DefaultReplacementFieldPath} @@ -191,6 +191,9 @@ func copyValueToTarget(target *yaml.RNode, value *yaml.RNode, selector *types.Ta if createErr != nil { return fmt.Errorf("error creating replacement node: %w", createErr) } + if createdField == nil { + return errors.Errorf("unable to find or create field %s in replacement target", fp) + } targetFields = append(targetFields, createdField) } else { // may return multiple fields, always wrapped in a sequence node @@ -202,6 +205,9 @@ func copyValueToTarget(target *yaml.RNode, value *yaml.RNode, selector *types.Ta if err != nil { return fmt.Errorf("error fetching elements in replacement target: %w", err) } + if len(targetFields) == 0 { + return errors.Errorf("unable to find field %s in replacement target", fp) + } } for _, t := range targetFields { diff --git a/api/krusty/replacementtransformer_test.go b/api/krusty/replacementtransformer_test.go index 5f57082ec96..e71f09b9ffd 100644 --- a/api/krusty/replacementtransformer_test.go +++ b/api/krusty/replacementtransformer_test.go @@ -6,6 +6,7 @@ package krusty_test import ( "testing" + "github.com/stretchr/testify/require" kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" ) @@ -546,3 +547,103 @@ metadata: name: red-dc6gc5btkc `) } + +func TestIssue4761_path_not_in_target_with_create_true(t *testing.T) { + th := kusttest_test.MakeEnhancedHarness(t) + defer th.Reset() + + th.WriteF("resources.yaml", ` +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: request-id +spec: + configPatches: + - applyTo: NETWORK_FILTER + - applyTo: NETWORK_FILTER +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-version + annotations: + config.kubernetes.io/local-config: true +data: + ISTIO_REGEX: '^1\.14.*' +`) + + th.WriteK(".", ` +resources: +- resources.yaml + +replacements: + - source: + kind: ConfigMap + name: istio-version + fieldPath: data.ISTIO_REGEX + targets: + - select: + kind: EnvoyFilter + fieldPaths: + - spec.configPatches.0.match.proxy.proxyVersion + - spec.configPatches.1.match.proxy.proxyVersion + - spec.configPatches.2.match.proxy.proxyVersion + - spec.configPatches.3.match.proxy.proxyVersion + options: + create: true +`) + + err := th.RunWithErr(".", th.MakeDefaultOptions()) + require.EqualError(t, err, "unable to find or create field spec.configPatches.2.match.proxy.proxyVersion in replacement target") +} + +func TestIssue4761_path_not_in_target_with_create_false(t *testing.T) { + th := kusttest_test.MakeEnhancedHarness(t) + defer th.Reset() + + th.WriteF("resources.yaml", ` +--- +apiVersion: networking.istio.io/v1alpha3 +kind: EnvoyFilter +metadata: + name: request-id +spec: + configPatches: + - applyTo: NETWORK_FILTER + - applyTo: NETWORK_FILTER +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-version + annotations: + config.kubernetes.io/local-config: true +data: + ISTIO_REGEX: '^1\.14.*' +`) + + th.WriteK(".", ` +resources: +- resources.yaml + +replacements: + - source: + kind: ConfigMap + name: istio-version + fieldPath: data.ISTIO_REGEX + targets: + - select: + kind: EnvoyFilter + fieldPaths: + - spec.configPatches.0.match.proxy.proxyVersion + - spec.configPatches.1.match.proxy.proxyVersion + - spec.configPatches.2.match.proxy.proxyVersion + - spec.configPatches.3.match.proxy.proxyVersion + options: + create: false +`) + + err := th.RunWithErr(".", th.MakeDefaultOptions()) + require.EqualError(t, err, "unable to find field spec.configPatches.0.match.proxy.proxyVersion in replacement target") +}