...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade/postupgrade_test.go

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

     1  /*
     2  Copyright 2017 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 upgrade
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"regexp"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/pkg/errors"
    27  
    28  	errorsutil "k8s.io/apimachinery/pkg/util/errors"
    29  	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    30  	"k8s.io/kubernetes/cmd/kubeadm/app/componentconfigs"
    31  	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
    32  	"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
    33  	testutil "k8s.io/kubernetes/cmd/kubeadm/test"
    34  )
    35  
    36  func TestMoveFiles(t *testing.T) {
    37  	tmpdir := testutil.SetupTempDir(t)
    38  	defer os.RemoveAll(tmpdir)
    39  	os.Chmod(tmpdir, 0766)
    40  
    41  	certPath := filepath.Join(tmpdir, constants.APIServerCertName)
    42  	certFile, err := os.OpenFile(certPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
    43  	if err != nil {
    44  		t.Fatalf("Failed to create cert file %s: %v", certPath, err)
    45  	}
    46  	certFile.Close()
    47  
    48  	keyPath := filepath.Join(tmpdir, constants.APIServerKeyName)
    49  	keyFile, err := os.OpenFile(keyPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
    50  	if err != nil {
    51  		t.Fatalf("Failed to create key file %s: %v", keyPath, err)
    52  	}
    53  	keyFile.Close()
    54  
    55  	subDir := filepath.Join(tmpdir, "expired")
    56  	if err := os.Mkdir(subDir, 0766); err != nil {
    57  		t.Fatalf("Failed to create backup directory %s: %v", subDir, err)
    58  	}
    59  
    60  	filesToMove := map[string]string{
    61  		filepath.Join(tmpdir, constants.APIServerCertName): filepath.Join(subDir, constants.APIServerCertName),
    62  		filepath.Join(tmpdir, constants.APIServerKeyName):  filepath.Join(subDir, constants.APIServerKeyName),
    63  	}
    64  
    65  	if err := moveFiles(filesToMove); err != nil {
    66  		t.Fatalf("Failed to move files %v: %v", filesToMove, err)
    67  	}
    68  }
    69  
    70  func TestRollbackFiles(t *testing.T) {
    71  	tmpdir := testutil.SetupTempDir(t)
    72  	defer os.RemoveAll(tmpdir)
    73  	os.Chmod(tmpdir, 0766)
    74  
    75  	subDir := filepath.Join(tmpdir, "expired")
    76  	if err := os.Mkdir(subDir, 0766); err != nil {
    77  		t.Fatalf("Failed to create backup directory %s: %v", subDir, err)
    78  	}
    79  
    80  	certPath := filepath.Join(subDir, constants.APIServerCertName)
    81  	certFile, err := os.OpenFile(certPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
    82  	if err != nil {
    83  		t.Fatalf("Failed to create cert file %s: %v", certPath, err)
    84  	}
    85  	defer certFile.Close()
    86  
    87  	keyPath := filepath.Join(subDir, constants.APIServerKeyName)
    88  	keyFile, err := os.OpenFile(keyPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
    89  	if err != nil {
    90  		t.Fatalf("Failed to create key file %s: %v", keyPath, err)
    91  	}
    92  	defer keyFile.Close()
    93  
    94  	filesToRollBack := map[string]string{
    95  		filepath.Join(subDir, constants.APIServerCertName): filepath.Join(tmpdir, constants.APIServerCertName),
    96  		filepath.Join(subDir, constants.APIServerKeyName):  filepath.Join(tmpdir, constants.APIServerKeyName),
    97  	}
    98  
    99  	errString := "there are files need roll back"
   100  	originalErr := errors.New(errString)
   101  	err = rollbackFiles(filesToRollBack, originalErr)
   102  	if err == nil {
   103  		t.Fatalf("Expected error contains %q, got nil", errString)
   104  	}
   105  	if !strings.Contains(err.Error(), errString) {
   106  		t.Fatalf("Expected error contains %q, got %v", errString, err)
   107  	}
   108  }
   109  
   110  func TestWriteKubeletConfigFiles(t *testing.T) {
   111  	// exit early if the user doesn't have root permission as the test needs to create /etc/kubernetes directory
   112  	// while the permission should be granted to the user.
   113  	isPrivileged := preflight.IsPrivilegedUserCheck{}
   114  	if _, err := isPrivileged.Check(); err != nil {
   115  		return
   116  	}
   117  	testCases := []struct {
   118  		name       string
   119  		dryrun     bool
   120  		patchesDir string
   121  		errPattern string
   122  		cfg        *kubeadmapi.InitConfiguration
   123  	}{
   124  		// Be careful that if the dryrun is set to false and the test is run on a live cluster, the kubelet config file might be overwritten.
   125  		// However, you should be able to find the original config file in /etc/kubernetes/tmp/kubeadm-kubelet-configxxx folder.
   126  		// The test haven't clean up the temporary file created under /etc/kubernetes/tmp/ as that could be accidentally delete other files in
   127  		// that folder as well which might be unexpected.
   128  		{
   129  			name:   "write kubelet config file successfully",
   130  			dryrun: true,
   131  			cfg: &kubeadmapi.InitConfiguration{
   132  				ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   133  					ComponentConfigs: kubeadmapi.ComponentConfigMap{
   134  						componentconfigs.KubeletGroup: &componentConfig{},
   135  					},
   136  				},
   137  			},
   138  		},
   139  		{
   140  			name:       "aggregate errs: no kubelet config file and cannot read config file",
   141  			dryrun:     true,
   142  			errPattern: missingKubeletConfig,
   143  			cfg:        &kubeadmapi.InitConfiguration{},
   144  		},
   145  		{
   146  			name:       "only one err: patch dir does not exist",
   147  			dryrun:     true,
   148  			patchesDir: "Bogus",
   149  			errPattern: "could not list patch files for path \"Bogus\"",
   150  			cfg: &kubeadmapi.InitConfiguration{
   151  				ClusterConfiguration: kubeadmapi.ClusterConfiguration{
   152  					ComponentConfigs: kubeadmapi.ComponentConfigMap{
   153  						componentconfigs.KubeletGroup: &componentConfig{},
   154  					},
   155  				},
   156  			},
   157  		},
   158  	}
   159  	for _, tc := range testCases {
   160  		err := WriteKubeletConfigFiles(tc.cfg, tc.patchesDir, tc.dryrun, os.Stdout)
   161  		if err != nil && tc.errPattern != "" {
   162  			if match, _ := regexp.MatchString(tc.errPattern, err.Error()); !match {
   163  				t.Fatalf("Expected error contains %q, got %v", tc.errPattern, err.Error())
   164  			}
   165  		}
   166  		if err == nil && len(tc.errPattern) != 0 {
   167  			t.Fatalf("WriteKubeletConfigFiles didn't return error expected %s", tc.errPattern)
   168  		}
   169  	}
   170  }
   171  
   172  // Just some stub code, the code could be enriched when necessary.
   173  type componentConfig struct {
   174  	userSupplied bool
   175  }
   176  
   177  func (cc *componentConfig) DeepCopy() kubeadmapi.ComponentConfig {
   178  	result := &componentConfig{}
   179  	return result
   180  }
   181  
   182  func (cc *componentConfig) Marshal() ([]byte, error) {
   183  	return nil, nil
   184  }
   185  
   186  func (cc *componentConfig) Unmarshal(docmap kubeadmapi.DocumentMap) error {
   187  	return nil
   188  }
   189  
   190  func (cc *componentConfig) Get() interface{} {
   191  	return &cc
   192  }
   193  
   194  func (cc *componentConfig) Set(cfg interface{}) {
   195  }
   196  
   197  func (cc *componentConfig) Default(_ *kubeadmapi.ClusterConfiguration, _ *kubeadmapi.APIEndpoint, _ *kubeadmapi.NodeRegistrationOptions) {
   198  }
   199  
   200  func (cc *componentConfig) Mutate() error {
   201  	return nil
   202  }
   203  
   204  func (cc *componentConfig) IsUserSupplied() bool {
   205  	return false
   206  }
   207  func (cc *componentConfig) SetUserSupplied(userSupplied bool) {
   208  	cc.userSupplied = userSupplied
   209  }
   210  
   211  // moveFiles moves files from one directory to another.
   212  func moveFiles(files map[string]string) error {
   213  	filesToRecover := make(map[string]string, len(files))
   214  	for from, to := range files {
   215  		if err := os.Rename(from, to); err != nil {
   216  			return rollbackFiles(filesToRecover, err)
   217  		}
   218  		filesToRecover[to] = from
   219  	}
   220  	return nil
   221  }
   222  
   223  // rollbackFiles moves the files back to the original directory.
   224  func rollbackFiles(files map[string]string, originalErr error) error {
   225  	errs := []error{originalErr}
   226  	for from, to := range files {
   227  		if err := os.Rename(from, to); err != nil {
   228  			errs = append(errs, err)
   229  		}
   230  	}
   231  	return errors.Errorf("couldn't move these files: %v. Got errors: %v", files, errorsutil.NewAggregate(errs))
   232  }
   233  

View as plain text