diff --git a/internal/util/render/executor.go b/internal/util/render/executor.go index 66c11e6e4d..71acf9e67a 100644 --- a/internal/util/render/executor.go +++ b/internal/util/render/executor.go @@ -90,7 +90,7 @@ func (e *Renderer) Execute(ctx context.Context) error { imagePullPolicy: e.ImagePullPolicy, allowExec: e.AllowExec, fileSystem: e.FileSystem, - evaluator: e.Runner, + runner: e.Runner, } if _, err = hydrate(ctx, root, hctx); err != nil { @@ -205,7 +205,8 @@ type hydrationContext struct { fileSystem filesys.FileSystem - evaluator fn.FunctionRunner + // custom function runner + runner fn.FunctionRunner } // @@ -479,14 +480,17 @@ func (pn *pkgNode) runValidators(ctx context.Context, hctx *hydrationContext, in return errAllowedExecNotSpecified } if function.Image != "" && !hctx.dockerCheckDone { - err := cmdutil.DockerCmdAvailable() - if err != nil { - return err + if hctx.runner == nil { + // Check for Docker when using standard runner. + err := cmdutil.DockerCmdAvailable() + if err != nil { + return err + } } hctx.dockerCheckDone = true } - if hctx.evaluator != nil { - validator, err = hctx.evaluator.NewRunner(ctx, &function, fn.RunnerOptions{ResultList: hctx.fnResults}) + if hctx.runner != nil { + validator, err = hctx.runner.NewRunner(ctx, &function, fn.RunnerOptions{ResultList: hctx.fnResults}) } else { validator, err = fnruntime.NewRunner(ctx, &function, pn.pkg.UniquePath, hctx.fnResults, hctx.imagePullPolicy, displayResourceCount) } @@ -597,14 +601,17 @@ func fnChain(ctx context.Context, hctx *hydrationContext, pkgPath types.UniquePa return nil, errAllowedExecNotSpecified } if function.Image != "" && !hctx.dockerCheckDone { - err := cmdutil.DockerCmdAvailable() - if err != nil { - return nil, err + if hctx.runner == nil { + // Check for Docker when using standard runner. + err := cmdutil.DockerCmdAvailable() + if err != nil { + return nil, err + } } hctx.dockerCheckDone = true } - if hctx.evaluator != nil { - runner, err = hctx.evaluator.NewRunner(ctx, &function, fn.RunnerOptions{ResultList: hctx.fnResults}) + if hctx.runner != nil { + runner, err = hctx.runner.NewRunner(ctx, &function, fn.RunnerOptions{ResultList: hctx.fnResults}) } else { runner, err = fnruntime.NewRunner(ctx, &function, pkgPath, hctx.fnResults, hctx.imagePullPolicy, displayResourceCount) } diff --git a/porch/engine/go.mod b/porch/engine/go.mod index b501d455d1..ddabf2155a 100644 --- a/porch/engine/go.mod +++ b/porch/engine/go.mod @@ -7,6 +7,7 @@ require ( github.com/GoogleContainerTools/kpt/porch/api v0.0.0-00010101000000-000000000000 github.com/GoogleContainerTools/kpt/porch/controllers v0.0.0-00010101000000-000000000000 github.com/GoogleContainerTools/kpt/porch/repository v0.0.0-00010101000000-000000000000 + github.com/google/go-cmp v0.5.6 k8s.io/klog/v2 v2.40.1 sigs.k8s.io/kustomize/api v0.8.11 sigs.k8s.io/kustomize/kyaml v0.13.1 @@ -44,7 +45,6 @@ require ( github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.6 // indirect github.com/google/go-containerregistry v0.8.0 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect diff --git a/porch/engine/pkg/internal/functions.go b/porch/engine/pkg/internal/functions.go index c671e04066..f671bb1788 100644 --- a/porch/engine/pkg/internal/functions.go +++ b/porch/engine/pkg/internal/functions.go @@ -21,7 +21,8 @@ import ( ) var functions map[string]framework.ResourceListProcessorFunc = map[string]framework.ResourceListProcessorFunc{ - "gcr.io/kpt-fn/set-labels:v0.1.5": setLabels, + "gcr.io/kpt-fn/set-labels:v0.1.5": setLabels, + "gcr.io/kpt-fn/set-namespace:v0.2.0": setNamespace, } func Eval(image string, rl *framework.ResourceList) error { diff --git a/porch/engine/pkg/internal/set-namespace.go b/porch/engine/pkg/internal/set-namespace.go new file mode 100644 index 0000000000..17d681f24d --- /dev/null +++ b/porch/engine/pkg/internal/set-namespace.go @@ -0,0 +1,48 @@ +// Copyright 2022 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 internal + +import ( + "fmt" + + "sigs.k8s.io/kustomize/kyaml/fn/framework" +) + +// Simple implementation of set-namespace kpt function, primarily for testing. +func setNamespace(rl *framework.ResourceList) error { + if rl.FunctionConfig == nil { + return nil // nothing to do + } + + if !validGVK(rl.FunctionConfig, "v1", "ConfigMap") { + return fmt.Errorf("invalid set-namespace function config type: %s/%s; expected v1/ConfigMap", rl.FunctionConfig.GetApiVersion(), rl.FunctionConfig.GetKind()) + } + + data := rl.FunctionConfig.GetDataMap() + if data == nil { + return nil // nothing to do + } + + namespace, ok := data["namespace"] + if !ok { + return nil // nothing to do + } + + for _, n := range rl.Items { + n.SetNamespace(namespace) + } + + return nil +} diff --git a/porch/engine/pkg/kpt/eval.go b/porch/engine/pkg/kpt/eval.go index dbc90bc9a1..08b60d3c30 100644 --- a/porch/engine/pkg/kpt/eval.go +++ b/porch/engine/pkg/kpt/eval.go @@ -28,31 +28,31 @@ import ( ) func NewPlaceholderFunctionRunner() fn.FunctionRunner { - return &evaluator{} + return &runner{} } -type evaluator struct { +type runner struct { } -var _ fn.FunctionRunner = &evaluator{} +var _ fn.FunctionRunner = &runner{} -func (e *evaluator) NewRunner(ctx context.Context, fn *kptfilev1.Function, opts fn.RunnerOptions) (kio.Filter, error) { - return &runner{ +func (e *runner) NewRunner(ctx context.Context, fn *kptfilev1.Function, opts fn.RunnerOptions) (kio.Filter, error) { + return &filter{ ctx: ctx, fn: *fn, rl: opts.ResultList, }, nil } -type runner struct { +type filter struct { ctx context.Context fn kptfilev1.Function rl *fnresultv1.ResultList } -var _ kio.Filter = &runner{} +var _ kio.Filter = &filter{} -func (r *runner) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) { +func (r *filter) Filter(items []*yaml.RNode) ([]*yaml.RNode, error) { rl := &framework.ResourceList{ Items: items, Results: []*framework.Result{}, diff --git a/porch/engine/pkg/kpt/eval_test.go b/porch/engine/pkg/kpt/eval_test.go index fe247dec27..8fddd84f87 100644 --- a/porch/engine/pkg/kpt/eval_test.go +++ b/porch/engine/pkg/kpt/eval_test.go @@ -26,7 +26,7 @@ import ( ) func TestSetLabels(t *testing.T) { - k := &evaluator{} + k := &runner{} const pkgYaml = `# Comment apiVersion: storage.cnrm.cloud.google.com/v1beta1 diff --git a/porch/engine/pkg/kpt/fs_test.go b/porch/engine/pkg/kpt/fs_test.go index d100f56743..bcacf86266 100644 --- a/porch/engine/pkg/kpt/fs_test.go +++ b/porch/engine/pkg/kpt/fs_test.go @@ -20,6 +20,7 @@ import ( "github.com/GoogleContainerTools/kpt/internal/fnruntime" "github.com/GoogleContainerTools/kpt/internal/printer/fake" "github.com/GoogleContainerTools/kpt/internal/util/render" + "github.com/google/go-cmp/cmp" ) func TestMemFS(t *testing.T) { @@ -62,10 +63,10 @@ metadata: name: app pipeline: mutators: - - image: gcr.io/kpt-fn/set-namespace:v0.1.3 + - image: gcr.io/kpt-fn/set-namespace:v0.2.0 configMap: namespace: staging - - image: gcr.io/kpt-fn/set-labels:v0.1.4 + - image: gcr.io/kpt-fn/set-labels:v0.1.5 configMap: tier: backend` @@ -78,13 +79,6 @@ metadata: tier: backend spec: replicas: 3 - selector: - matchLabels: - tier: backend - template: - metadata: - labels: - tier: backend --- apiVersion: custom.io/v1 kind: Custom @@ -111,6 +105,7 @@ spec: PkgPath: "/a/b/c", ImagePullPolicy: fnruntime.IfNotPresentPull, FileSystem: fs, + Runner: &runner{}, } err := r.Execute(fake.CtxWithDefaultPrinter()) if err != nil { @@ -146,33 +141,13 @@ metadata: name: app-with-db pipeline: mutators: - - image: gcr.io/kpt-fn/set-namespace:v0.1.3 + - image: gcr.io/kpt-fn/set-namespace:v0.2.0 configMap: namespace: staging - - image: gcr.io/kpt-fn/set-labels:v0.1.4 + - image: gcr.io/kpt-fn/set-labels:v0.1.5 configMap: tier: db` - /*dbResources := `apiVersion: apps/v1 - kind: StatefulSet - metadata: - name: db - spec: - replicas: 3` - - dbKptfile := `apiVersion: kpt.dev/v1 - kind: Kptfile - metadata: - name: db - pipeline: - mutators: - - image: gcr.io/kpt-fn/set-namespace:v0.1.3 - configMap: - namespace: db - - image: gcr.io/kpt-fn/set-labels:v0.1.4 - configMap: - app: backend`*/ - expectedAppResources := `apiVersion: apps/v1 kind: Deployment metadata: @@ -182,13 +157,6 @@ metadata: tier: db spec: replicas: 3 - selector: - matchLabels: - tier: db - template: - metadata: - labels: - tier: db --- apiVersion: custom.io/v1 kind: Custom @@ -200,24 +168,6 @@ metadata: spec: image: nginx:1.2.3 ` - /*expectedDbResources := `apiVersion: apps/v1 - kind: StatefulSet - metadata: - name: db - namespace: staging - labels: - tier: db - spec: - replicas: 3 - selector: - matchLabels: - tier: db - template: - metadata: - labels: - tier: db - `*/ - fs := &memfs{} if err := fs.MkdirAll("app"); err != nil { t.Errorf(`MkdirAll("a/b/c") failed %v`, err) @@ -228,17 +178,12 @@ spec: if err := fs.WriteFile("/app/Kptfile", []byte(appKptfile)); err != nil { t.Errorf("Failed to write file: %v", err) } - /*if err := fs.WriteFile("/app/db/resources.yaml", []byte(dbResources)); err != nil { - t.Errorf("Failed to write file: %v", err) - } - if err := fs.WriteFile("/app/db/Kptfile", []byte(dbKptfile)); err != nil { - t.Errorf("Failed to write file: %v", err) - }*/ r := render.Renderer{ PkgPath: "/app", ImagePullPolicy: fnruntime.IfNotPresentPull, FileSystem: fs, + Runner: &runner{}, } err := r.Execute(fake.CtxWithDefaultPrinter()) if err != nil { @@ -251,12 +196,6 @@ spec: if res, err := fs.ReadFile("/app/resources.yaml"); err != nil { t.Errorf("Failed to read file: %v", err) } else if got, want := string(res), expectedAppResources; got != want { - t.Errorf("unexpected file contents: got %q, want %q", got, want) + t.Errorf("unexpected file contents: got %q, want %q\n%s", got, want, cmp.Diff(want, got)) } - - /*if res, err := fs.ReadFile("/app/db/resources.yaml"); err != nil { - t.Errorf("Failed to read file: %v", err) - } else if got, want := string(res), expectedDbResources; got != want { - t.Errorf("unexpected file contents: got %q, want %q", got, want) - }*/ }