mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-18 17:37:03 +00:00
123 lines
3.2 KiB
Go
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
|
|
}
|