...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig

     1  /*
     2  Copyright 2018 The Kubernetes 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 kubeconfig
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"crypto"
    23  	"crypto/x509"
    24  	"fmt"
    25  	"io"
    26  	"os"
    27  	"path/filepath"
    28  	"reflect"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/lithammer/dedent"
    33  	"github.com/pkg/errors"
    34  
    35  	rbac "k8s.io/api/rbac/v1"
    36  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    37  	"k8s.io/apimachinery/pkg/runtime"
    38  	"k8s.io/apimachinery/pkg/runtime/schema"
    39  	clientset "k8s.io/client-go/kubernetes"
    40  	clientsetfake "k8s.io/client-go/kubernetes/fake"
    41  	clientgotesting "k8s.io/client-go/testing"
    42  	"k8s.io/client-go/tools/clientcmd"
    43  	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
    44  
    45  	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    46  	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
    47  	certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
    48  	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
    49  	certstestutil "k8s.io/kubernetes/cmd/kubeadm/app/util/certs"
    50  	"k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
    51  	testutil "k8s.io/kubernetes/cmd/kubeadm/test"
    52  	kubeconfigtestutil "k8s.io/kubernetes/cmd/kubeadm/test/kubeconfig"
    53  )
    54  
    55  func TestGetKubeConfigSpecsFailsIfCADoesntExists(t *testing.T) {
    56  	// Create temp folder for the test case (without a CA)
    57  	tmpdir := testutil.SetupTempDir(t)
    58  	defer os.RemoveAll(tmpdir)
    59  
    60  	// Creates an InitConfiguration pointing to the pkidir folder
    61  	cfg := &kubeadmapi.InitConfiguration{
    62  		ClusterConfiguration: kubeadmapi.ClusterConfiguration{
    63  			CertificatesDir: tmpdir,
    64  		},
    65  	}
    66  
    67  	// Executes getKubeConfigSpecs
    68  	if _, err := getKubeConfigSpecs(cfg); err == nil {
    69  		t.Error("getKubeConfigSpecs didnt failed when expected")
    70  	}
    71  }
    72  
    73  func TestGetKubeConfigSpecs(t *testing.T) {
    74  	// Create temp folder for the test case
    75  	tmpdir := testutil.SetupTempDir(t)
    76  	defer os.RemoveAll(tmpdir)
    77  
    78  	// Adds a pki folder with a ca certs to the temp folder
    79  	pkidir := testutil.SetupPkiDirWithCertificateAuthority(t, tmpdir)
    80  
    81  	// Creates InitConfigurations pointing to the pkidir folder
    82  	cfgs := []*kubeadmapi.InitConfiguration{
    83  		{
    84  			LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
    85  			ClusterConfiguration: kubeadmapi.ClusterConfiguration{
    86  				CertificatesDir: pkidir,
    87  			},
    88  			NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
    89  		},
    90  		{
    91  			LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
    92  			ClusterConfiguration: kubeadmapi.ClusterConfiguration{
    93  				ControlPlaneEndpoint: "api.k8s.io",
    94  				CertificatesDir:      pkidir,
    95  			},
    96  			NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
    97  		},
    98  		{
    99  			LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
   100  			ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   101  				ControlPlaneEndpoint: "api.k8s.io:4321",
   102  				CertificatesDir:      pkidir,
   103  			},
   104  			NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
   105  		},
   106  		{
   107  			LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
   108  			ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   109  				ControlPlaneEndpoint: "api.k8s.io",
   110  				CertificatesDir:      pkidir,
   111  			},
   112  			NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
   113  		},
   114  		{
   115  			LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
   116  			ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   117  				ControlPlaneEndpoint: "api.k8s.io:4321",
   118  				CertificatesDir:      pkidir,
   119  			},
   120  			NodeRegistration: kubeadmapi.NodeRegistrationOptions{Name: "valid-node-name"},
   121  		},
   122  	}
   123  
   124  	for i, cfg := range cfgs {
   125  		var assertions = []struct {
   126  			kubeConfigFile string
   127  			clientName     string
   128  			organizations  []string
   129  		}{
   130  			{
   131  				kubeConfigFile: kubeadmconstants.AdminKubeConfigFileName,
   132  				clientName:     "kubernetes-admin",
   133  				organizations:  []string{kubeadmconstants.ClusterAdminsGroupAndClusterRoleBinding},
   134  			},
   135  			{
   136  				kubeConfigFile: kubeadmconstants.SuperAdminKubeConfigFileName,
   137  				clientName:     "kubernetes-super-admin",
   138  				organizations:  []string{kubeadmconstants.SystemPrivilegedGroup},
   139  			},
   140  			{
   141  				kubeConfigFile: kubeadmconstants.KubeletKubeConfigFileName,
   142  				clientName:     fmt.Sprintf("%s%s", kubeadmconstants.NodesUserPrefix, cfg.NodeRegistration.Name),
   143  				organizations:  []string{kubeadmconstants.NodesGroup},
   144  			},
   145  			{
   146  				kubeConfigFile: kubeadmconstants.ControllerManagerKubeConfigFileName,
   147  				clientName:     kubeadmconstants.ControllerManagerUser,
   148  			},
   149  			{
   150  				kubeConfigFile: kubeadmconstants.SchedulerKubeConfigFileName,
   151  				clientName:     kubeadmconstants.SchedulerUser,
   152  			},
   153  		}
   154  
   155  		for _, assertion := range assertions {
   156  			t.Run(fmt.Sprintf("%d-%s", i, assertion.clientName), func(t *testing.T) {
   157  				// Executes getKubeConfigSpecs
   158  				specs, err := getKubeConfigSpecs(cfg)
   159  				if err != nil {
   160  					t.Fatal("getKubeConfigSpecs failed!")
   161  				}
   162  
   163  				var spec *kubeConfigSpec
   164  				var ok bool
   165  
   166  				// assert the spec for the kubeConfigFile exists
   167  				if spec, ok = specs[assertion.kubeConfigFile]; !ok {
   168  					t.Errorf("getKubeConfigSpecs didn't create spec for %s ", assertion.kubeConfigFile)
   169  					return
   170  				}
   171  
   172  				// Assert clientName
   173  				if spec.ClientName != assertion.clientName {
   174  					t.Errorf("getKubeConfigSpecs for %s clientName is %s, expected %s", assertion.kubeConfigFile, spec.ClientName, assertion.clientName)
   175  				}
   176  
   177  				// Assert Organizations
   178  				if spec.ClientCertAuth == nil || !reflect.DeepEqual(spec.ClientCertAuth.Organizations, assertion.organizations) {
   179  					t.Errorf("getKubeConfigSpecs for %s Organizations is %v, expected %v", assertion.kubeConfigFile, spec.ClientCertAuth.Organizations, assertion.organizations)
   180  				}
   181  
   182  				// Asserts InitConfiguration values injected into spec
   183  				controlPlaneEndpoint, err := kubeadmutil.GetControlPlaneEndpoint(cfg.ControlPlaneEndpoint, &cfg.LocalAPIEndpoint)
   184  				if err != nil {
   185  					t.Error(err)
   186  				}
   187  				localAPIEndpoint, err := kubeadmutil.GetLocalAPIEndpoint(&cfg.LocalAPIEndpoint)
   188  				if err != nil {
   189  					t.Error(err)
   190  				}
   191  
   192  				switch assertion.kubeConfigFile {
   193  				case kubeadmconstants.AdminKubeConfigFileName, kubeadmconstants.SuperAdminKubeConfigFileName, kubeadmconstants.KubeletKubeConfigFileName:
   194  					if spec.APIServer != controlPlaneEndpoint {
   195  						t.Errorf("expected getKubeConfigSpecs for %s to set cfg.APIServer to %s, got %s",
   196  							assertion.kubeConfigFile, controlPlaneEndpoint, spec.APIServer)
   197  					}
   198  				case kubeadmconstants.ControllerManagerKubeConfigFileName, kubeadmconstants.SchedulerKubeConfigFileName:
   199  					if spec.APIServer != localAPIEndpoint {
   200  						t.Errorf("expected getKubeConfigSpecs for %s to set cfg.APIServer to %s, got %s",
   201  							assertion.kubeConfigFile, localAPIEndpoint, spec.APIServer)
   202  					}
   203  				}
   204  
   205  				// Asserts CA certs and CA keys loaded into specs
   206  				if spec.CACert == nil {
   207  					t.Errorf("getKubeConfigSpecs didn't loaded CACert into spec for %s!", assertion.kubeConfigFile)
   208  				}
   209  				if spec.ClientCertAuth == nil || spec.ClientCertAuth.CAKey == nil {
   210  					t.Errorf("getKubeConfigSpecs didn't loaded CAKey into spec for %s!", assertion.kubeConfigFile)
   211  				}
   212  			})
   213  		}
   214  	}
   215  }
   216  
   217  func TestBuildKubeConfigFromSpecWithClientAuth(t *testing.T) {
   218  	// Creates a CA
   219  	caCert, caKey := certstestutil.SetupCertificateAuthority(t)
   220  
   221  	// Executes buildKubeConfigFromSpec passing a KubeConfigSpec with a ClientAuth
   222  	config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "myClientName", "test-cluster", "myOrg1", "myOrg2")
   223  
   224  	// Asserts spec data are propagated to the kubeconfig
   225  	kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
   226  	kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myClientName", "myOrg1", "myOrg2")
   227  }
   228  
   229  func TestBuildKubeConfigFromSpecWithTokenAuth(t *testing.T) {
   230  	// Creates a CA
   231  	caCert, _ := certstestutil.SetupCertificateAuthority(t)
   232  
   233  	// Executes buildKubeConfigFromSpec passing a KubeConfigSpec with a Token
   234  	config := setupdKubeConfigWithTokenAuth(t, caCert, "https://1.2.3.4:1234", "myClientName", "123456", "test-cluster")
   235  
   236  	// Asserts spec data are propagated to the kubeconfig
   237  	kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
   238  	kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myClientName", "123456")
   239  }
   240  
   241  func TestCreateKubeConfigFileIfNotExists(t *testing.T) {
   242  
   243  	// Creates a CAs
   244  	caCert, caKey := certstestutil.SetupCertificateAuthority(t)
   245  	anotherCaCert, anotherCaKey := certstestutil.SetupCertificateAuthority(t)
   246  
   247  	// build kubeconfigs (to be used to test kubeconfigs equality/not equality)
   248  	config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1", "myOrg2")
   249  	configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1", "myOrg2")
   250  	configWithAnotherClusterAddress := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://3.4.5.6:3456", "myOrg1", "test-cluster", "myOrg2")
   251  	invalidConfig := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1", "myOrg2")
   252  	invalidConfig.CurrentContext = "invalid context"
   253  
   254  	var tests = []struct {
   255  		name               string
   256  		existingKubeConfig *clientcmdapi.Config
   257  		kubeConfig         *clientcmdapi.Config
   258  		expectedError      bool
   259  	}{
   260  		{ // if there is no existing KubeConfig, creates the kubeconfig
   261  			name:       "KubeConfig doesn't exist",
   262  			kubeConfig: config,
   263  		},
   264  		{ // if KubeConfig is invalid raise error
   265  			name:               "KubeConfig is invalid",
   266  			existingKubeConfig: invalidConfig,
   267  			kubeConfig:         invalidConfig,
   268  			expectedError:      true,
   269  		},
   270  		{ // if KubeConfig is equal to the existingKubeConfig - refers to the same cluster -, use the existing (Test idempotency)
   271  			name:               "KubeConfig refers to the same cluster",
   272  			existingKubeConfig: config,
   273  			kubeConfig:         config,
   274  		},
   275  		{ // if KubeConfig is not equal to the existingKubeConfig - refers to the another cluster (a cluster with another Ca) -, raise error
   276  			name:               "KubeConfig refers to the cluster with another CA",
   277  			existingKubeConfig: config,
   278  			kubeConfig:         configWithAnotherClusterCa,
   279  			expectedError:      true,
   280  		},
   281  		{ // if KubeConfig is not equal to the existingKubeConfig - tolerate custom server addresses
   282  			name:               "KubeConfig referst to the cluster with another address",
   283  			existingKubeConfig: config,
   284  			kubeConfig:         configWithAnotherClusterAddress,
   285  		},
   286  	}
   287  
   288  	for _, test := range tests {
   289  		t.Run(test.name, func(t *testing.T) {
   290  			// Create temp folder for the test case
   291  			tmpdir := testutil.SetupTempDir(t)
   292  			defer os.RemoveAll(tmpdir)
   293  
   294  			// Writes the existing kubeconfig file to disk
   295  			if test.existingKubeConfig != nil {
   296  				if err := createKubeConfigFileIfNotExists(tmpdir, "test.conf", test.existingKubeConfig); err != nil {
   297  					t.Errorf("createKubeConfigFileIfNotExists failed")
   298  				}
   299  			}
   300  
   301  			// Writes the kubeconfig file to disk
   302  			err := createKubeConfigFileIfNotExists(tmpdir, "test.conf", test.kubeConfig)
   303  			if test.expectedError && err == nil {
   304  				t.Errorf("createKubeConfigFileIfNotExists didn't failed when expected to fail")
   305  			}
   306  			if !test.expectedError && err != nil {
   307  				t.Errorf("createKubeConfigFileIfNotExists failed")
   308  			}
   309  
   310  			// Assert that the created file is there
   311  			testutil.AssertFileExists(t, tmpdir, "test.conf")
   312  		})
   313  	}
   314  }
   315  
   316  func TestCreateKubeconfigFilesAndWrappers(t *testing.T) {
   317  	var tests = []struct {
   318  		name                     string
   319  		createKubeConfigFunction func(outDir string, cfg *kubeadmapi.InitConfiguration) error
   320  		expectedFiles            []string
   321  		expectedError            bool
   322  	}{
   323  		{ // Test createKubeConfigFiles fails for unknown kubeconfig is requested
   324  			name: "createKubeConfigFiles",
   325  			createKubeConfigFunction: func(outDir string, cfg *kubeadmapi.InitConfiguration) error {
   326  				return createKubeConfigFiles(outDir, cfg, "unknown.conf")
   327  			},
   328  			expectedError: true,
   329  		},
   330  		{ // Test CreateJoinControlPlaneKubeConfigFiles (wrapper to createKubeConfigFile)
   331  			name:                     "CreateJoinControlPlaneKubeConfigFiles",
   332  			createKubeConfigFunction: CreateJoinControlPlaneKubeConfigFiles,
   333  			expectedFiles: []string{
   334  				kubeadmconstants.AdminKubeConfigFileName,
   335  				kubeadmconstants.ControllerManagerKubeConfigFileName,
   336  				kubeadmconstants.SchedulerKubeConfigFileName,
   337  			},
   338  		},
   339  	}
   340  
   341  	for _, test := range tests {
   342  		t.Run(test.name, func(t *testing.T) {
   343  			// Create temp folder for the test case
   344  			tmpdir := testutil.SetupTempDir(t)
   345  			defer os.RemoveAll(tmpdir)
   346  
   347  			// Adds a pki folder with a ca certs to the temp folder
   348  			pkidir := testutil.SetupPkiDirWithCertificateAuthority(t, tmpdir)
   349  
   350  			// Creates an InitConfiguration pointing to the pkidir folder
   351  			cfg := &kubeadmapi.InitConfiguration{
   352  				LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
   353  				ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   354  					CertificatesDir: pkidir,
   355  				},
   356  			}
   357  
   358  			// Execs the createKubeConfigFunction
   359  			err := test.createKubeConfigFunction(tmpdir, cfg)
   360  			if test.expectedError && err == nil {
   361  				t.Errorf("createKubeConfigFunction didn't failed when expected to fail")
   362  				return
   363  			}
   364  			if !test.expectedError && err != nil {
   365  				t.Errorf("createKubeConfigFunction failed")
   366  				return
   367  			}
   368  
   369  			// Assert expected files are there
   370  			testutil.AssertFileExists(t, tmpdir, test.expectedFiles...)
   371  		})
   372  	}
   373  }
   374  
   375  func TestWriteKubeConfigFailsIfCADoesntExists(t *testing.T) {
   376  	// Temporary folders for the test case (without a CA)
   377  	tmpdir := testutil.SetupTempDir(t)
   378  	defer os.RemoveAll(tmpdir)
   379  
   380  	// Creates an InitConfiguration pointing to the tmpdir folder
   381  	cfg := &kubeadmapi.InitConfiguration{
   382  		ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   383  			CertificatesDir: tmpdir,
   384  		},
   385  	}
   386  
   387  	var tests = []struct {
   388  		name                    string
   389  		writeKubeConfigFunction func(out io.Writer) error
   390  	}{
   391  		{
   392  			name: "WriteKubeConfigWithClientCert",
   393  			writeKubeConfigFunction: func(out io.Writer) error {
   394  				return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"}, nil)
   395  			},
   396  		},
   397  		{
   398  			name: "WriteKubeConfigWithToken",
   399  			writeKubeConfigFunction: func(out io.Writer) error {
   400  				return WriteKubeConfigWithToken(out, cfg, "myUser", "12345", nil)
   401  			},
   402  		},
   403  	}
   404  
   405  	for _, test := range tests {
   406  		t.Run(test.name, func(t *testing.T) {
   407  			buf := new(bytes.Buffer)
   408  
   409  			// executes writeKubeConfigFunction
   410  			if err := test.writeKubeConfigFunction(buf); err == nil {
   411  				t.Error("writeKubeConfigFunction didnt failed when expected")
   412  			}
   413  		})
   414  	}
   415  }
   416  
   417  func TestWriteKubeConfig(t *testing.T) {
   418  	// Temporary folders for the test case
   419  	tmpdir := testutil.SetupTempDir(t)
   420  	defer os.RemoveAll(tmpdir)
   421  
   422  	// Adds a pki folder with a ca cert to the temp folder
   423  	pkidir := testutil.SetupPkiDirWithCertificateAuthority(t, tmpdir)
   424  
   425  	// Retrieves ca cert for assertions
   426  	caCert, _, err := pkiutil.TryLoadCertAndKeyFromDisk(pkidir, kubeadmconstants.CACertAndKeyBaseName)
   427  	if err != nil {
   428  		t.Fatalf("couldn't retrieve ca cert: %v", err)
   429  	}
   430  
   431  	// Creates an InitConfiguration pointing to the pkidir folder
   432  	cfg := &kubeadmapi.InitConfiguration{
   433  		LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "1.2.3.4", BindPort: 1234},
   434  		ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   435  			CertificatesDir: pkidir,
   436  		},
   437  	}
   438  
   439  	var tests = []struct {
   440  		name                    string
   441  		writeKubeConfigFunction func(out io.Writer) error
   442  		withClientCert          bool
   443  		withToken               bool
   444  	}{
   445  		{
   446  			name: "WriteKubeConfigWithClientCert",
   447  			writeKubeConfigFunction: func(out io.Writer) error {
   448  				return WriteKubeConfigWithClientCert(out, cfg, "myUser", []string{"myOrg"}, nil)
   449  			},
   450  			withClientCert: true,
   451  		},
   452  		{
   453  			name: "WriteKubeConfigWithToken",
   454  			writeKubeConfigFunction: func(out io.Writer) error {
   455  				return WriteKubeConfigWithToken(out, cfg, "myUser", "12345", nil)
   456  			},
   457  			withToken: true,
   458  		},
   459  	}
   460  
   461  	for _, test := range tests {
   462  		t.Run(test.name, func(t *testing.T) {
   463  			buf := new(bytes.Buffer)
   464  
   465  			// executes writeKubeConfigFunction
   466  			if err := test.writeKubeConfigFunction(buf); err != nil {
   467  				t.Error("writeKubeConfigFunction failed")
   468  				return
   469  			}
   470  
   471  			// reads kubeconfig written to stdout
   472  			config, err := clientcmd.Load(buf.Bytes())
   473  			if err != nil {
   474  				t.Errorf("Couldn't read kubeconfig file from buffer: %v", err)
   475  				return
   476  			}
   477  
   478  			// checks that CLI flags are properly propagated
   479  			kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
   480  
   481  			if test.withClientCert {
   482  				// checks that kubeconfig files have expected client cert
   483  				kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithClientCert(t, config, caCert, "myUser", "myOrg")
   484  			}
   485  
   486  			if test.withToken {
   487  				// checks that kubeconfig files have expected token
   488  				kubeconfigtestutil.AssertKubeConfigCurrentAuthInfoWithToken(t, config, "myUser", "12345")
   489  			}
   490  		})
   491  	}
   492  }
   493  
   494  func TestValidateKubeConfig(t *testing.T) {
   495  	caCert, caKey := certstestutil.SetupCertificateAuthority(t)
   496  	anotherCaCert, anotherCaKey := certstestutil.SetupCertificateAuthority(t)
   497  
   498  	config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
   499  	configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
   500  	configWithAnotherServerURL := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://4.3.2.1:4321", "test-cluster", "myOrg1")
   501  
   502  	configWithSameClusterCaByExternalFile := config.DeepCopy()
   503  	currentCtx, exists := configWithSameClusterCaByExternalFile.Contexts[configWithSameClusterCaByExternalFile.CurrentContext]
   504  	if !exists {
   505  		t.Fatal("failed to find CurrentContext in Contexts of the kubeconfig")
   506  	}
   507  	if configWithSameClusterCaByExternalFile.Clusters[currentCtx.Cluster] == nil {
   508  		t.Fatal("failed to find the given CurrentContext Cluster in Clusters of the kubeconfig")
   509  	}
   510  	tmpfile, err := os.CreateTemp("", "external-ca.crt")
   511  	if err != nil {
   512  		t.Fatal(err)
   513  	}
   514  	defer os.Remove(tmpfile.Name())
   515  	if _, err := tmpfile.Write(pkiutil.EncodeCertPEM(caCert)); err != nil {
   516  		t.Fatal(err)
   517  	}
   518  	configWithSameClusterCaByExternalFile.Clusters[currentCtx.Cluster].CertificateAuthorityData = nil
   519  	configWithSameClusterCaByExternalFile.Clusters[currentCtx.Cluster].CertificateAuthority = tmpfile.Name()
   520  
   521  	// create a valid config but with whitespace around the CA PEM.
   522  	// validateKubeConfig() should tolerate that.
   523  	configWhitespace := config.DeepCopy()
   524  	configWhitespaceCtx := configWhitespace.Contexts[configWhitespace.CurrentContext]
   525  	configWhitespaceCA := string(configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData)
   526  	configWhitespaceCA = "\n" + configWhitespaceCA + "\n"
   527  	configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData = []byte(configWhitespaceCA)
   528  
   529  	tests := map[string]struct {
   530  		existingKubeConfig *clientcmdapi.Config
   531  		kubeConfig         *clientcmdapi.Config
   532  		expectedError      bool
   533  	}{
   534  		"kubeconfig don't exist": {
   535  			kubeConfig:    config,
   536  			expectedError: true,
   537  		},
   538  		"kubeconfig exist and has invalid ca": {
   539  			existingKubeConfig: configWithAnotherClusterCa,
   540  			kubeConfig:         config,
   541  			expectedError:      true,
   542  		},
   543  		"kubeconfig exist and has a different server url": {
   544  			existingKubeConfig: configWithAnotherServerURL,
   545  			kubeConfig:         config,
   546  		},
   547  		"kubeconfig exist and is valid": {
   548  			existingKubeConfig: config,
   549  			kubeConfig:         config,
   550  			expectedError:      false,
   551  		},
   552  		"kubeconfig exist and is valid even if its CA contains whitespace": {
   553  			existingKubeConfig: configWhitespace,
   554  			kubeConfig:         config,
   555  			expectedError:      false,
   556  		},
   557  		"kubeconfig exist and is valid even if its CA is provided as an external file": {
   558  			existingKubeConfig: configWithSameClusterCaByExternalFile,
   559  			kubeConfig:         config,
   560  			expectedError:      false,
   561  		},
   562  	}
   563  
   564  	for name, test := range tests {
   565  		t.Run(name, func(t *testing.T) {
   566  			tmpdir := testutil.SetupTempDir(t)
   567  			defer os.RemoveAll(tmpdir)
   568  
   569  			if test.existingKubeConfig != nil {
   570  				if err := createKubeConfigFileIfNotExists(tmpdir, "test.conf", test.existingKubeConfig); err != nil {
   571  					t.Errorf("createKubeConfigFileIfNotExists failed")
   572  				}
   573  			}
   574  
   575  			err := validateKubeConfig(tmpdir, "test.conf", test.kubeConfig)
   576  			if (err != nil) != test.expectedError {
   577  				t.Fatalf(dedent.Dedent(
   578  					"validateKubeConfig failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"),
   579  					name,
   580  					test.expectedError,
   581  					(err != nil),
   582  					err,
   583  				)
   584  			}
   585  		})
   586  	}
   587  }
   588  
   589  func TestValidateKubeconfigsForExternalCA(t *testing.T) {
   590  	tmpDir := testutil.SetupTempDir(t)
   591  	defer os.RemoveAll(tmpDir)
   592  	pkiDir := filepath.Join(tmpDir, "pki")
   593  
   594  	initConfig := &kubeadmapi.InitConfiguration{
   595  		ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   596  			CertificatesDir: pkiDir,
   597  		},
   598  		LocalAPIEndpoint: kubeadmapi.APIEndpoint{
   599  			BindPort:         1234,
   600  			AdvertiseAddress: "1.2.3.4",
   601  		},
   602  	}
   603  
   604  	// creates CA, write to pkiDir and remove ca.key to get into external CA condition
   605  	caCert, caKey := certstestutil.SetupCertificateAuthority(t)
   606  	if err := pkiutil.WriteCertAndKey(pkiDir, kubeadmconstants.CACertAndKeyBaseName, caCert, caKey); err != nil {
   607  		t.Fatalf("failure while saving CA certificate and key: %v", err)
   608  	}
   609  	if err := os.Remove(filepath.Join(pkiDir, kubeadmconstants.CAKeyName)); err != nil {
   610  		t.Fatalf("failure while deleting ca.key: %v", err)
   611  	}
   612  
   613  	// create a valid config
   614  	config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
   615  
   616  	// create a config with another CA
   617  	anotherCaCert, anotherCaKey := certstestutil.SetupCertificateAuthority(t)
   618  	configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
   619  
   620  	// create a config with another server URL
   621  	configWithAnotherServerURL := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://4.3.2.1:4321", "test-cluster", "myOrg1")
   622  
   623  	tests := map[string]struct {
   624  		filesToWrite  map[string]*clientcmdapi.Config
   625  		initConfig    *kubeadmapi.InitConfiguration
   626  		expectedError bool
   627  	}{
   628  		"files don't exist": {
   629  			initConfig:    initConfig,
   630  			expectedError: true,
   631  		},
   632  		"some files don't exist": {
   633  			filesToWrite: map[string]*clientcmdapi.Config{
   634  				kubeadmconstants.AdminKubeConfigFileName:      config,
   635  				kubeadmconstants.SuperAdminKubeConfigFileName: config,
   636  				kubeadmconstants.KubeletKubeConfigFileName:    config,
   637  			},
   638  			initConfig:    initConfig,
   639  			expectedError: true,
   640  		},
   641  		"some files have invalid CA": {
   642  			filesToWrite: map[string]*clientcmdapi.Config{
   643  				kubeadmconstants.AdminKubeConfigFileName:             config,
   644  				kubeadmconstants.SuperAdminKubeConfigFileName:        config,
   645  				kubeadmconstants.KubeletKubeConfigFileName:           config,
   646  				kubeadmconstants.ControllerManagerKubeConfigFileName: configWithAnotherClusterCa,
   647  				kubeadmconstants.SchedulerKubeConfigFileName:         config,
   648  			},
   649  			initConfig:    initConfig,
   650  			expectedError: true,
   651  		},
   652  		"some files have a different Server URL": {
   653  			filesToWrite: map[string]*clientcmdapi.Config{
   654  				kubeadmconstants.AdminKubeConfigFileName:             config,
   655  				kubeadmconstants.SuperAdminKubeConfigFileName:        config,
   656  				kubeadmconstants.KubeletKubeConfigFileName:           config,
   657  				kubeadmconstants.ControllerManagerKubeConfigFileName: config,
   658  				kubeadmconstants.SchedulerKubeConfigFileName:         configWithAnotherServerURL,
   659  			},
   660  			initConfig: initConfig,
   661  		},
   662  		"all files are valid": {
   663  			filesToWrite: map[string]*clientcmdapi.Config{
   664  				kubeadmconstants.AdminKubeConfigFileName:             config,
   665  				kubeadmconstants.SuperAdminKubeConfigFileName:        config,
   666  				kubeadmconstants.KubeletKubeConfigFileName:           config,
   667  				kubeadmconstants.ControllerManagerKubeConfigFileName: config,
   668  				kubeadmconstants.SchedulerKubeConfigFileName:         config,
   669  			},
   670  			initConfig:    initConfig,
   671  			expectedError: false,
   672  		},
   673  	}
   674  
   675  	for name, test := range tests {
   676  		t.Run(name, func(t *testing.T) {
   677  			tmpdir := testutil.SetupTempDir(t)
   678  			defer os.RemoveAll(tmpdir)
   679  
   680  			for name, config := range test.filesToWrite {
   681  				if err := createKubeConfigFileIfNotExists(tmpdir, name, config); err != nil {
   682  					t.Errorf("createKubeConfigFileIfNotExists failed: %v", err)
   683  				}
   684  			}
   685  
   686  			err := ValidateKubeconfigsForExternalCA(tmpdir, test.initConfig)
   687  			if (err != nil) != test.expectedError {
   688  				t.Fatalf(dedent.Dedent(
   689  					"ValidateKubeconfigsForExternalCA failed\n%s\nexpected error: %t\n\tgot: %t\nerror: %v"),
   690  					name,
   691  					test.expectedError,
   692  					(err != nil),
   693  					err,
   694  				)
   695  			}
   696  		})
   697  	}
   698  }
   699  
   700  // setupdKubeConfigWithClientAuth is a test utility function that wraps buildKubeConfigFromSpec for building a KubeConfig object With ClientAuth
   701  func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKey crypto.Signer, APIServer, clientName, clustername string, organizations ...string) *clientcmdapi.Config {
   702  	spec := &kubeConfigSpec{
   703  		CACert:     caCert,
   704  		APIServer:  APIServer,
   705  		ClientName: clientName,
   706  		ClientCertAuth: &clientCertAuth{
   707  			CAKey:         caKey,
   708  			Organizations: organizations,
   709  		},
   710  	}
   711  
   712  	config, err := buildKubeConfigFromSpec(spec, clustername, nil)
   713  	if err != nil {
   714  		t.Fatal("buildKubeConfigFromSpec failed!")
   715  	}
   716  
   717  	return config
   718  }
   719  
   720  // setupdKubeConfigWithClientAuth is a test utility function that wraps buildKubeConfigFromSpec for building a KubeConfig object With Token
   721  func setupdKubeConfigWithTokenAuth(t *testing.T, caCert *x509.Certificate, APIServer, clientName, token, clustername string) *clientcmdapi.Config {
   722  	spec := &kubeConfigSpec{
   723  		CACert:     caCert,
   724  		APIServer:  APIServer,
   725  		ClientName: clientName,
   726  		TokenAuth: &tokenAuth{
   727  			Token: token,
   728  		},
   729  	}
   730  
   731  	config, err := buildKubeConfigFromSpec(spec, clustername, nil)
   732  	if err != nil {
   733  		t.Fatal("buildKubeConfigFromSpec failed!")
   734  	}
   735  
   736  	return config
   737  }
   738  
   739  func TestEnsureAdminClusterRoleBinding(t *testing.T) {
   740  	dir := testutil.SetupTempDir(t)
   741  	defer os.RemoveAll(dir)
   742  
   743  	cfg := testutil.GetDefaultInternalConfig(t)
   744  	cfg.CertificatesDir = dir
   745  
   746  	ca := certsphase.KubeadmCertRootCA()
   747  	_, _, err := ca.CreateAsCA(cfg)
   748  	if err != nil {
   749  		t.Fatal(err)
   750  	}
   751  
   752  	tests := []struct {
   753  		name                  string
   754  		expectedRBACError     bool
   755  		expectedError         bool
   756  		missingAdminConf      bool
   757  		missingSuperAdminConf bool
   758  	}{
   759  		{
   760  			name: "no errors",
   761  		},
   762  		{
   763  			name:              "expect RBAC error",
   764  			expectedRBACError: true,
   765  			expectedError:     true,
   766  		},
   767  		{
   768  			name:             "admin.conf is missing",
   769  			missingAdminConf: true,
   770  			expectedError:    true,
   771  		},
   772  		{
   773  			name:                  "super-admin.conf is missing",
   774  			missingSuperAdminConf: true,
   775  			expectedError:         false, // The file is optional.
   776  		},
   777  	}
   778  
   779  	for _, tc := range tests {
   780  		t.Run(tc.name, func(t *testing.T) {
   781  			ensureRBACFunc := func(_ context.Context, adminClient clientset.Interface, superAdminClient clientset.Interface,
   782  				_ time.Duration, _ time.Duration) (clientset.Interface, error) {
   783  
   784  				if tc.expectedRBACError {
   785  					return nil, errors.New("ensureRBACFunc error")
   786  				}
   787  				return adminClient, nil
   788  			}
   789  
   790  			// Create the admin.conf and super-admin.conf so that EnsureAdminClusterRoleBinding
   791  			// can create clients from the files.
   792  			os.Remove(filepath.Join(dir, kubeadmconstants.AdminKubeConfigFileName))
   793  			if !tc.missingAdminConf {
   794  				if err := CreateKubeConfigFile(kubeadmconstants.AdminKubeConfigFileName, dir, cfg); err != nil {
   795  					t.Fatal(err)
   796  				}
   797  			}
   798  			os.Remove(filepath.Join(dir, kubeadmconstants.SuperAdminKubeConfigFileName))
   799  			if !tc.missingSuperAdminConf {
   800  				if err := CreateKubeConfigFile(kubeadmconstants.SuperAdminKubeConfigFileName, dir, cfg); err != nil {
   801  					t.Fatal(err)
   802  				}
   803  			}
   804  
   805  			client, err := EnsureAdminClusterRoleBinding(dir, ensureRBACFunc)
   806  			if (err != nil) != tc.expectedError {
   807  				t.Fatalf("expected error: %v, got: %v, error: %v", err != nil, tc.expectedError, err)
   808  			}
   809  
   810  			if err == nil && client == nil {
   811  				t.Fatal("got nil client")
   812  			}
   813  		})
   814  	}
   815  }
   816  
   817  func TestEnsureAdminClusterRoleBindingImpl(t *testing.T) {
   818  	tests := []struct {
   819  		name                  string
   820  		setupAdminClient      func(*clientsetfake.Clientset)
   821  		setupSuperAdminClient func(*clientsetfake.Clientset)
   822  		expectedError         bool
   823  	}{
   824  		{
   825  			name: "admin.conf: handle forbidden errors when the super-admin.conf client is nil",
   826  			setupAdminClient: func(client *clientsetfake.Clientset) {
   827  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   828  					return true, nil, apierrors.NewForbidden(
   829  						schema.GroupResource{}, "name", errors.New(""))
   830  				})
   831  			},
   832  			expectedError: true,
   833  		},
   834  		{
   835  			// A "create" call against a real server can return a forbidden error and a non-nil CRB
   836  			name: "admin.conf: handle forbidden error and returned CRBs, when the super-admin.conf client is nil",
   837  			setupAdminClient: func(client *clientsetfake.Clientset) {
   838  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   839  					return true, &rbac.ClusterRoleBinding{}, apierrors.NewForbidden(
   840  						schema.GroupResource{}, "name", errors.New(""))
   841  				})
   842  			},
   843  			expectedError: true,
   844  		},
   845  		{
   846  			name: "admin.conf: CRB already exists, use the admin.conf client",
   847  			setupAdminClient: func(client *clientsetfake.Clientset) {
   848  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   849  					return true, nil, apierrors.NewAlreadyExists(
   850  						schema.GroupResource{}, "name")
   851  				})
   852  			},
   853  			setupSuperAdminClient: func(client *clientsetfake.Clientset) {
   854  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   855  					return true, nil, apierrors.NewAlreadyExists(
   856  						schema.GroupResource{}, "name")
   857  				})
   858  			},
   859  			expectedError: false,
   860  		},
   861  		{
   862  			name: "admin.conf: handle other errors, such as a server timeout",
   863  			setupAdminClient: func(client *clientsetfake.Clientset) {
   864  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   865  					return true, nil, apierrors.NewServerTimeout(
   866  						schema.GroupResource{}, "create", 0)
   867  				})
   868  			},
   869  			expectedError: true,
   870  		},
   871  		{
   872  			name: "admin.conf: CRB exists, return a client from admin.conf",
   873  			setupAdminClient: func(client *clientsetfake.Clientset) {
   874  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   875  					return true, &rbac.ClusterRoleBinding{}, nil
   876  				})
   877  			},
   878  			expectedError: false,
   879  		},
   880  		{
   881  			name: "super-admin.conf: error while creating CRB",
   882  			setupAdminClient: func(client *clientsetfake.Clientset) {
   883  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   884  					return true, nil, apierrors.NewForbidden(
   885  						schema.GroupResource{}, "name", errors.New(""))
   886  				})
   887  			},
   888  			setupSuperAdminClient: func(client *clientsetfake.Clientset) {
   889  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   890  					return true, nil, apierrors.NewServerTimeout(
   891  						schema.GroupResource{}, "create", 0)
   892  				})
   893  			},
   894  			expectedError: true,
   895  		},
   896  		{
   897  			name: "super-admin.conf: admin.conf cannot create CRB, create CRB with super-admin.conf, return client from admin.conf",
   898  			setupAdminClient: func(client *clientsetfake.Clientset) {
   899  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   900  					return true, nil, apierrors.NewForbidden(
   901  						schema.GroupResource{}, "name", errors.New(""))
   902  				})
   903  			},
   904  			setupSuperAdminClient: func(client *clientsetfake.Clientset) {
   905  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   906  					return true, &rbac.ClusterRoleBinding{}, nil
   907  				})
   908  			},
   909  			expectedError: false,
   910  		},
   911  		{
   912  			name: "super-admin.conf: admin.conf cannot create CRB, try to create CRB with super-admin.conf, encounter 'already exists' error",
   913  			setupAdminClient: func(client *clientsetfake.Clientset) {
   914  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   915  					return true, nil, apierrors.NewForbidden(
   916  						schema.GroupResource{}, "name", errors.New(""))
   917  				})
   918  			},
   919  			setupSuperAdminClient: func(client *clientsetfake.Clientset) {
   920  				client.PrependReactor("create", "clusterrolebindings", func(action clientgotesting.Action) (bool, runtime.Object, error) {
   921  					return true, nil, apierrors.NewAlreadyExists(
   922  						schema.GroupResource{}, "name")
   923  				})
   924  			},
   925  			expectedError: false,
   926  		},
   927  	}
   928  
   929  	for _, tc := range tests {
   930  		t.Run(tc.name, func(t *testing.T) {
   931  			adminClient := clientsetfake.NewSimpleClientset()
   932  			tc.setupAdminClient(adminClient)
   933  
   934  			var superAdminClient clientset.Interface // ensure superAdminClient is nil by default
   935  			if tc.setupSuperAdminClient != nil {
   936  				fakeSuperAdminClient := clientsetfake.NewSimpleClientset()
   937  				tc.setupSuperAdminClient(fakeSuperAdminClient)
   938  				superAdminClient = fakeSuperAdminClient
   939  			}
   940  
   941  			client, err := EnsureAdminClusterRoleBindingImpl(
   942  				context.Background(), adminClient, superAdminClient, 0, 0)
   943  			if (err != nil) != tc.expectedError {
   944  				t.Fatalf("expected error: %v, got %v, error: %v", tc.expectedError, err != nil, err)
   945  			}
   946  
   947  			if err == nil && client == nil {
   948  				t.Fatal("got nil client")
   949  			}
   950  		})
   951  	}
   952  }
   953  
   954  func TestCreateKubeConfigAndCSR(t *testing.T) {
   955  	tmpDir := testutil.SetupTempDir(t)
   956  	testutil.SetupEmptyFiles(t, tmpDir, "testfile", "bar.csr", "bar.key")
   957  	defer func() {
   958  		if err := os.RemoveAll(tmpDir); err != nil {
   959  			t.Error(err)
   960  		}
   961  	}()
   962  	caCert, caKey := certstestutil.SetupCertificateAuthority(t)
   963  
   964  	type args struct {
   965  		kubeConfigDir string
   966  		kubeadmConfig *kubeadmapi.InitConfiguration
   967  		name          string
   968  		spec          *kubeConfigSpec
   969  	}
   970  	tests := []struct {
   971  		name          string
   972  		args          args
   973  		expectedError bool
   974  	}{
   975  		{
   976  			name: "kubeadmConfig is nil",
   977  			args: args{
   978  				kubeConfigDir: tmpDir,
   979  				kubeadmConfig: nil,
   980  				name:          "foo",
   981  				spec: &kubeConfigSpec{
   982  					CACert:         caCert,
   983  					APIServer:      "10.0.0.1",
   984  					ClientName:     "foo",
   985  					TokenAuth:      &tokenAuth{Token: "test"},
   986  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
   987  				},
   988  			},
   989  			expectedError: true,
   990  		},
   991  		{
   992  			name: "The kubeConfigDir is empty",
   993  			args: args{
   994  				kubeConfigDir: "",
   995  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
   996  				name:          "foo",
   997  				spec: &kubeConfigSpec{
   998  					CACert:         caCert,
   999  					APIServer:      "10.0.0.1",
  1000  					ClientName:     "foo",
  1001  					TokenAuth:      &tokenAuth{Token: "test"},
  1002  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
  1003  				},
  1004  			},
  1005  			expectedError: true,
  1006  		},
  1007  		{
  1008  			name: "The name is empty",
  1009  			args: args{
  1010  				kubeConfigDir: tmpDir,
  1011  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1012  				name:          "",
  1013  				spec: &kubeConfigSpec{
  1014  					CACert:         caCert,
  1015  					APIServer:      "10.0.0.1",
  1016  					ClientName:     "foo",
  1017  					TokenAuth:      &tokenAuth{Token: "test"},
  1018  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
  1019  				},
  1020  			},
  1021  			expectedError: true,
  1022  		},
  1023  		{
  1024  			name: "The spec is empty",
  1025  			args: args{
  1026  				kubeConfigDir: tmpDir,
  1027  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1028  				name:          "foo",
  1029  				spec:          nil,
  1030  			},
  1031  			expectedError: true,
  1032  		},
  1033  		{
  1034  			name: "The kubeconfig file already exists",
  1035  			args: args{
  1036  				kubeConfigDir: tmpDir,
  1037  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1038  				name:          "testfile",
  1039  				spec: &kubeConfigSpec{
  1040  					CACert:         caCert,
  1041  					APIServer:      "10.0.0.1",
  1042  					ClientName:     "foo",
  1043  					TokenAuth:      &tokenAuth{Token: "test"},
  1044  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
  1045  				},
  1046  			},
  1047  			expectedError: true,
  1048  		},
  1049  		{
  1050  			name: "The CSR or key files already exists",
  1051  			args: args{
  1052  				kubeConfigDir: tmpDir,
  1053  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1054  				name:          "bar",
  1055  				spec: &kubeConfigSpec{
  1056  					CACert:         caCert,
  1057  					APIServer:      "10.0.0.1",
  1058  					ClientName:     "foo",
  1059  					TokenAuth:      &tokenAuth{Token: "test"},
  1060  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
  1061  				},
  1062  			},
  1063  			expectedError: true,
  1064  		},
  1065  		{
  1066  			name: "configuration is valid, expect no errors",
  1067  			args: args{
  1068  				kubeConfigDir: tmpDir,
  1069  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1070  				name:          "test",
  1071  				spec: &kubeConfigSpec{
  1072  					CACert:         caCert,
  1073  					APIServer:      "10.0.0.1",
  1074  					ClientName:     "foo",
  1075  					TokenAuth:      &tokenAuth{Token: "test"},
  1076  					ClientCertAuth: &clientCertAuth{CAKey: caKey},
  1077  				},
  1078  			},
  1079  			expectedError: false,
  1080  		},
  1081  	}
  1082  	for _, tc := range tests {
  1083  		t.Run(tc.name, func(t *testing.T) {
  1084  			if err := createKubeConfigAndCSR(tc.args.kubeConfigDir, tc.args.kubeadmConfig, tc.args.name, tc.args.spec); (err != nil) != tc.expectedError {
  1085  				t.Errorf("createKubeConfigAndCSR() error = %v, wantErr %v", err, tc.expectedError)
  1086  			}
  1087  		})
  1088  	}
  1089  }
  1090  
  1091  func TestCreateDefaultKubeConfigsAndCSRFiles(t *testing.T) {
  1092  	tmpDir := testutil.SetupTempDir(t)
  1093  	defer func() {
  1094  		if err := os.RemoveAll(tmpDir); err != nil {
  1095  			t.Error(err)
  1096  		}
  1097  	}()
  1098  	type args struct {
  1099  		kubeConfigDir string
  1100  		kubeadmConfig *kubeadmapi.InitConfiguration
  1101  	}
  1102  	tests := []struct {
  1103  		name    string
  1104  		args    args
  1105  		wantErr bool
  1106  	}{
  1107  		{
  1108  			name: "kubeadmConfig is empty",
  1109  			args: args{
  1110  				kubeConfigDir: tmpDir,
  1111  				kubeadmConfig: &kubeadmapi.InitConfiguration{},
  1112  			},
  1113  			wantErr: true,
  1114  		},
  1115  		{
  1116  			name: "The APIEndpoint is invalid",
  1117  			args: args{
  1118  				kubeConfigDir: tmpDir,
  1119  				kubeadmConfig: &kubeadmapi.InitConfiguration{
  1120  					LocalAPIEndpoint: kubeadmapi.APIEndpoint{
  1121  						AdvertiseAddress: "x.12.FOo.1",
  1122  						BindPort:         6443,
  1123  					},
  1124  				},
  1125  			},
  1126  			wantErr: true,
  1127  		},
  1128  		{
  1129  			name: "The APIEndpoint is valid",
  1130  			args: args{
  1131  				kubeConfigDir: tmpDir,
  1132  				kubeadmConfig: &kubeadmapi.InitConfiguration{
  1133  					LocalAPIEndpoint: kubeadmapi.APIEndpoint{
  1134  						AdvertiseAddress: "127.0.0.1",
  1135  						BindPort:         6443,
  1136  					},
  1137  				},
  1138  			},
  1139  			wantErr: false,
  1140  		},
  1141  	}
  1142  	for _, tc := range tests {
  1143  		t.Run(tc.name, func(t *testing.T) {
  1144  			out := &bytes.Buffer{}
  1145  			if err := CreateDefaultKubeConfigsAndCSRFiles(out, tc.args.kubeConfigDir, tc.args.kubeadmConfig); (err != nil) != tc.wantErr {
  1146  				t.Errorf("CreateDefaultKubeConfigsAndCSRFiles() error = %v, wantErr %v", err, tc.wantErr)
  1147  				return
  1148  			}
  1149  		})
  1150  	}
  1151  }
  1152  

View as plain text