infra/blueprint-test/pkg/kpt/kpt.go (100 lines of code) (raw):

package kpt import ( "fmt" "time" "github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/utils" kptfilev1 "github.com/GoogleContainerTools/kpt-functions-sdk/go/api/kptfile/v1" kptutil "github.com/GoogleContainerTools/kpt-functions-sdk/go/api/util" "github.com/gruntwork-io/terratest/modules/logger" "github.com/gruntwork-io/terratest/modules/retry" "github.com/gruntwork-io/terratest/modules/shell" "github.com/mitchellh/go-testing-interface" "sigs.k8s.io/kustomize/kyaml/kio/kioutil" "sigs.k8s.io/kustomize/kyaml/yaml" ) // MIN_KPT_VERSION format: vMAJOR[.MINOR[.PATCH[-PRERELEASE]]] const MIN_KPT_VERSION = "v1.0.0-beta.16" type CmdCfg struct { kptBinary string // kpt binary dir string // dir to execute commands in logger *logger.Logger // custom logger t testing.TB // TestingT or TestingB tries int // qty to try kpt command, default: 3 } type cmdOption func(*CmdCfg) func WithDir(dir string) cmdOption { return func(f *CmdCfg) { f.dir = dir } } func WithBinary(kptBinary string) cmdOption { return func(f *CmdCfg) { f.kptBinary = kptBinary } } func WithLogger(logger *logger.Logger) cmdOption { return func(f *CmdCfg) { f.logger = logger } } // NewCmdConfig sets defaults and validates values for kpt Options. func NewCmdConfig(t testing.TB, opts ...cmdOption) *CmdCfg { kOpts := &CmdCfg{ logger: utils.GetLoggerFromT(), t: t, tries: 3, } // apply options for _, opt := range opts { opt(kOpts) } if kOpts.kptBinary == "" { err := utils.BinaryInPath("kpt") if err != nil { t.Fatalf("unable to find kpt in path: %v", err) } kOpts.kptBinary = "kpt" } // Validate required KPT version if err := utils.MinSemver("v"+GetKptVersion(t, kOpts.kptBinary), MIN_KPT_VERSION); err != nil { t.Fatalf("unable to validate minimum required kpt version: %v", err) } return kOpts } func (k *CmdCfg) RunCmd(args ...string) string { kptCmd := shell.Command{ Command: "kpt", Args: args, Logger: k.logger, WorkingDir: k.dir, } command := func() (string, error) { return shell.RunCommandAndGetStdOutE(k.t, kptCmd) } op, err := retry.DoWithRetryE(k.t, fmt.Sprintf("kpt %v", kptCmd.Args), k.tries, 15*time.Second, command) if err != nil { k.t.Fatal(err) } return op } // findKptfile discovers Kptfile of the root package from slice of nodes func findKptfile(nodes []*yaml.RNode) (*kptfilev1.KptFile, error) { for _, node := range nodes { if node.GetAnnotations()[kioutil.PathAnnotation] == kptfilev1.KptFileName { s, err := node.String() if err != nil { return nil, fmt.Errorf("unable to read Kptfile: %v", err) } kf, err := kptutil.DecodeKptfile(s) if err != nil { return nil, fmt.Errorf("unable to decode Kptfile: %v", err) } return kf, nil } } return nil, fmt.Errorf("unable to find Kptfile, please include --include-meta-resources flag if a Kptfile is present") } // GetKptVersion gets the version of kptBinary func GetKptVersion(t testing.TB, kptBinary string) string { kVersionOpts := &CmdCfg{ kptBinary: kptBinary, dir: utils.GetWD(t), logger: utils.GetLoggerFromT(), t: t, } return kVersionOpts.RunCmd("version") }