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  }