Skip to content

Commit

Permalink
fix kubernetes-sigs#201 running kubectl apply in higher level
Browse files Browse the repository at this point in the history
  • Loading branch information
xuzhenglun committed Mar 24, 2022
1 parent 8e2f972 commit 006ad38
Showing 1 changed file with 45 additions and 53 deletions.
98 changes: 45 additions & 53 deletions pkg/patterns/declarative/pkg/applier/direct.go
Original file line number Diff line number Diff line change
@@ -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"
)

Expand All @@ -27,78 +27,48 @@ 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
type staticRESTClientGetter struct {
RESTConfig *rest.Config
DiscoveryClient discovery.CachedDiscoveryInterface
RESTMapper meta.RESTMapper
namespace string
}

var _ resource.RESTClientGetter = &staticRESTClientGetter{}
Expand All @@ -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")
}

0 comments on commit 006ad38

Please sign in to comment.