refactor Factory make it interface

pull/6/head
AdoHe 2016-10-13 08:09:26 +08:00
parent 06c1f2ba2c
commit 593d8e0d7c
2 changed files with 639 additions and 587 deletions

View File

@ -77,87 +77,107 @@ const (
// TODO: make the functions interfaces
// TODO: pass the various interfaces on the factory directly into the command constructors (so the
// commands are decoupled from the factory).
type Factory struct {
clients *ClientCache
flags *pflag.FlagSet
type Factory interface {
// Returns internal flagset
FlagSet() *pflag.FlagSet
// Returns interfaces for dealing with arbitrary runtime.Objects.
Object func() (meta.RESTMapper, runtime.ObjectTyper)
Object() (meta.RESTMapper, runtime.ObjectTyper)
// Returns interfaces for dealing with arbitrary
// runtime.Unstructured. This performs API calls to discover types.
UnstructuredObject func() (meta.RESTMapper, runtime.ObjectTyper, error)
UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, error)
// Returns interfaces for decoding objects - if toInternal is set, decoded objects will be converted
// into their internal form (if possible). Eventually the internal form will be removed as an option,
// and only versioned objects will be returned.
Decoder func(toInternal bool) runtime.Decoder
Decoder(toInternal bool) runtime.Decoder
// Returns an encoder capable of encoding a provided object into JSON in the default desired version.
JSONEncoder func() runtime.Encoder
JSONEncoder() runtime.Encoder
// ClientSet gives you back an internal, generated clientset
ClientSet func() (*internalclientset.Clientset, error)
ClientSet() (*internalclientset.Clientset, error)
// Returns a RESTClient for accessing Kubernetes resources or an error.
RESTClient func() (*restclient.RESTClient, error)
RESTClient() (*restclient.RESTClient, error)
// Returns a client.Config for accessing the Kubernetes server.
ClientConfig func() (*restclient.Config, error)
ClientConfig() (*restclient.Config, 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 func(mapping *meta.RESTMapping) (resource.RESTClient, error)
ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
// Returns a RESTClient for working with Unstructured objects.
UnstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
// Returns a Describer for displaying the specified RESTMapping type or an error.
Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
Describer(mapping *meta.RESTMapping) (kubectl.Describer, error)
// Returns a Printer for formatting objects of the given type or an error.
Printer func(mapping *meta.RESTMapping, options kubectl.PrintOptions) (kubectl.ResourcePrinter, error)
Printer(mapping *meta.RESTMapping, options kubectl.PrintOptions) (kubectl.ResourcePrinter, error)
// Returns a Scaler for changing the size of the specified RESTMapping type or an error
Scaler func(mapping *meta.RESTMapping) (kubectl.Scaler, error)
Scaler(mapping *meta.RESTMapping) (kubectl.Scaler, error)
// Returns a Reaper for gracefully shutting down resources.
Reaper func(mapping *meta.RESTMapping) (kubectl.Reaper, error)
Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error)
// Returns a HistoryViewer for viewing change history
HistoryViewer func(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error)
HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error)
// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error
Rollbacker func(mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
// Returns a StatusViewer for printing rollout status.
StatusViewer func(mapping *meta.RESTMapping) (kubectl.StatusViewer, error)
StatusViewer(mapping *meta.RESTMapping) (kubectl.StatusViewer, error)
// MapBasedSelectorForObject returns the map-based selector associated with the provided object. If a
// new set-based selector is provided, an error is returned if the selector cannot be converted to a
// map-based selector
MapBasedSelectorForObject func(object runtime.Object) (string, error)
MapBasedSelectorForObject(object runtime.Object) (string, error)
// PortsForObject returns the ports associated with the provided object
PortsForObject func(object runtime.Object) ([]string, error)
PortsForObject(object runtime.Object) ([]string, error)
// ProtocolsForObject returns the <port, protocol> mapping associated with the provided object
ProtocolsForObject func(object runtime.Object) (map[string]string, error)
ProtocolsForObject(object runtime.Object) (map[string]string, error)
// LabelsForObject returns the labels associated with the provided object
LabelsForObject func(object runtime.Object) (map[string]string, error)
LabelsForObject(object runtime.Object) (map[string]string, error)
// LogsForObject returns a request for the logs associated with the provided object
LogsForObject func(object, options runtime.Object) (*restclient.Request, error)
LogsForObject(object, options runtime.Object) (*restclient.Request, error)
// PauseObject marks the provided object as paused ie. it will not be reconciled by its controller.
PauseObject func(object runtime.Object) (bool, error)
PauseObject(object runtime.Object) (bool, error)
// ResumeObject resumes a paused object ie. it will be reconciled by its controller.
ResumeObject func(object runtime.Object) (bool, error)
ResumeObject(object runtime.Object) (bool, error)
// Returns a schema that can validate objects stored on disk.
Validator func(validate bool, cacheDir string) (validation.Schema, error)
Validator(validate bool, cacheDir string) (validation.Schema, error)
// SwaggerSchema returns the schema declaration for the provided group version kind.
SwaggerSchema func(unversioned.GroupVersionKind) (*swagger.ApiDeclaration, error)
SwaggerSchema(unversioned.GroupVersionKind) (*swagger.ApiDeclaration, error)
// Returns the default namespace to use in cases where no
// other namespace is specified and whether the namespace was
// overridden.
DefaultNamespace func() (string, bool, error)
DefaultNamespace() (string, bool, error)
// Generators returns the generators for the provided command
Generators func(cmdName string) map[string]kubectl.Generator
Generators(cmdName string) map[string]kubectl.Generator
// Check whether the kind of resources could be exposed
CanBeExposed func(kind unversioned.GroupKind) error
CanBeExposed(kind unversioned.GroupKind) error
// Check whether the kind of resources could be autoscaled
CanBeAutoscaled func(kind unversioned.GroupKind) error
CanBeAutoscaled(kind unversioned.GroupKind) error
// AttachablePodForObject returns the pod to which to attach given an object.
AttachablePodForObject func(object runtime.Object) (*api.Pod, error)
AttachablePodForObject(object runtime.Object) (*api.Pod, error)
// UpdatePodSpecForObject will call the provided function on the pod spec this object supports,
// return false if no pod spec is supported, or return an error.
UpdatePodSpecForObject func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error)
UpdatePodSpecForObject(obj runtime.Object, fn func(*api.PodSpec) error) (bool, 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 func() []string
EditorEnvs() []string
// PrintObjectSpecificMessage prints object-specific messages on the provided writer
PrintObjectSpecificMessage func(obj runtime.Object, out io.Writer)
PrintObjectSpecificMessage(obj runtime.Object, out io.Writer)
// Command will stringify and return all environment arguments ie. a command run by a client
// using the factory.
Command() string
// BindFlags adds any flags that are common to all kubectl sub commands.
BindFlags(flags *pflag.FlagSet)
// BindExternalFlags adds any flags defined by external projects (not part of pflags)
BindExternalFlags(flags *pflag.FlagSet)
DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace bool) *kubectl.PrintOptions
// DefaultResourceFilterFunc returns a collection of FilterFuncs suitable for filtering specific resource types.
DefaultResourceFilterFunc() kubectl.Filters
// PrintObject prints an api object given command line flags to modify the output format
PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error)
// One stop shopping for a Builder
NewBuilder() *resource.Builder
}
const (
@ -273,10 +293,17 @@ func makeInterfacesFor(versionList []unversioned.GroupVersion) func(version unve
}
}
type factory struct {
flags *pflag.FlagSet
clientConfig clientcmd.ClientConfig
clients *ClientCache
}
// NewFactory creates a factory with the default Kubernetes resources defined
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
// if optionalClientConfig is not nil, then this factory will make use of it.
func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
func NewFactory(optionalClientConfig clientcmd.ClientConfig) Factory {
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
flags.SetNormalizeFunc(utilflag.WarnWordSepNormalizeFunc) // Warn for "_" flags
@ -286,13 +313,19 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
clients := NewClientCache(clientConfig)
return &Factory{
clients: clients,
return &factory{
flags: flags,
clientConfig: clientConfig,
clients: clients,
}
}
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
cfg, err := clientConfig.ClientConfig()
func (f *factory) FlagSet() *pflag.FlagSet {
return f.flags
}
func (f *factory) Object() (meta.RESTMapper, runtime.ObjectTyper) {
cfg, err := f.clientConfig.ClientConfig()
checkErrWithPrefix("failed to get client config: ", err)
cmdApiVersion := unversioned.GroupVersion{}
if cfg.GroupVersion != nil {
@ -329,9 +362,10 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
// wrap with output preferences
mapper = kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}
return mapper, api.Scheme
},
UnstructuredObject: func() (meta.RESTMapper, runtime.ObjectTyper, error) {
cfg, err := clients.ClientConfigForVersion(nil)
}
func (f *factory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, error) {
cfg, err := f.clients.ClientConfigForVersion(nil)
if err != nil {
return nil, nil, err
}
@ -363,22 +397,26 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
typer := discovery.NewUnstructuredObjectTyper(groupResources)
return NewShortcutExpander(mapper, dc), typer, nil
},
RESTClient: func() (*restclient.RESTClient, error) {
clientConfig, err := clients.ClientConfigForVersion(nil)
}
func (f *factory) RESTClient() (*restclient.RESTClient, error) {
clientConfig, err := f.clients.ClientConfigForVersion(nil)
if err != nil {
return nil, err
}
return restclient.RESTClientFor(clientConfig)
},
ClientSet: func() (*internalclientset.Clientset, error) {
return clients.ClientSetForVersion(nil)
},
ClientConfig: func() (*restclient.Config, error) {
return clients.ClientConfigForVersion(nil)
},
ClientForMapping: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
cfg, err := clientConfig.ClientConfig()
}
func (f *factory) ClientSet() (*internalclientset.Clientset, error) {
return f.clients.ClientSetForVersion(nil)
}
func (f *factory) ClientConfig() (*restclient.Config, error) {
return f.clients.ClientConfigForVersion(nil)
}
func (f *factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
cfg, err := f.clientConfig.ClientConfig()
if err != nil {
return nil, err
}
@ -389,7 +427,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
switch gvk.Group {
case federation.GroupName:
mappingVersion := mapping.GroupVersionKind.GroupVersion()
return clients.FederationClientForVersion(&mappingVersion)
return f.clients.FederationClientForVersion(&mappingVersion)
case api.GroupName:
cfg.APIPath = "/api"
default:
@ -401,9 +439,10 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
cfg.NegotiatedSerializer = thirdpartyresourcedata.NewNegotiatedSerializer(api.Codecs, gvk.Kind, gv, gv)
}
return restclient.RESTClientFor(cfg)
},
UnstructuredClientForMapping: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
cfg, err := clientConfig.ClientConfig()
}
func (f *factory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
cfg, err := f.clientConfig.ClientConfig()
if err != nil {
return nil, err
}
@ -418,11 +457,12 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
cfg.ContentConfig = dynamic.ContentConfig()
cfg.GroupVersion = &gv
return restclient.RESTClientFor(cfg)
},
Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
}
func (f *factory) Describer(mapping *meta.RESTMapping) (kubectl.Describer, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
if mapping.GroupVersionKind.Group == federation.GroupName {
fedClientSet, err := clients.FederationClientSetForVersion(&mappingVersion)
fedClientSet, err := f.clients.FederationClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
@ -430,7 +470,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return &kubectl.ClusterDescriber{Interface: fedClientSet}, nil
}
}
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
@ -438,8 +478,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return describer, nil
}
return nil, fmt.Errorf("no description has been implemented for %q", mapping.GroupVersionKind.Kind)
},
Decoder: func(toInternal bool) runtime.Decoder {
}
func (f *factory) Decoder(toInternal bool) runtime.Decoder {
var decoder runtime.Decoder
if toInternal {
decoder = api.Codecs.UniversalDecoder()
@ -447,15 +488,17 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
decoder = api.Codecs.UniversalDeserializer()
}
return thirdpartyresourcedata.NewDecoder(decoder, "")
}
},
JSONEncoder: func() runtime.Encoder {
func (f *factory) JSONEncoder() runtime.Encoder {
return api.Codecs.LegacyCodec(registered.EnabledVersions()...)
},
Printer: func(mapping *meta.RESTMapping, options kubectl.PrintOptions) (kubectl.ResourcePrinter, error) {
}
func (f *factory) Printer(mapping *meta.RESTMapping, options kubectl.PrintOptions) (kubectl.ResourcePrinter, error) {
return kubectl.NewHumanReadablePrinter(options), nil
},
MapBasedSelectorForObject: func(object runtime.Object) (string, error) {
}
func (f *factory) MapBasedSelectorForObject(object runtime.Object) (string, error) {
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
switch t := object.(type) {
case *api.ReplicationController:
@ -491,8 +534,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return "", fmt.Errorf("cannot extract pod selector from %v", gvks[0])
}
},
PortsForObject: func(object runtime.Object) ([]string, error) {
}
func (f *factory) PortsForObject(object runtime.Object) ([]string, error) {
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
switch t := object.(type) {
case *api.ReplicationController:
@ -512,8 +556,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return nil, fmt.Errorf("cannot extract ports from %v", gvks[0])
}
},
ProtocolsForObject: func(object runtime.Object) (map[string]string, error) {
}
func (f *factory) ProtocolsForObject(object runtime.Object) (map[string]string, error) {
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
switch t := object.(type) {
case *api.ReplicationController:
@ -533,12 +578,14 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return nil, fmt.Errorf("cannot extract protocols from %v", gvks[0])
}
},
LabelsForObject: func(object runtime.Object) (map[string]string, error) {
}
func (f *factory) LabelsForObject(object runtime.Object) (map[string]string, error) {
return meta.NewAccessor().Labels(object)
},
LogsForObject: func(object, options runtime.Object) (*restclient.Request, error) {
clientset, err := clients.ClientSetForVersion(nil)
}
func (f *factory) LogsForObject(object, options runtime.Object) (*restclient.Request, error) {
clientset, err := f.clients.ClientSetForVersion(nil)
if err != nil {
return nil, err
}
@ -595,9 +642,10 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return nil, fmt.Errorf("cannot get the logs from %v", gvks[0])
}
},
PauseObject: func(object runtime.Object) (bool, error) {
clientset, err := clients.ClientSetForVersion(nil)
}
func (f *factory) PauseObject(object runtime.Object) (bool, error) {
clientset, err := f.clients.ClientSetForVersion(nil)
if err != nil {
return false, err
}
@ -617,9 +665,10 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return false, fmt.Errorf("cannot pause %v", gvks[0])
}
},
ResumeObject: func(object runtime.Object) (bool, error) {
clientset, err := clients.ClientSetForVersion(nil)
}
func (f *factory) ResumeObject(object runtime.Object) (bool, error) {
clientset, err := f.clients.ClientSetForVersion(nil)
if err != nil {
return false, err
}
@ -639,50 +688,56 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return false, fmt.Errorf("cannot resume %v", gvks[0])
}
},
Scaler: func(mapping *meta.RESTMapping) (kubectl.Scaler, error) {
}
func (f *factory) Scaler(mapping *meta.RESTMapping) (kubectl.Scaler, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.ScalerFor(mapping.GroupVersionKind.GroupKind(), clientset)
},
Reaper: func(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
}
func (f *factory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.ReaperFor(mapping.GroupVersionKind.GroupKind(), clientset)
},
HistoryViewer: func(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) {
}
func (f *factory) HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.HistoryViewerFor(mapping.GroupVersionKind.GroupKind(), clientset)
},
Rollbacker: func(mapping *meta.RESTMapping) (kubectl.Rollbacker, error) {
}
func (f *factory) Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), clientset)
},
StatusViewer: func(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) {
}
func (f *factory) StatusViewer(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
clientset, err := clients.ClientSetForVersion(&mappingVersion)
clientset, err := f.clients.ClientSetForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.StatusViewerFor(mapping.GroupVersionKind.GroupKind(), clientset)
},
Validator: func(validate bool, cacheDir string) (validation.Schema, error) {
}
func (f *factory) Validator(validate bool, cacheDir string) (validation.Schema, error) {
if validate {
clientConfig, err := clients.ClientConfigForVersion(nil)
clientConfig, err := f.clients.ClientConfigForVersion(nil)
if err != nil {
return nil, err
}
@ -690,7 +745,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
if err != nil {
return nil, err
}
clientset, err := clients.ClientSetForVersion(nil)
clientset, err := f.clients.ClientSetForVersion(nil)
if err != nil {
return nil, err
}
@ -703,7 +758,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
dir = "" // disable caching as a fallback
}
}
fedClient, err := clients.FederationClientForVersion(nil)
fedClient, err := f.clients.FederationClientForVersion(nil)
if err != nil {
return nil, err
}
@ -714,22 +769,26 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}, nil
}
return validation.NullSchema{}, nil
},
SwaggerSchema: func(gvk unversioned.GroupVersionKind) (*swagger.ApiDeclaration, error) {
}
func (f *factory) SwaggerSchema(gvk unversioned.GroupVersionKind) (*swagger.ApiDeclaration, error) {
version := gvk.GroupVersion()
clientset, err := clients.ClientSetForVersion(&version)
clientset, err := f.clients.ClientSetForVersion(&version)
if err != nil {
return nil, err
}
return clientset.Discovery().SwaggerSchema(version)
},
DefaultNamespace: func() (string, bool, error) {
return clientConfig.Namespace()
},
Generators: func(cmdName string) map[string]kubectl.Generator {
}
func (f *factory) DefaultNamespace() (string, bool, error) {
return f.clientConfig.Namespace()
}
func (f *factory) Generators(cmdName string) map[string]kubectl.Generator {
return DefaultGenerators(cmdName)
},
CanBeExposed: func(kind unversioned.GroupKind) error {
}
func (f *factory) CanBeExposed(kind unversioned.GroupKind) error {
switch kind {
case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"), extensions.Kind("Deployment"), extensions.Kind("ReplicaSet"):
// nothing to do here
@ -737,8 +796,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return fmt.Errorf("cannot expose a %s", kind)
}
return nil
},
CanBeAutoscaled: func(kind unversioned.GroupKind) error {
}
func (f *factory) CanBeAutoscaled(kind unversioned.GroupKind) error {
switch kind {
case api.Kind("ReplicationController"), extensions.Kind("Deployment"), extensions.Kind("ReplicaSet"):
// nothing to do here
@ -746,9 +806,10 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return fmt.Errorf("cannot autoscale a %v", kind)
}
return nil
},
AttachablePodForObject: func(object runtime.Object) (*api.Pod, error) {
clientset, err := clients.ClientSetForVersion(nil)
}
func (f *factory) AttachablePodForObject(object runtime.Object) (*api.Pod, error) {
clientset, err := f.clients.ClientSetForVersion(nil)
if err != nil {
return nil, err
}
@ -783,9 +844,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return nil, fmt.Errorf("cannot attach to %v: not implemented", gvks[0])
}
},
// UpdatePodSpecForObject update the pod specification for the provided object
UpdatePodSpecForObject: func(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error) {
}
func (f *factory) UpdatePodSpecForObject(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error) {
// TODO: replace with a swagger schema based approach (identify pod template via schema introspection)
switch t := obj.(type) {
case *api.Pod:
@ -808,11 +869,13 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
default:
return false, fmt.Errorf("the object is not a pod or does not have a pod template")
}
},
EditorEnvs: func() []string {
}
func (f *factory) EditorEnvs() []string {
return []string{"KUBE_EDITOR", "EDITOR"}
},
PrintObjectSpecificMessage: func(obj runtime.Object, out io.Writer) {
}
func (f *factory) PrintObjectSpecificMessage(obj runtime.Object, out io.Writer) {
switch obj := obj.(type) {
case *api.Service:
if obj.Spec.Type == api.ServiceTypeNodePort {
@ -838,8 +901,6 @@ See http://kubernetes.io/docs/user-guide/services-firewalls for more details.
out.Write([]byte(msg))
}
}
},
}
}
// GetFirstPod returns a pod matching the namespace and label selector
@ -883,10 +944,8 @@ func GetFirstPod(client coreclient.PodsGetter, namespace string, selector labels
return pod, 1, nil
}
// Command will stringify and return all environment arguments ie. a command run by a client
// using the factory.
// TODO: We need to filter out stuff like secrets.
func (f *Factory) Command() string {
func (f *factory) Command() string {
if len(os.Args) == 0 {
return ""
}
@ -895,8 +954,7 @@ func (f *Factory) Command() string {
return strings.Join(args, " ")
}
// BindFlags adds any flags that are common to all kubectl sub commands.
func (f *Factory) BindFlags(flags *pflag.FlagSet) {
func (f *factory) BindFlags(flags *pflag.FlagSet) {
// Merge factory's flags
flags.AddFlagSet(f.flags)
@ -911,8 +969,7 @@ func (f *Factory) BindFlags(flags *pflag.FlagSet) {
flags.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)
}
// BindCommonFlags adds any flags defined by external projects (not part of pflags)
func (f *Factory) BindExternalFlags(flags *pflag.FlagSet) {
func (f *factory) BindExternalFlags(flags *pflag.FlagSet) {
// any flags defined by external projects (not part of pflags)
flags.AddGoFlagSet(flag.CommandLine)
}
@ -1179,7 +1236,7 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
return clientConfig
}
func (f *Factory) DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace bool) *kubectl.PrintOptions {
func (f *factory) DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace bool) *kubectl.PrintOptions {
columnLabel, err := cmd.Flags().GetStringSlice("label-columns")
if err != nil {
columnLabel = []string{}
@ -1197,13 +1254,11 @@ func (f *Factory) DefaultResourceFilterOptions(cmd *cobra.Command, withNamespace
return opts
}
// DefaultResourceFilterFunc returns a collection of FilterFuncs suitable for filtering specific resource types.
func (f *Factory) DefaultResourceFilterFunc() kubectl.Filters {
func (f *factory) DefaultResourceFilterFunc() kubectl.Filters {
return kubectl.NewResourceFilter()
}
// PrintObject prints an api object given command line flags to modify the output format
func (f *Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error {
func (f *factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error {
gvks, _, err := api.Scheme.ObjectKinds(obj)
if err != nil {
return err
@ -1221,9 +1276,7 @@ func (f *Factory) PrintObject(cmd *cobra.Command, mapper meta.RESTMapper, obj ru
return printer.PrintObj(obj, out)
}
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error) {
func (f *factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping, withNamespace bool) (kubectl.ResourcePrinter, error) {
printer, ok, err := PrinterForCommand(cmd)
if err != nil {
return nil, err
@ -1273,8 +1326,7 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin
return printer, nil
}
// One stop shopping for a Builder
func (f *Factory) NewBuilder() *resource.Builder {
func (f *factory) NewBuilder() *resource.Builder {
mapper, typer := f.Object()
return resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true))

View File

@ -55,7 +55,7 @@ import (
func TestNewFactoryDefaultFlagBindings(t *testing.T) {
factory := NewFactory(nil)
if !factory.flags.HasFlags() {
if !factory.FlagSet().HasFlags() {
t.Errorf("Expected flags, but didn't get any")
}
}
@ -64,8 +64,8 @@ func TestNewFactoryNoFlagBindings(t *testing.T) {
clientConfig := clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})
factory := NewFactory(clientConfig)
if factory.flags.HasFlags() {
t.Errorf("Expected zero flags, but got %v", factory.flags)
if factory.FlagSet().HasFlags() {
t.Errorf("Expected zero flags, but got %v", factory.FlagSet())
}
}
@ -229,12 +229,12 @@ func TestCanBeExposed(t *testing.T) {
func TestFlagUnderscoreRenaming(t *testing.T) {
factory := NewFactory(nil)
factory.flags.SetNormalizeFunc(flag.WordSepNormalizeFunc)
factory.flags.Bool("valid_flag", false, "bool value")
factory.FlagSet().SetNormalizeFunc(flag.WordSepNormalizeFunc)
factory.FlagSet().Bool("valid_flag", false, "bool value")
// In case of failure of this test check this PR: spf13/pflag#23
if factory.flags.Lookup("valid_flag").Name != "valid-flag" {
t.Fatalf("Expected flag name to be valid-flag, got %s", factory.flags.Lookup("valid_flag").Name)
if factory.FlagSet().Lookup("valid_flag").Name != "valid-flag" {
t.Fatalf("Expected flag name to be valid-flag, got %s", factory.FlagSet().Lookup("valid_flag").Name)
}
}