github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/hook/executor.go (about) 1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package hook 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 22 "github.com/GoogleContainerTools/kpt/internal/fnruntime" 23 "github.com/GoogleContainerTools/kpt/internal/pkg" 24 "github.com/GoogleContainerTools/kpt/internal/types" 25 fnresult "github.com/GoogleContainerTools/kpt/pkg/api/fnresult/v1" 26 kptfilev1 "github.com/GoogleContainerTools/kpt/pkg/api/kptfile/v1" 27 "github.com/GoogleContainerTools/kpt/pkg/fn" 28 "sigs.k8s.io/kustomize/kyaml/filesys" 29 "sigs.k8s.io/kustomize/kyaml/kio" 30 ) 31 32 // ErrAllowedExecNotSpecified indicates user need to authorize to invoke 33 // exec binaries. 34 var ErrAllowedExecNotSpecified = fmt.Errorf("must run with `--allow-exec` option to allow running function binaries") 35 36 // Executor executes a hook. 37 type Executor struct { 38 PkgPath string 39 ResultsDirPath string 40 Output io.Writer 41 42 RunnerOptions fnruntime.RunnerOptions 43 44 FileSystem filesys.FileSystem 45 46 // function runtime 47 Runtime fn.FunctionRuntime 48 49 // fnResults stores function results gathered 50 // during pipeline execution. 51 fnResults *fnresult.ResultList 52 } 53 54 // Execute executes given hook. 55 func (e *Executor) Execute(ctx context.Context, hook []kptfilev1.Function) error { 56 e.fnResults = fnresult.NewResultList() 57 58 pkgReaderWriter := &kio.LocalPackageReadWriter{ 59 PackagePath: e.PkgPath, 60 MatchFilesGlob: pkg.MatchAllKRM, 61 PreserveSeqIndent: true, 62 PackageFileName: kptfilev1.KptFileName, 63 IncludeSubpackages: true, 64 WrapBareSeqNode: true, 65 } 66 mutators, err := e.fnChain(ctx, hook) 67 if err != nil { 68 return err 69 } 70 p := kio.Pipeline{ 71 Inputs: []kio.Reader{pkgReaderWriter}, 72 Filters: mutators, 73 Outputs: []kio.Writer{pkgReaderWriter}, 74 } 75 76 return p.Execute() 77 } 78 79 // fnChain returns a slice of function runners given a list of functions defined in pipeline. 80 func (e *Executor) fnChain(ctx context.Context, fns []kptfilev1.Function) ([]kio.Filter, error) { 81 var runners []kio.Filter 82 for i := range fns { 83 var err error 84 var runner kio.Filter 85 fn := fns[i] 86 if fn.Exec != "" && !e.RunnerOptions.AllowExec { 87 return nil, ErrAllowedExecNotSpecified 88 } 89 opts := e.RunnerOptions 90 runner, err = fnruntime.NewRunner(ctx, 91 e.FileSystem, 92 &fn, 93 types.UniquePath(e.PkgPath), 94 e.fnResults, 95 opts, 96 e.Runtime) 97 if err != nil { 98 return nil, err 99 } 100 runners = append(runners, runner) 101 } 102 return runners, nil 103 }