kubeconform/vendor/github.com/GoogleContainerTools/kpt-functions-sdk/go/fn/run.go
2023-01-24 16:34:14 +01:00

123 lines
3.2 KiB
Go

// 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 fn
import (
"fmt"
"io"
"os"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
)
// AsMain evaluates the ResourceList from STDIN to STDOUT.
// `input` can be
// - a `ResourceListProcessor` which implements `Process` method
// - a function `Runner` which implements `Run` method
func AsMain(input interface{}) error {
err := func() error {
var p ResourceListProcessor
switch input := input.(type) {
case runnerProcessor:
p = input
case ResourceListProcessorFunc:
p = input
default:
return fmt.Errorf("unknown input type %T", input)
}
in, err := io.ReadAll(os.Stdin)
if err != nil {
return fmt.Errorf("unable to read from stdin: %v", err)
}
out, err := Run(p, in)
// If there is an error, we don't return the error immediately.
// We write out to stdout before returning any error.
_, outErr := os.Stdout.Write(out)
if outErr != nil {
return outErr
}
return err
}()
if err != nil {
Logf("failed to evaluate function: %v", err)
}
return err
}
// Run evaluates the function. input must be a resourceList in yaml format. An
// updated resourceList will be returned.
func Run(p ResourceListProcessor, input []byte) ([]byte, error) {
switch input := p.(type) {
case runnerProcessor:
p = input
case ResourceListProcessorFunc:
p = input
default:
return nil, fmt.Errorf("unknown input type %T", input)
}
rl, err := ParseResourceList(input)
if err != nil {
return nil, err
}
success, fnErr := p.Process(rl)
out, yamlErr := rl.ToYAML()
if yamlErr != nil {
return out, yamlErr
}
if fnErr != nil {
return out, fnErr
}
if !success {
return out, fmt.Errorf("error: function failure")
}
return out, nil
}
func Execute(p ResourceListProcessor, r io.Reader, w io.Writer) error {
rw := &byteReadWriter{
kio.ByteReadWriter{
Reader: r,
Writer: w,
// We should not set the id annotation in the function, since we should not
// overwrite what the orchestrator set.
OmitReaderAnnotations: true,
// We should not remove the id annotations in the function, since the
// orchestrator (e.g. kpt) may need them.
KeepReaderAnnotations: true,
},
}
return execute(p, rw)
}
func execute(p ResourceListProcessor, rw *byteReadWriter) error {
// Read the input
rl, err := rw.Read()
if err != nil {
return errors.WrapPrefixf(err, "failed to read ResourceList input")
}
success, fnErr := p.Process(rl)
// Write the output
if err := rw.Write(rl); err != nil {
return errors.WrapPrefixf(err, "failed to write ResourceList output")
}
if fnErr != nil {
return fnErr
}
if !success {
return fmt.Errorf("error: function failure")
}
return nil
}