mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-17 18:25:26 +00:00
150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
// Copyright 2019 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package runner
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/go-errors/errors"
|
|
"github.com/spf13/cobra"
|
|
"sigs.k8s.io/kustomize/cmd/config/ext"
|
|
"sigs.k8s.io/kustomize/kyaml/pathutil"
|
|
)
|
|
|
|
// CmdRunner interface holds ExecuteCmd definition which executes respective command's
|
|
// implementation on single package
|
|
type CmdRunner interface {
|
|
ExecuteCmd(w io.Writer, pkgPath string) error
|
|
}
|
|
|
|
// ExecuteCmdOnPkgs struct holds the parameters necessary to
|
|
// execute the filter command on packages in rootPkgPath
|
|
type ExecuteCmdOnPkgs struct {
|
|
RootPkgPath string
|
|
RecurseSubPackages bool
|
|
NeedOpenAPI bool
|
|
CmdRunner CmdRunner
|
|
Writer io.Writer
|
|
SkipPkgPathPrint bool
|
|
}
|
|
|
|
// ExecuteCmdOnPkgs takes the function definition for a command to be executed on single package, applies that definition
|
|
// recursively on all the subpackages present in rootPkgPath if recurseSubPackages is true, else applies the command on rootPkgPath only
|
|
func (e ExecuteCmdOnPkgs) Execute() error {
|
|
pkgsPaths, err := pathutil.DirsWithFile(e.RootPkgPath, ext.KRMFileName(), e.RecurseSubPackages)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(pkgsPaths) == 0 {
|
|
// at this point, there are no openAPI files in the rootPkgPath
|
|
if e.NeedOpenAPI {
|
|
// few executions need openAPI file to be present(ex: setters commands), if true throw an error
|
|
return errors.Errorf("unable to find %q in package %q", ext.KRMFileName(), e.RootPkgPath)
|
|
}
|
|
|
|
// add root path for commands which doesn't need openAPI(ex: annotate, fmt)
|
|
pkgsPaths = []string{e.RootPkgPath}
|
|
}
|
|
|
|
// for commands which doesn't need openAPI file, make sure that the root package is
|
|
// included all the times
|
|
if !e.NeedOpenAPI && !containsString(pkgsPaths, e.RootPkgPath) {
|
|
pkgsPaths = append([]string{e.RootPkgPath}, pkgsPaths...)
|
|
}
|
|
|
|
for i := range pkgsPaths {
|
|
err := e.processPkg(pkgsPaths[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if i != len(pkgsPaths)-1 {
|
|
fmt.Fprint(e.Writer, "\n")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e ExecuteCmdOnPkgs) processPkg(pkgPath string) error {
|
|
// Add schema present in openAPI file for current package
|
|
if !e.SkipPkgPathPrint {
|
|
fmt.Fprintf(e.Writer, "%s/\n", pkgPath)
|
|
}
|
|
|
|
return e.CmdRunner.ExecuteCmd(e.Writer, pkgPath)
|
|
}
|
|
|
|
// ParseFieldPath parse a flag value into a field path
|
|
func ParseFieldPath(path string) ([]string, error) {
|
|
// fixup '\.' so we don't split on it
|
|
match := strings.ReplaceAll(path, "\\.", "$$$$")
|
|
parts := strings.Split(match, ".")
|
|
for i := range parts {
|
|
parts[i] = strings.ReplaceAll(parts[i], "$$$$", ".")
|
|
}
|
|
|
|
// split the list index from the list field
|
|
var newParts []string
|
|
for i := range parts {
|
|
if !strings.Contains(parts[i], "[") {
|
|
newParts = append(newParts, parts[i])
|
|
continue
|
|
}
|
|
p := strings.Split(parts[i], "[")
|
|
if len(p) != 2 {
|
|
return nil, fmt.Errorf("unrecognized path element: %s. "+
|
|
"Should be of the form 'list[field=value]'", parts[i])
|
|
}
|
|
p[1] = "[" + p[1]
|
|
newParts = append(newParts, p[0], p[1])
|
|
}
|
|
return newParts, nil
|
|
}
|
|
|
|
func HandleError(c *cobra.Command, err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if StackOnError {
|
|
if err, ok := err.(*errors.Error); ok {
|
|
fmt.Fprintf(os.Stderr, "%s", err.Stack())
|
|
}
|
|
}
|
|
|
|
if ExitOnError {
|
|
fmt.Fprintf(c.ErrOrStderr(), "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// ExitOnError if true, will cause commands to call os.Exit instead of returning an error.
|
|
// Used for skipping printing usage on failure.
|
|
var ExitOnError bool
|
|
|
|
// StackOnError if true, will print a stack trace on failure.
|
|
var StackOnError bool
|
|
|
|
const cmdName = "kustomize fn"
|
|
|
|
// FixDocs replaces instances of old with new in the docs for c
|
|
func FixDocs(newStr string, c *cobra.Command) {
|
|
c.Use = strings.ReplaceAll(c.Use, cmdName, newStr)
|
|
c.Short = strings.ReplaceAll(c.Short, cmdName, newStr)
|
|
c.Long = strings.ReplaceAll(c.Long, cmdName, newStr)
|
|
c.Example = strings.ReplaceAll(c.Example, cmdName, newStr)
|
|
}
|
|
|
|
// containsString returns true if slice contains s
|
|
func containsString(slice []string, s string) bool {
|
|
for _, item := range slice {
|
|
if item == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|