Skip to content

Commit

Permalink
Merge pull request #3107 from corneliusweig/w/kubeconfig-cli-go
Browse files Browse the repository at this point in the history
Prepare cli-go to accept `--kubeconfig` setting
  • Loading branch information
tejal29 authored Oct 30, 2019
2 parents b6fa9f2 + 2790ddf commit 2c990cb
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 22 deletions.
2 changes: 1 addition & 1 deletion cmd/skaffold/app/cmd/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func createNewRunner(opts config.SkaffoldOptions) (runner.Runner, *latest.Skaffo
return nil, nil, errors.Wrap(err, "applying profiles")
}

kubectx.UseKubeContext(opts.KubeContext, config.Deploy.KubeContext)
kubectx.ConfigureKubeConfig(opts.KubeConfig, opts.KubeContext, config.Deploy.KubeContext)

if err := defaults.Set(config); err != nil {
return nil, nil, errors.Wrap(err, "setting default values")
Expand Down
1 change: 1 addition & 0 deletions pkg/skaffold/config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type SkaffoldOptions struct {
CacheFile string
Trigger string
KubeContext string
KubeConfig string
WatchPollInterval int
DefaultRepo string
CustomLabels []string
Expand Down
34 changes: 19 additions & 15 deletions pkg/skaffold/kubernetes/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,26 @@ var (
)

var (
kubeConfigOnce sync.Once
kubeConfig clientcmd.ClientConfig
kubeContextOnce sync.Once
kubeContext string
kubeConfigOnce sync.Once
kubeConfig clientcmd.ClientConfig

configureOnce sync.Once
kubeContext string
kubeConfigFile string
)

// UseKubeContext sets an override for the current context in the k8s config.
// ConfigureKubeConfig sets an override for the current context in the k8s config.
// When given, the firstCliValue always takes precedence over the yamlValue.
// Changing the kube-context of a running Skaffold process is not supported, so
// after the first call, the kube-context will be locked.
func UseKubeContext(cliValue, yamlValue string) {
newKubeContext := yamlValue
if cliValue != "" {
newKubeContext = cliValue
func ConfigureKubeConfig(cliKubeConfig, cliKubeContext, yamlKubeContext string) {
newKubeContext := yamlKubeContext
if cliKubeContext != "" {
newKubeContext = cliKubeContext
}
kubeContextOnce.Do(func() {
configureOnce.Do(func() {
kubeContext = newKubeContext
kubeConfigFile = cliKubeConfig
if kubeContext != "" {
logrus.Infof("Activated kube-context %q", kubeContext)
}
Expand All @@ -60,23 +63,23 @@ func UseKubeContext(cliValue, yamlValue string) {
}

// GetRestClientConfig returns a REST client config for API calls against the Kubernetes API.
// If UseKubeContext was called before, the CurrentContext will be overridden.
// If ConfigureKubeConfig was called before, the CurrentContext will be overridden.
// The kubeconfig used will be cached for the life of the skaffold process after the first call.
// If the CurrentContext is empty and the resulting config is empty, this method attempts to
// create a RESTClient with an in-cluster config.
func GetRestClientConfig() (*restclient.Config, error) {
return getRestClientConfig(kubeContext)
return getRestClientConfig(kubeContext, kubeConfigFile)
}

func getRestClientConfig(kctx string) (*restclient.Config, error) {
func getRestClientConfig(kctx string, kcfg string) (*restclient.Config, error) {
logrus.Debugf("getting client config for kubeContext: `%s`", kctx)
rawConfig, err := getRawKubeConfig()
if err != nil {
return nil, err
}
clientConfig := clientcmd.NewNonInteractiveClientConfig(rawConfig, kctx, &clientcmd.ConfigOverrides{CurrentContext: kctx}, nil)
restConfig, err := clientConfig.ClientConfig()
if kctx == "" && clientcmd.IsEmptyConfig(err) {
if kctx == "" && kcfg == "" && clientcmd.IsEmptyConfig(err) {
logrus.Debug("no kube-context set and no kubeConfig found, attempting in-cluster config")
restConfig, err := restclient.InClusterConfig()
return restConfig, errors.Wrap(err, "error creating REST client config in-cluster")
Expand All @@ -85,7 +88,7 @@ func getRestClientConfig(kctx string) (*restclient.Config, error) {
return restConfig, errors.Wrapf(err, "error creating REST client config for kubeContext '%s'", kctx)
}

// getCurrentConfig retrieves the kubeconfig file. If UseKubeContext was called before, the CurrentContext will be overridden.
// getCurrentConfig retrieves the kubeconfig file. If ConfigureKubeConfig was called before, the CurrentContext will be overridden.
// The result will be cached after the first call.
func getCurrentConfig() (clientcmdapi.Config, error) {
cfg, err := getRawKubeConfig()
Expand All @@ -101,6 +104,7 @@ func getCurrentConfig() (clientcmdapi.Config, error) {
func getRawKubeConfig() (clientcmdapi.Config, error) {
kubeConfigOnce.Do(func() {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
loadingRules.ExplicitPath = kubeConfigFile
kubeConfig = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{
CurrentContext: kubeContext,
})
Expand Down
28 changes: 22 additions & 6 deletions pkg/skaffold/kubernetes/context/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ clusters:
contexts:
- context:
cluster: cluster-bar
user: user1
name: cluster-bar
current-context: cluster-foo
user: user-bar
name: context-bar
- context:
cluster: cluster-bar
user: user-baz
name: context-baz
current-context: context-baz
users:
- name: user1
user:
Expand Down Expand Up @@ -96,6 +100,17 @@ func TestCurrentContext(t *testing.T) {
t.CheckDeepEqual(clusterBarContext, config.CurrentContext)
})

testutil.Run(t, "kubeconfig CLI flag takes precedence", func(t *testutil.T) {
resetKubeConfig(t, validKubeConfig)
kubeConfig := t.TempFile("config", []byte(changedKubeConfig))

kubeConfigFile = kubeConfig
config, err := CurrentConfig()

t.CheckNoError(err)
t.CheckDeepEqual("context-baz", config.CurrentContext)
})

testutil.Run(t, "invalid context", func(t *testutil.T) {
resetKubeConfig(t, "invalid")

Expand Down Expand Up @@ -172,7 +187,7 @@ func TestGetRestClientConfig(t *testing.T) {
t.SetEnvs(map[string]string{"KUBECONFIG": "non-valid"})
resetConfig()

_, err := getRestClientConfig("")
_, err := getRestClientConfig("", "")

if err == nil {
t.Errorf("expected error outside the cluster")
Expand Down Expand Up @@ -258,7 +273,7 @@ func TestUseKubeContext(t *testing.T) {
testutil.Run(t, test.name, func(t *testutil.T) {
kubeContext = ""
for _, inv := range test.invocations {
UseKubeContext(inv.cliValue, inv.yamlValue)
ConfigureKubeConfig("", inv.cliValue, inv.yamlValue)
}

t.CheckDeepEqual(test.expected, kubeContext)
Expand All @@ -270,12 +285,13 @@ func TestUseKubeContext(t *testing.T) {
// resetConfig is used by tests
func resetConfig() {
kubeConfigOnce = sync.Once{}
kubeContextOnce = sync.Once{}
configureOnce = sync.Once{}
}

func resetKubeConfig(t *testutil.T, content string) {
kubeConfig := t.TempFile("config", []byte(content))
t.SetEnvs(map[string]string{"KUBECONFIG": kubeConfig})
kubeContext = ""
kubeConfigFile = ""
resetConfig()
}

0 comments on commit 2c990cb

Please sign in to comment.