github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/kubernetes/context/context_test.go (about)

     1  /*
     2  Copyright 2019 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package context
    18  
    19  import (
    20  	"io/ioutil"
    21  	"sync"
    22  	"testing"
    23  
    24  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log"
    25  	"github.com/GoogleContainerTools/skaffold/testutil"
    26  )
    27  
    28  const clusterFooContext = "cluster-foo"
    29  const clusterBarContext = "cluster-bar"
    30  
    31  const validKubeConfig = `
    32  apiVersion: v1
    33  kind: Config
    34  clusters:
    35  - cluster:
    36      server: https://foo.com
    37    name: cluster-foo
    38  - cluster:
    39      server: https://bar.com
    40    name: cluster-bar
    41  contexts:
    42  - context:
    43      cluster: cluster-foo
    44      user: user1
    45    name: cluster-foo
    46  - context:
    47      cluster: cluster-bar
    48      user: user1
    49    name: cluster-bar
    50  current-context: cluster-foo
    51  users:
    52  - name: user1
    53    user:
    54      password: secret
    55      username: user
    56  `
    57  
    58  const changedKubeConfig = `
    59  apiVersion: v1
    60  kind: Config
    61  clusters:
    62  - cluster:
    63      server: https://changed-url.com
    64    name: cluster-bar
    65  contexts:
    66  - context:
    67      cluster: cluster-bar
    68      user: user-bar
    69    name: context-bar
    70  - context:
    71      cluster: cluster-bar
    72      user: user-baz
    73    name: context-baz
    74  current-context: context-baz
    75  users:
    76  - name: user1
    77    user:
    78      password: secret
    79      username: user
    80  `
    81  
    82  func TestCurrentContext(t *testing.T) {
    83  	testutil.Run(t, "valid context", func(t *testutil.T) {
    84  		resetKubeConfig(t, validKubeConfig)
    85  
    86  		config, err := CurrentConfig()
    87  
    88  		t.CheckNoError(err)
    89  		t.CheckDeepEqual(clusterFooContext, config.CurrentContext)
    90  	})
    91  
    92  	testutil.Run(t, "valid with override context", func(t *testutil.T) {
    93  		resetKubeConfig(t, validKubeConfig)
    94  
    95  		kubeContext = "cluster-bar"
    96  		config, err := CurrentConfig()
    97  
    98  		t.CheckNoError(err)
    99  		t.CheckDeepEqual(clusterBarContext, config.CurrentContext)
   100  	})
   101  
   102  	testutil.Run(t, "kubeconfig CLI flag takes precedence", func(t *testutil.T) {
   103  		resetKubeConfig(t, validKubeConfig)
   104  		kubeConfig := t.TempFile("config", []byte(changedKubeConfig))
   105  
   106  		kubeConfigFile = kubeConfig
   107  		config, err := CurrentConfig()
   108  
   109  		t.CheckNoError(err)
   110  		t.CheckDeepEqual("context-baz", config.CurrentContext)
   111  	})
   112  
   113  	testutil.Run(t, "invalid context", func(t *testutil.T) {
   114  		resetKubeConfig(t, "invalid")
   115  
   116  		_, err := CurrentConfig()
   117  
   118  		t.CheckError(true, err)
   119  	})
   120  }
   121  
   122  func TestGetRestClientConfig(t *testing.T) {
   123  	testutil.Run(t, "valid context", func(t *testutil.T) {
   124  		resetKubeConfig(t, validKubeConfig)
   125  
   126  		cfg, err := GetRestClientConfig("")
   127  
   128  		t.CheckNoError(err)
   129  		t.CheckDeepEqual("https://foo.com", cfg.Host)
   130  	})
   131  
   132  	testutil.Run(t, "valid context with override", func(t *testutil.T) {
   133  		resetKubeConfig(t, validKubeConfig)
   134  
   135  		kubeContext = clusterBarContext
   136  		cfg, err := GetRestClientConfig("")
   137  
   138  		t.CheckNoError(err)
   139  		t.CheckDeepEqual("https://bar.com", cfg.Host)
   140  	})
   141  
   142  	testutil.Run(t, "invalid context", func(t *testutil.T) {
   143  		resetKubeConfig(t, "invalid")
   144  
   145  		_, err := GetRestClientConfig("")
   146  
   147  		t.CheckError(true, err)
   148  	})
   149  
   150  	testutil.Run(t, "kube-config immutability", func(t *testutil.T) {
   151  		log.SetLevel(log.InfoLevel)
   152  		kubeConfig := t.TempFile("config", []byte(validKubeConfig))
   153  		kubeContext = clusterBarContext
   154  		t.SetEnvs(map[string]string{"KUBECONFIG": kubeConfig})
   155  		resetConfig()
   156  
   157  		cfg, err := GetRestClientConfig("")
   158  
   159  		t.CheckNoError(err)
   160  		t.CheckDeepEqual("https://bar.com", cfg.Host)
   161  
   162  		if err = ioutil.WriteFile(kubeConfig, []byte(changedKubeConfig), 0644); err != nil {
   163  			t.Error(err)
   164  		}
   165  
   166  		cfg, err = GetRestClientConfig("")
   167  
   168  		t.CheckNoError(err)
   169  		t.CheckDeepEqual("https://bar.com", cfg.Host)
   170  	})
   171  
   172  	testutil.Run(t, "change context after first execution", func(t *testutil.T) {
   173  		resetKubeConfig(t, validKubeConfig)
   174  
   175  		_, err := GetRestClientConfig("")
   176  		t.CheckNoError(err)
   177  		kubeContext = clusterBarContext
   178  		cfg, err := GetRestClientConfig("")
   179  
   180  		t.CheckNoError(err)
   181  		t.CheckDeepEqual("https://bar.com", cfg.Host)
   182  	})
   183  
   184  	testutil.Run(t, "REST client in-cluster", func(t *testutil.T) {
   185  		t.SetEnvs(map[string]string{"KUBECONFIG": "non-valid"})
   186  		resetConfig()
   187  
   188  		_, err := getRestClientConfig("", "")
   189  
   190  		if err == nil {
   191  			t.Errorf("expected error outside the cluster")
   192  		}
   193  	})
   194  }
   195  
   196  func TestUseKubeContext(t *testing.T) {
   197  	type invocation struct {
   198  		cliValue string
   199  	}
   200  	tests := []struct {
   201  		name        string
   202  		invocations []invocation
   203  		expected    string
   204  	}{
   205  		{
   206  			name:        "when not called at all",
   207  			invocations: nil,
   208  			expected:    "",
   209  		},
   210  		{
   211  			name: "first CLI value takes precedence",
   212  			invocations: []invocation{
   213  				{cliValue: "context-first"},
   214  				{cliValue: "context-second"},
   215  			},
   216  			expected: "context-first",
   217  		},
   218  	}
   219  
   220  	for _, test := range tests {
   221  		testutil.Run(t, test.name, func(t *testutil.T) {
   222  			kubeContext = ""
   223  			for _, inv := range test.invocations {
   224  				ConfigureKubeConfig("", inv.cliValue)
   225  			}
   226  
   227  			t.CheckDeepEqual(test.expected, kubeContext)
   228  			resetConfig()
   229  		})
   230  	}
   231  }
   232  
   233  // resetConfig is used by tests
   234  func resetConfig() {
   235  	kubeConfigOnce = sync.Once{}
   236  	configureOnce = sync.Once{}
   237  }
   238  
   239  func resetKubeConfig(t *testutil.T, content string) {
   240  	kubeConfig := t.TempFile("config", []byte(content))
   241  	t.SetEnvs(map[string]string{"KUBECONFIG": kubeConfig})
   242  	kubeContext = ""
   243  	kubeConfigFile = ""
   244  	resetConfig()
   245  }