diff --git a/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go b/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go index ae0f01f3257..0880adfd718 100644 --- a/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go +++ b/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go @@ -115,6 +115,19 @@ func NewClientConfigFromBytes(configBytes []byte) (ClientConfig, error) { return &DirectClientConfig{*config, "", &ConfigOverrides{}, nil, nil, promptedCredentials{}}, nil } +// NewClientConfigWithMergedRawConfig acts like a NewDefaultClientConfig but merges the RawConfig with the overrides +func NewClientConfigWithMergedRawConfig(config clientcmdapi.Config, overrides *ConfigOverrides) (ClientConfig, error) { + clientCfg := &DirectClientConfig{config, config.CurrentContext, overrides, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}} + + mergedRawCfg, err := clientCfg.getMergedRawConfig() + clientCfg.config = mergedRawCfg + if err != nil { + return nil, err + } + return clientCfg, nil + +} + // RESTConfigFromKubeConfig is a convenience method to give back a restconfig from your kubeconfig bytes. // For programmatic access, this is what you want 80% of the time func RESTConfigFromKubeConfig(configBytes []byte) (*restclient.Config, error) { @@ -129,6 +142,40 @@ func (config *DirectClientConfig) RawConfig() (clientcmdapi.Config, error) { return config.config, nil } +// getMergedRawConfig returns the raw kube config merged with the overrides +func (config *DirectClientConfig) getMergedRawConfig() (clientcmdapi.Config, error) { + if err := config.ConfirmUsable(); err != nil { + return clientcmdapi.Config{}, err + } + merged := clientcmdapi.NewConfig() + + // set the AuthInfo merged with overrides in the merged config + mergedAuthInfo, err := config.getAuthInfo() + if err != nil { + return clientcmdapi.Config{}, err + } + mergedAuthInfoName, _ := config.getAuthInfoName() + merged.AuthInfos[mergedAuthInfoName] = &mergedAuthInfo + + // set the Context merged with overrides in the merged config + mergedContext, err := config.getContext() + if err != nil { + return clientcmdapi.Config{}, err + } + mergedContextName, _ := config.getContextName() + merged.Contexts[mergedContextName] = &mergedContext + merged.CurrentContext = mergedContextName + + // set the Cluster merged with overrides in the merged config + configClusterInfo, err := config.getCluster() + if err != nil { + return clientcmdapi.Config{}, err + } + configClusterName, _ := config.getClusterName() + merged.Clusters[configClusterName] = &configClusterInfo + return *merged, nil +} + // ClientConfig implements ClientConfig func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) { // check that getAuthInfo, getContext, and getCluster do not return an error. diff --git a/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go b/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go index 64efc901623..ac68a4afcdb 100644 --- a/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go +++ b/staging/src/k8s.io/client-go/tools/clientcmd/client_config_test.go @@ -1013,3 +1013,72 @@ func TestCleanANSIEscapeCodes(t *testing.T) { }) } } + +func TestMergeRawConfigDoOverride(t *testing.T) { + cfg := createValidTestConfig() + + overrides := &ConfigOverrides{ + ClusterInfo: clientcmdapi.Cluster{ + Server: "http://localhost:8081", + }, + Context: clientcmdapi.Context{ + Namespace: "foobar", + Cluster: "clean", + AuthInfo: "clean", + }, + AuthInfo: clientcmdapi.AuthInfo{ + Token: "modified-token", + }, + CurrentContext: "clean", + } + + cut, err := NewClientConfigWithMergedRawConfig(*cfg, overrides) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + act, err := cut.RawConfig() + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if act.Clusters["clean"].Server != "http://localhost:8081" { + t.Errorf("Expected server %v, got %v", "http://localhost:8081", act.Clusters["clean"].Server) + } + + if act.Contexts["clean"].Namespace != "foobar" { + t.Errorf("Expected namespace %v, got %v", "foobar", act.Contexts["clean"].Namespace) + } +} + +func TestMergeRawConfigDoNotOverride(t *testing.T) { + cfg := createValidTestConfig() + + overrides := &ConfigOverrides{ + ClusterInfo: clientcmdapi.Cluster{ + Server: "http://localhost:8081", + }, + Context: clientcmdapi.Context{ + Namespace: "foobar", + Cluster: "clean", + AuthInfo: "clean", + }, + AuthInfo: clientcmdapi.AuthInfo{ + Token: "modified-token", + }, + CurrentContext: "clean", + } + + cut := NewDefaultClientConfig(*cfg, overrides) + act, err := cut.RawConfig() + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if act.Clusters["clean"].Server != cfg.Clusters["clean"].Server { + t.Errorf("Expected server %v, got %v", cfg.Clusters["clean"].Server, act.Clusters["clean"].Server) + } + + if act.Contexts["clean"].Namespace != cfg.Contexts["clean"].Namespace { + t.Errorf("Expected namespace %v, got %v", cfg.Contexts["clean"].Namespace, act.Contexts["clean"].Namespace) + } +}