func (f *CommandFactory) Delete(args ...string) (c Command) {
	logging.TraceCall(f.logger)
	defer logging.TraceExit(f.logger)
	c = &DeleteCommand{
		abstractCommand: abstractCommand{
			logger:     f.logger,
			factory:    f,
			subCmd:     "delete",
			jsonOutput: false,
			args:       args,
		},
	}
	return c
}
Delete instantiates a DeleteCommand instance for the described Kubernetes resource.
package kubectl
import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
	"github.com/go-logr/logr"
	"github.com/pkg/errors"
	"github.com/fidelity/kraan/pkg/logging"
)
const (
	kustomizeYaml = "kustomization.yaml"
)
var (
	kubectlCmd          = "kubectl"
	kustomizeCmd        = "kustomize"
	applyArgs           = []string{"-R", "-f"}
	newExecProviderFunc = newExecProvider
	tempDirProviderFunc = createTempDir
)
type Kubectl interface {
	Apply(path string) (c Command)
	Delete(args ...string) (c Command)
	Get(args ...string) (c Command)
}
type Kustomize interface {
	Build(path string) (c Command)
}
func NewKubectl(logger logr.Logger) (kubectl Kubectl, err error) {
	execProvider := newExecProviderFunc()
	return newCommandFactory(logger, execProvider, kubectlCmd)
}
func NewKustomize(logger logr.Logger) (kustomize Kustomize, err error) {
	execProvider := newExecProviderFunc()
	return newCommandFactory(logger, execProvider, kustomizeCmd)
}
type CommandFactory struct {
	logger       logr.Logger
	path         string
	execProvider ExecProvider
}
func newCommandFactory(logger logr.Logger, execProvider ExecProvider, execProg string) (factory *CommandFactory, err error) {
	factory = &CommandFactory{
		logger:       logger,
		execProvider: execProvider,
	}
	factory.path, err = factory.getExecProvider().FindOnPath(execProg)
	if err != nil {
		return nil, errors.Wrapf(err, "%s - unable to find %s binary on system PATH", logging.CallerStr(logging.Me), execProg)
	}
	return factory, nil
}
func (f CommandFactory) getLogger() logr.Logger {
	return f.logger
}
func (f CommandFactory) getPath() string {
	return f.path
}
func (f CommandFactory) getExecProvider() ExecProvider {
	return f.execProvider
}
type Command interface {
	Run() (output []byte, err error)
	Build() (buildDir string)
	DryRun() (output []byte, err error)
	WithLogger(logger logr.Logger) (self Command)
	getPath() string
	getSubCmd() string
	getArgs() []string
	asString() string
	isJSONOutput() bool
}
type abstractCommand struct {
	logger     logr.Logger
	factory    *CommandFactory
	subCmd     string
	jsonOutput bool
	args       []string
	cmd        string
	output     []byte
}
func (c *abstractCommand) logDebug(msg string, keysAndValues ...interface{}) {
	c.logger.V(1).Info(msg, append(keysAndValues, append(logging.GetFunctionAndSource(logging.MyCaller+1), "command", c.asString())...)...)
}
func (c *abstractCommand) logError(sourceErr error, keysAndValues ...interface{}) (err error) {
	msg := "error executing kubectl command"
	c.logger.Error(err, msg, append(keysAndValues, append(logging.GetFunctionAndSource(logging.MyCaller+1), "command", c.asString())...)...)
	return fmt.Errorf("%s '%s' : %w", msg, c.asString(), sourceErr)
}
func (c *abstractCommand) getPath() (path string) {
	return c.factory.path
}
func (c *abstractCommand) getSubCmd() (subCmd string) {
	return c.subCmd
}
func (c *abstractCommand) getArgs() (kargz []string) {
	return append([]string{c.subCmd}, c.args...)
}
func (c *abstractCommand) isJSONOutput() bool {
	return c.jsonOutput
}
func (c *abstractCommand) asString() (cmdString string) {
	if c.cmd == "" {
		c.cmd = strings.Join(append([]string{c.getPath()}, c.getArgs()...), " ")
	}
	return c.cmd
}
func (c *abstractCommand) Run() (output []byte, err error) {
	logging.TraceCall(c.logger)
	defer logging.TraceExit(c.logger)
	if c.jsonOutput {
		c.args = append(c.args, "-o", "json")
	}
	c.logDebug("executing kubectl")
	c.output, err = c.factory.getExecProvider().ExecCmd(c.getPath(), c.getArgs()...)
	if err != nil {
		return nil, errors.WithMessagef(err, "%s - failed to execute kubectl", logging.CallerStr(logging.Me))
	}
	return c.output, nil
}
func createTempDir() (buildDir string, err error) {
	buildDir, err = ioutil.TempDir("", "build-*")
	if err != nil {
		return "", errors.WithMessagef(err, "%s - failed to create temporary directory", logging.CallerStr(logging.Me))
	}
	return buildDir, nil
}
func (c *abstractCommand) Build() (buildDir string) {
	logging.TraceCall(c.logger)
	defer logging.TraceExit(c.logger)
	var err error
	buildDir, err = tempDirProviderFunc()
	if err != nil {
		c.logError(err)  
		return buildDir
	}
	c.args = append(c.args, "-o", buildDir)
	c.logDebug("executing kustomize build")
	c.output, err = c.factory.getExecProvider().ExecCmd(c.getPath(), c.getArgs()...)
	if err != nil {
		c.logError(err)  
	}
	return buildDir
}
func (c *abstractCommand) DryRun() (output []byte, err error) {
	c.args = append(c.args, "--dry-run=server")
	return c.Run()
}
func (c *abstractCommand) WithLogger(logger logr.Logger) (self Command) {
	if logger != nil {
		c.logger = logger
	}
	return c
}
type ApplyCommand struct {
	abstractCommand
}
type BuildCommand struct {
	abstractCommand
}
func (f *CommandFactory) kustomizationBuiler(path string, log logr.Logger) string {
	logging.TraceCall(f.logger)
	defer logging.TraceExit(f.logger)
	kustomize, err := NewKustomize(log)
	if err != nil {
		log.Error(err, "failed to create kustomize command object", logging.GetFunctionAndSource(logging.MyCaller)...)
		return path
	}
	return kustomize.Build(path).Build()
}
func (f *CommandFactory) Build(path string) (c Command) {
	logging.TraceCall(f.logger)
	defer logging.TraceExit(f.logger)
	c = &BuildCommand{
		abstractCommand: abstractCommand{
			logger:     f.logger,
			factory:    f,
			subCmd:     "build",
			jsonOutput: true,
			args:       []string{path},
		},
	}
	return c
}
func (f *CommandFactory) Apply(path string) (c Command) {
	logging.TraceCall(f.logger)
	defer logging.TraceExit(f.logger)
	if f.isKustomization(path) {
		path = f.kustomizationBuiler(path, f.logger)
	}
	c = &ApplyCommand{
		abstractCommand: abstractCommand{
			logger:     f.logger,
			factory:    f,
			subCmd:     "apply",
			jsonOutput: true,
			args:       append(applyArgs, path),
		},
	}
	return c
}
func (f *CommandFactory) isKustomization(dir string) bool {
	logging.TraceCall(f.logger)
	defer logging.TraceExit(f.logger)
	return f.getExecProvider().FileExists(filepath.Join(dir, kustomizeYaml))
}
type DeleteCommand struct {
	abstractCommand
}