diff --git a/pkg/kubectl/cmd/plugin.go b/pkg/kubectl/cmd/plugin.go index 12d621ff3ef..35c4662a59b 100644 --- a/pkg/kubectl/cmd/plugin.go +++ b/pkg/kubectl/cmd/plugin.go @@ -44,7 +44,7 @@ var ( // NewCmdPlugin creates the command that is the top-level for plugin commands. func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { // Loads plugins and create commands for each plugin identified - loadedPlugins, loadErr := f.PluginLoader().Load() + loadedPlugins, loadErr := pluginLoader().Load() if loadErr != nil { glog.V(1).Infof("Unable to load plugins: %v", loadErr) } @@ -63,7 +63,7 @@ func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra } if len(loadedPlugins) > 0 { - pluginRunner := f.PluginRunner() + pluginRunner := pluginRunner() for _, p := range loadedPlugins { cmd.AddCommand(NewCmdForPlugin(f, p, pluginRunner, streams)) } @@ -166,3 +166,22 @@ func (p *factoryAttrsPluginEnvProvider) Env() (plugins.EnvList, error) { plugins.Env{N: "KUBECTL_PLUGINS_CURRENT_NAMESPACE", V: cmdNamespace}, }, nil } + +// pluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var. +// If this env var is not set, it defaults to +// "~/.kube/plugins", plus +// "./kubectl/plugins" directory under the "data dir" directory specified by the XDG +// system directory structure spec for the given platform. +func pluginLoader() plugins.PluginLoader { + if len(os.Getenv("KUBECTL_PLUGINS_PATH")) > 0 { + return plugins.KubectlPluginsPathPluginLoader() + } + return plugins.TolerantMultiPluginLoader{ + plugins.XDGDataDirsPluginLoader(), + plugins.UserDirPluginLoader(), + } +} + +func pluginRunner() plugins.PluginRunner { + return &plugins.ExecPluginRunner{} +} diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 0823f273399..0d8c9c93b0f 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -168,7 +168,7 @@ func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st if err != nil { return err } - o.scaler, err = f.Scaler() + o.scaler, err = scaler(f) if err != nil { return err } @@ -288,3 +288,12 @@ func ScaleJob(info *resource.Info, jobsClient batchclient.JobsGetter, count uint return scaler.Scale(info.Namespace, info.Name, count, jobPreconditions, jobRetry, jobWaitForReplicas) } + +func scaler(f cmdutil.Factory) (kubectl.Scaler, error) { + scalesGetter, err := f.ScaleClient() + if err != nil { + return nil, err + } + + return kubectl.NewScaler(scalesGetter), nil +} diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 402edf38947..813194fa814 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -286,10 +286,6 @@ func (f *TestFactory) Cleanup() { os.Remove(f.tempConfigFile.Name()) } -func (f *TestFactory) CategoryExpander() (restmapper.CategoryExpander, error) { - return resource.FakeCategoryExpander, nil -} - func (f *TestFactory) ClientConfig() (*restclient.Config, error) { return f.ClientConfigVal, nil } @@ -334,7 +330,6 @@ func (f *TestFactory) Command(*cobra.Command, bool) string { func (f *TestFactory) NewBuilder() *resource.Builder { mapper, err := f.RESTMapper() - categoryExpander, err2 := f.CategoryExpander() return resource.NewFakeBuilder( func(version schema.GroupVersion) (resource.RESTClient, error) { @@ -347,8 +342,8 @@ func (f *TestFactory) NewBuilder() *resource.Builder { return f.Client, nil }, mapper, - categoryExpander, - ).AddError(err).AddError(err2) + resource.FakeCategoryExpander, + ).AddError(err) } func (f *TestFactory) KubernetesClientSet() (*kubernetes.Clientset, error) { diff --git a/pkg/kubectl/cmd/util/BUILD b/pkg/kubectl/cmd/util/BUILD index ca6446fda35..55d011890d4 100644 --- a/pkg/kubectl/cmd/util/BUILD +++ b/pkg/kubectl/cmd/util/BUILD @@ -30,7 +30,6 @@ go_library( "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi/validation:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library", - "//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/validation:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index 47308d4dd23..e300364b564 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -185,7 +185,7 @@ func (o *EditOptions) Validate() error { } func (o *EditOptions) Run() error { - edit := NewDefaultEditor(o.f.EditorEnvs()) + edit := NewDefaultEditor(editorEnvs()) // editFn is invoked for each edit session (once with a list for normal edit, once for each individual resource in a edit-on-create invocation) editFn := func(infos []*resource.Info) error { var ( @@ -811,3 +811,11 @@ func hashOnLineBreak(s string) string { } return r } + +// editorEnvs returns an ordered list of env vars to check for editor preferences. +func editorEnvs() []string { + return []string{ + "KUBE_EDITOR", + "EDITOR", + } +} diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 96e7aa3f9f2..4e23d5861e9 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -24,7 +24,6 @@ import ( "time" "github.com/spf13/cobra" - "github.com/spf13/pflag" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -36,7 +35,6 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" scaleclient "k8s.io/client-go/scale" api "k8s.io/kubernetes/pkg/apis/core" apiv1 "k8s.io/kubernetes/pkg/apis/core/v1" @@ -45,7 +43,6 @@ import ( "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" - "k8s.io/kubernetes/pkg/kubectl/plugins" "k8s.io/kubernetes/pkg/kubectl/validation" "k8s.io/kubernetes/pkg/printers" ) @@ -66,14 +63,6 @@ type Factory interface { BuilderFactory } -type DiscoveryClientFactory interface { - // Returns a discovery client - DiscoveryClient() (discovery.CachedDiscoveryInterface, error) - - // BindFlags adds any discovery flags that are common to all kubectl sub commands. - BindFlags(flags *pflag.FlagSet) -} - // ClientAccessFactory holds the first level of factory methods. // Generally provides discovery, negotiation, and no-dep calls. // TODO The polymorphic calls probably deserve their own interface. @@ -151,18 +140,11 @@ type ClientAccessFactory interface { CanBeExposed(kind schema.GroupKind) error // Check whether the kind of resources could be autoscaled CanBeAutoscaled(kind schema.GroupKind) error - - // EditorEnvs returns a group of environment variables that the edit command - // can range over in order to determine if the user has specified an editor - // of their choice. - EditorEnvs() []string } // ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods. // Generally they provide object typing and functions that build requests based on the negotiated clients. type ObjectMappingFactory interface { - // Returns interface for expanding categories like `all`. - CategoryExpander() (restmapper.CategoryExpander, error) // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended // for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer. ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) @@ -197,12 +179,6 @@ type ObjectMappingFactory interface { // BuilderFactory holds the third level of factory methods. These functions depend upon ObjectMappingFactory and ClientAccessFactory methods. // Generally they depend upon client mapper functions type BuilderFactory interface { - // PluginLoader provides the implementation to be used to load cli plugins. - PluginLoader() plugins.PluginLoader - // PluginRunner provides the implementation to be used to run cli plugins. - PluginRunner() plugins.PluginRunner - // Returns a Scaler for changing the size of the specified RESTMapping type or an error - Scaler() (kubectl.Scaler, error) // ScaleClient gives you back scale getter ScaleClient() (scaleclient.ScalesGetter, error) // Returns a Reaper for gracefully shutting down resources. diff --git a/pkg/kubectl/cmd/util/factory_builder.go b/pkg/kubectl/cmd/util/factory_builder.go index 1d9cbead9e1..81145a4cc94 100644 --- a/pkg/kubectl/cmd/util/factory_builder.go +++ b/pkg/kubectl/cmd/util/factory_builder.go @@ -19,13 +19,10 @@ limitations under the License. package util import ( - "os" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/client-go/dynamic" scaleclient "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/kubectl/plugins" ) type ring2Factory struct { @@ -42,25 +39,6 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac return f } -// PluginLoader loads plugins from a path set by the KUBECTL_PLUGINS_PATH env var. -// If this env var is not set, it defaults to -// "~/.kube/plugins", plus -// "./kubectl/plugins" directory under the "data dir" directory specified by the XDG -// system directory structure spec for the given platform. -func (f *ring2Factory) PluginLoader() plugins.PluginLoader { - if len(os.Getenv("KUBECTL_PLUGINS_PATH")) > 0 { - return plugins.KubectlPluginsPathPluginLoader() - } - return plugins.TolerantMultiPluginLoader{ - plugins.XDGDataDirsPluginLoader(), - plugins.UserDirPluginLoader(), - } -} - -func (f *ring2Factory) PluginRunner() plugins.PluginRunner { - return &plugins.ExecPluginRunner{} -} - func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { discoClient, err := f.clientAccessFactory.DiscoveryClient() if err != nil { @@ -79,15 +57,6 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil } -func (f *ring2Factory) Scaler() (kubectl.Scaler, error) { - scalesGetter, err := f.ScaleClient() - if err != nil { - return nil, err - } - - return kubectl.NewScaler(scalesGetter), nil -} - func (f *ring2Factory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) { clientset, clientsetErr := f.clientAccessFactory.ClientSet() if clientsetErr != nil { diff --git a/pkg/kubectl/cmd/util/factory_client_access.go b/pkg/kubectl/cmd/util/factory_client_access.go index 5850dc2ae65..ad3c4a8f7c0 100644 --- a/pkg/kubectl/cmd/util/factory_client_access.go +++ b/pkg/kubectl/cmd/util/factory_client_access.go @@ -578,10 +578,6 @@ func (f *ring0Factory) CanBeAutoscaled(kind schema.GroupKind) error { return nil } -func (f *ring0Factory) EditorEnvs() []string { - return []string{"KUBE_EDITOR", "EDITOR"} -} - // overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`) diff --git a/pkg/kubectl/cmd/util/factory_object_mapping.go b/pkg/kubectl/cmd/util/factory_object_mapping.go index 0fbd425b90d..5e74534c9c1 100644 --- a/pkg/kubectl/cmd/util/factory_object_mapping.go +++ b/pkg/kubectl/cmd/util/factory_object_mapping.go @@ -40,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" @@ -75,15 +74,6 @@ func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMapp return f } -func (f *ring1Factory) CategoryExpander() (restmapper.CategoryExpander, error) { - discoveryClient, err := f.clientAccessFactory.DiscoveryClient() - if err != nil { - return nil, err - } - - return restmapper.NewDiscoveryCategoryExpander(discoveryClient), nil -} - func (f *ring1Factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) { cfg, err := f.clientAccessFactory.ClientConfig() if err != nil {