diff --git a/cmd/config/internal/commands/run-fns.go b/cmd/config/internal/commands/run-fns.go index bc536c837..e5b588fed 100644 --- a/cmd/config/internal/commands/run-fns.go +++ b/cmd/config/internal/commands/run-fns.go @@ -27,6 +27,8 @@ func GetRunFnRunner(name string) *RunFnRunner { r.Command = c r.Command.Flags().BoolVar( &r.DryRun, "dry-run", false, "print results to stdout") + r.Command.Flags().BoolVar( + &r.GlobalScope, "global-scope", false, "set global scope for functions.") r.Command.Flags().StringSliceVar( &r.FnPaths, "fn-path", []string{}, "directories containing functions without configuration") @@ -44,11 +46,12 @@ type RunFnRunner struct { IncludeSubpackages bool Command *cobra.Command DryRun bool + GlobalScope bool FnPaths []string } func (r *RunFnRunner) runE(c *cobra.Command, args []string) error { - rec := runfn.RunFns{Path: args[0], FunctionPaths: r.FnPaths} + rec := runfn.RunFns{Path: args[0], FunctionPaths: r.FnPaths, GlobalScope: r.GlobalScope} if r.DryRun { rec.Output = c.OutOrStdout() } diff --git a/kyaml/kio/filters/container_test.go b/kyaml/kio/filters/container_test.go index d5fda8200..441f43a7f 100644 --- a/kyaml/kio/filters/container_test.go +++ b/kyaml/kio/filters/container_test.go @@ -587,6 +587,96 @@ metadata: `, b.String()) } +func TestFilter_Filter_globalScope(t *testing.T) { + cfg, err := yaml.Parse(`apiVersion: apps/v1 +kind: Deployment +metadata: + name: foo + annotations: + config.kubernetes.io/path: 'foo/bar.yaml' +`) + if !assert.NoError(t, err) { + return + } + + input, err := (&kio.ByteReader{Reader: bytes.NewBufferString(` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: deployment-foo +--- +apiVersion: v1 +kind: Service +metadata: + name: service-foo +`)}).Read() + if !assert.NoError(t, err) { + return + } + + // no resources match the scope + called := false + result, err := (&ContainerFilter{ + GlobalScope: true, + Image: "example.com:version", + Config: cfg, + args: []string{"sed", "s/Deployment/StatefulSet/g"}, + checkInput: func(s string) { + called = true + if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1 +kind: ResourceList +items: +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: deployment-foo + annotations: + config.kubernetes.io/index: '0' +- apiVersion: v1 + kind: Service + metadata: + name: service-foo + annotations: + config.kubernetes.io/index: '1' +functionConfig: {apiVersion: apps/v1, kind: Deployment, metadata: {name: foo, annotations: { + config.kubernetes.io/path: 'foo/bar.yaml'}}} +`, s) { + t.FailNow() + } + }, + }).Filter(input) + if !assert.NoError(t, err) { + return + } + if !assert.True(t, called) { + return + } + + b := &bytes.Buffer{} + err = kio.ByteWriter{Writer: b, KeepReaderAnnotations: true}.Write(result) + if !assert.NoError(t, err) { + return + } + + // Resources should be preserved -- paths shouldn't be set by container + assert.Equal(t, `apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: deployment-foo + annotations: + config.kubernetes.io/index: '0' + config.kubernetes.io/path: 'foo/statefulset_deployment-foo.yaml' +--- +apiVersion: v1 +kind: Service +metadata: + name: service-foo + annotations: + config.kubernetes.io/index: '1' + config.kubernetes.io/path: 'foo/service_service-foo.yaml' +`, b.String()) +} + func TestFilter_Filter_scopeFunctionsDir(t *testing.T) { // functions under "functions/" dir should be scoped to parent dir cfg, err := yaml.Parse(`apiVersion: apps/v1 diff --git a/kyaml/runfn/runfn.go b/kyaml/runfn/runfn.go index f0b32c912..4aabe5ba1 100644 --- a/kyaml/runfn/runfn.go +++ b/kyaml/runfn/runfn.go @@ -25,6 +25,8 @@ type RunFns struct { // directory FunctionPaths []string + GlobalScope bool + // Output can be set to write the result to Output rather than back to the directory Output io.Writer @@ -91,7 +93,12 @@ func (r *RunFns) init() { // if containerFilterProvider hasn't been set, use the default if r.containerFilterProvider == nil { r.containerFilterProvider = func(image, path string, api *yaml.RNode) kio.Filter { - cf := &filters.ContainerFilter{Image: image, Config: api, StorageMounts: r.StorageMounts} + cf := &filters.ContainerFilter{ + Image: image, + Config: api, + StorageMounts: r.StorageMounts, + GlobalScope: r.GlobalScope, + } return cf } } diff --git a/kyaml/runfn/runfn_test.go b/kyaml/runfn/runfn_test.go index 3ff988ffd..7a9cb8d90 100644 --- a/kyaml/runfn/runfn_test.go +++ b/kyaml/runfn/runfn_test.go @@ -43,6 +43,20 @@ kind: assert.Equal(t, &filters.ContainerFilter{Image: "example.com:version", Config: api}, filter) } +func TestRunFns_Execute_globalScope(t *testing.T) { + instance := RunFns{GlobalScope: true} + instance.init() + api, err := yaml.Parse(`apiVersion: apps/v1 +kind: +`) + if !assert.NoError(t, err) { + return + } + filter := instance.containerFilterProvider("example.com:version", "", api) + assert.Equal(t, &filters.ContainerFilter{ + Image: "example.com:version", Config: api, GlobalScope: true}, filter) +} + func TestCmd_Execute(t *testing.T) { dir, err := ioutil.TempDir("", "kustomize-kyaml-test") if !assert.NoError(t, err) {