diff --git a/pkg/patterns/declarative/pkg/applier/direct.go b/pkg/patterns/declarative/pkg/applier/direct.go index b8c84583..44cb3519 100644 --- a/pkg/patterns/declarative/pkg/applier/direct.go +++ b/pkg/patterns/declarative/pkg/applier/direct.go @@ -1,19 +1,19 @@ package applier import ( + "bytes" "context" "fmt" - "os" "strings" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/cli-runtime/pkg/genericclioptions" - "k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/discovery" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" "k8s.io/kubectl/pkg/cmd/apply" - cmdDelete "k8s.io/kubectl/pkg/cmd/delete" cmdutil "k8s.io/kubectl/pkg/cmd/util" ) @@ -27,71 +27,40 @@ func NewDirectApplier() *DirectApplier { } func (d *DirectApplier) Apply(ctx context.Context, opt ApplierOptions) error { + ioReader := strings.NewReader(opt.Manifest) + + buffer := &bytes.Buffer{} + ioStreams := genericclioptions.IOStreams{ - In: os.Stdin, - Out: os.Stdout, - ErrOut: os.Stderr, + In: ioReader, + Out: buffer, + ErrOut: buffer, } - ioReader := strings.NewReader(opt.Manifest) restClientGetter := &staticRESTClientGetter{ RESTMapper: opt.RESTMapper, RESTConfig: opt.RESTConfig, } - b := resource.NewBuilder(restClientGetter) - - if opt.Validate { - // This potentially causes redundant work, but validation isn't the common path - v, err := cmdutil.NewFactory(&genericclioptions.ConfigFlags{}).Validator(true) - if err != nil { - return err - } - b.Schema(v) - } - res := b.Unstructured().Stream(ioReader, "manifestString").Do() - infos, err := res.Infos() - if err != nil { - return err + args := append(opt.ExtraArgs, "-f -") + if !opt.Validate { + args = append(args, "--validate=false") } - - // Populate the namespace on any namespace-scoped objects - if opt.Namespace != "" { - visitor := resource.SetNamespace(opt.Namespace) - for _, info := range infos { - if err := info.Visit(visitor); err != nil { - return fmt.Errorf("error from SetNamespace: %w", err) - } - } + if len(opt.Namespace) > 0 { + args = append(args, "") } - applyOpts := apply.NewApplyOptions(ioStreams) - - for i, arg := range opt.ExtraArgs { - switch arg { - case "--force": - applyOpts.ForceConflicts = true - case "--prune": - applyOpts.Prune = true - case "--selector": - applyOpts.Selector = opt.ExtraArgs[i + 1] - default: - continue - } + f := cmdutil.NewFactory(restClientGetter) + cmd := apply.NewCmdApply("kubectl", f, ioStreams) + if err := cmd.ParseFlags(args); err != nil { + return err } - applyOpts.Namespace = opt.Namespace - applyOpts.SetObjects(infos) - applyOpts.ToPrinter = func(operation string) (printers.ResourcePrinter, error) { - applyOpts.PrintFlags.NamePrintFlags.Operation = operation - cmdutil.PrintFlagsWithDryRunStrategy(applyOpts.PrintFlags, applyOpts.DryRunStrategy) - return applyOpts.PrintFlags.ToPrinter() - } - applyOpts.DeleteOptions = &cmdDelete.DeleteOptions{ - IOStreams: ioStreams, + if err := cmd.Execute(); err != nil { + return fmt.Errorf("exec kubectl apply failed, args: %v, errors: %s", args, buffer.String()) } - return applyOpts.Run() + return nil } // staticRESTClientGetter returns a fixed RESTClient @@ -99,6 +68,7 @@ type staticRESTClientGetter struct { RESTConfig *rest.Config DiscoveryClient discovery.CachedDiscoveryInterface RESTMapper meta.RESTMapper + namespace string } var _ resource.RESTClientGetter = &staticRESTClientGetter{} @@ -121,3 +91,25 @@ func (s *staticRESTClientGetter) ToRESTMapper() (meta.RESTMapper, error) { } return s.RESTMapper, nil } +func (s *staticRESTClientGetter) ToRawKubeConfigLoader() clientcmd.ClientConfig { + return namespaceStub(s.namespace) +} + +type namespaceStub string + +func (n namespaceStub) Namespace() (string, bool, error) { + return string(n), false, nil +} + +// below methods should never be called +func (namespaceStub) RawConfig() (api.Config, error) { + panic("implement me") +} + +func (namespaceStub) ClientConfig() (*rest.Config, error) { + panic("implement me") +} + +func (namespaceStub) ConfigAccess() clientcmd.ConfigAccess { + panic("implement me") +}