From 203246b7e06670da9c47d368305b0ca371ecb8dc Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Fri, 12 Dec 2014 17:53:33 -0500 Subject: [PATCH] Allow the api-version on the command to override the client builder --- pkg/client/clientcmd/client_builder.go | 38 +++++++++++++++++---- pkg/client/clientcmd/client_builder_test.go | 35 +++++++++++++++++++ pkg/kubectl/cmd/cmd.go | 4 ++- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/pkg/client/clientcmd/client_builder.go b/pkg/client/clientcmd/client_builder.go index 80ef5b704fe..201c8a83be8 100644 --- a/pkg/client/clientcmd/client_builder.go +++ b/pkg/client/clientcmd/client_builder.go @@ -33,10 +33,15 @@ import ( type Builder interface { // BindFlags must bind and keep track of all the flags required to build a client config object BindFlags(flags *pflag.FlagSet) - // Config uses the values of the bound flags and builds a complete client config - Config() (*client.Config, error) // Client calls BuildConfig under the covers and uses that config to return a client Client() (*client.Client, error) + + // Config uses the values of the bound flags and builds a complete client config + Config() (*client.Config, error) + // Override invokes Config(), then passes that to the provided function, and returns a new + // builder that will use that config as its default. If Config() returns an error for the default + // values the function will not be invoked, and the error will be available when Client() is called. + Override(func(*client.Config)) Builder } // cmdAuthInfo is used to track whether flags have been set @@ -58,6 +63,8 @@ type builder struct { apiserver string apiVersion string matchApiVersion bool + + config *client.Config } // NewBuilder returns a valid Builder that uses the passed authLoader. If authLoader is nil, the NewDefaultAuthLoader is used. @@ -124,6 +131,26 @@ func (builder *builder) Client() (*client.Client, error) { // Config implements Builder func (builder *builder) Config() (*client.Config, error) { + if builder.config != nil { + return builder.config, nil + } + return builder.newConfig() +} + +// Override implements Builder +func (builder *builder) Override(fn func(*client.Config)) Builder { + config, err := builder.newConfig() + if err != nil { + return builder + } + fn(config) + b := *builder + b.config = config + return &b +} + +// newConfig creates a new config object for this builder +func (builder *builder) newConfig() (*client.Config, error) { clientConfig := client.Config{} if len(builder.apiserver) > 0 { clientConfig.Host = builder.apiserver @@ -140,12 +167,11 @@ func (builder *builder) Config() (*client.Config, error) { authInfoFileFound := true authInfo, err := builder.authLoader.LoadAuth(builder.authPath) if authInfo == nil && err != nil { // only consider failing if we don't have any auth info - if os.IsNotExist(err) { // if it's just a case of a missing file, simply flag the auth as not found and use the command line arguments - authInfoFileFound = false - authInfo = &clientauth.Info{} - } else { + if !os.IsNotExist(err) { // if it's just a case of a missing file, simply flag the auth as not found and use the command line arguments return nil, err } + authInfoFileFound = false + authInfo = &clientauth.Info{} } // If provided, the command line options override options from the auth file diff --git a/pkg/client/clientcmd/client_builder_test.go b/pkg/client/clientcmd/client_builder_test.go index cb2a7b45e68..6262fe83cac 100644 --- a/pkg/client/clientcmd/client_builder_test.go +++ b/pkg/client/clientcmd/client_builder_test.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/pflag" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/clientauth" ) @@ -251,6 +252,40 @@ func TestLoadClientAuthInfoOrPrompt(t *testing.T) { } } +func TestOverride(t *testing.T) { + b := NewBuilder(nil) + cfg, err := b.Config() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if cfg.Version != "" { + t.Errorf("unexpected default config version") + } + + newCfg, err := b.Override(func(cfg *client.Config) { + if cfg.Version != "" { + t.Errorf("unexpected default config version") + } + cfg.Version = "test" + }).Config() + + if newCfg.Version != "test" { + t.Errorf("unexpected override config version") + } + + if cfg.Version != "" { + t.Errorf("original object should not change") + } + + cfg, err = b.Config() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if cfg.Version != "" { + t.Errorf("override should not be persistent") + } +} + func matchStringArg(expected, got string, t *testing.T) { if expected != got { t.Errorf("Expected %v, got %v", expected, got) diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index cffdb909296..50ce9b710f6 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -64,7 +64,9 @@ func NewFactory(clientBuilder clientcmd.Builder) *Factory { } }, Client: func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error) { - return clientBuilder.Client() + return clientBuilder.Override(func(c *client.Config) { + c.Version = mapping.APIVersion + }).Client() }, Describer: func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error) { client, err := clientBuilder.Client()