github.com/SUSE/skuba@v1.4.17/pkg/skuba/actions/cluster/init/init_test.go (about) 1 /* 2 * Copyright (c) 2019 SUSE LLC. 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 18 package cluster 19 20 import ( 21 "fmt" 22 "io/ioutil" 23 "os" 24 "path/filepath" 25 "testing" 26 27 "github.com/SUSE/skuba/internal/pkg/skuba/node" 28 constants "github.com/SUSE/skuba/pkg/skuba" 29 ) 30 31 type TestFilesystemContext struct { 32 WorkDirectory string 33 OldWorkDirectory string 34 } 35 36 func TestInitCloudProvider(t *testing.T) { 37 tests := []struct { 38 name string 39 cloudProvider string 40 providerReadmeFiles []string 41 }{ 42 { 43 name: "init with no cloud provider", 44 cloudProvider: "", 45 providerReadmeFiles: []string{ 46 constants.CloudReadmeFile(), 47 }, 48 }, 49 { 50 name: "init with aws cloud provider", 51 cloudProvider: "aws", 52 providerReadmeFiles: []string{ 53 constants.CloudReadmeFile(), 54 constants.AWSReadmeFile(), 55 }, 56 }, 57 { 58 name: "init with opendstack cloud provider", 59 cloudProvider: "openstack", 60 providerReadmeFiles: []string{ 61 constants.CloudReadmeFile(), 62 constants.OpenstackReadmeFile(), 63 }, 64 }, 65 { 66 name: "init with vsphere cloud provider", 67 cloudProvider: "vsphere", 68 providerReadmeFiles: []string{ 69 constants.CloudReadmeFile(), 70 constants.VSphereReadmeFile(), 71 }, 72 }, 73 } 74 75 clusterName := "testCluster" 76 controlPlane := "http://k8s.example.com" 77 k8sDesiredVersion := "" 78 strictCapDefaults := true 79 initConfig := "kubeadm-init.conf" 80 joinFiles := []string{ 81 filepath.Join("kubeadm-join.conf.d", "master.conf.template"), 82 filepath.Join("kubeadm-join.conf.d", "worker.conf.template"), 83 } 84 for _, tt := range tests { 85 tt := tt // Parallel testing 86 t.Run(tt.name, func(t *testing.T) { 87 initConf, err := NewInitConfiguration( 88 clusterName, 89 tt.cloudProvider, 90 controlPlane, 91 k8sDesiredVersion, 92 strictCapDefaults) 93 if err != nil { 94 t.Errorf("unexpected error: %v", err) 95 } 96 97 ctx, err := switchToTemporaryDirectory() 98 if err != nil { 99 t.Errorf("unexpect error: %v", err) 100 } 101 defer switchBackAndCleanFilesystem(ctx) 102 103 if err = Init(initConf); err != nil { 104 t.Errorf("unexpect error: %v", err) 105 } 106 107 switch tt.cloudProvider { 108 case "": 109 for _, file := range tt.providerReadmeFiles { 110 found, err := doesFileExist(ctx, clusterName, file) 111 if err != nil { 112 t.Errorf("unexpected error while checking %s presence: %v", 113 file, err) 114 } 115 if found { 116 t.Errorf("unexpected file %s found", file) 117 } 118 } 119 default: 120 for _, file := range tt.providerReadmeFiles { 121 found, err := doesFileExist(ctx, clusterName, file) 122 if err != nil { 123 t.Errorf("unexpected error while checking %s presence: %v", 124 file, err) 125 } 126 if !found { 127 t.Errorf("expected %s to exist", file) 128 } 129 } 130 } 131 132 if err := checkInitConfig(ctx, clusterName, initConfig, tt.cloudProvider); err != nil { 133 t.Errorf("%s: %v", initConfig, err) 134 } 135 136 for _, f := range joinFiles { 137 if err := checkJoinConfig(ctx, clusterName, f, tt.cloudProvider); err != nil { 138 t.Errorf("error while inspecting file %s: %v", f, err) 139 } 140 } 141 }) 142 } 143 } 144 145 // check the init configuration hold inside of `file`. Path to file is built starting 146 // from the test `ctx` and the `clusterName`, plus the ending name of the `file`. 147 // `cloud` holds the name of the CPI - leave empty if CPI is disabled. 148 func checkInitConfig(ctx TestFilesystemContext, clusterName, file, provider string) error { 149 expected := len(provider) > 0 150 kubeadmInitConfig, err := node.LoadInitConfigurationFromFile( 151 filepath.Join(ctx.WorkDirectory, clusterName, file)) 152 if err != nil { 153 return fmt.Errorf("unexpected error: %v", err) 154 } 155 156 value, found := kubeadmInitConfig.NodeRegistration.KubeletExtraArgs["cloud-provider"] 157 if err := checkMapEntry(provider, value, expected, found); err != nil { 158 return fmt.Errorf("nodeRegistration - %v", err) 159 } 160 161 value, found = kubeadmInitConfig.ClusterConfiguration.APIServer.ExtraArgs["cloud-provider"] 162 if err := checkMapEntry(provider, value, expected, found); err != nil { 163 return fmt.Errorf("apiServer.extraArgs - %v", err) 164 } 165 166 value, found = kubeadmInitConfig.ClusterConfiguration.ControllerManager.ExtraArgs["cloud-provider"] 167 if err := checkMapEntry(provider, value, expected, found); err != nil { 168 return fmt.Errorf("controllerManager.extraArgs - %v", err) 169 } 170 171 if provider == "aws" { 172 value, found = kubeadmInitConfig.ClusterConfiguration.ControllerManager.ExtraArgs["allocate-node-cidrs"] 173 if err := checkMapEntry("false", value, expected, found); err != nil { 174 return fmt.Errorf("controllerManager.extraArgs - %v", err) 175 } 176 } 177 178 return nil 179 } 180 181 // check the join configuration hold inside of `file`. Path to file is built starting 182 // from the test `ctx` and the `clusterName`, plus the ending name of the `file`. 183 // `cloud` holds the name of the CPI - leave empty if CPI is disabled. 184 func checkJoinConfig(ctx TestFilesystemContext, clusterName, file, provider string) error { 185 expected := provider != "" 186 kubeadmJoinConfig, err := node.LoadJoinConfigurationFromFile( 187 filepath.Join(ctx.WorkDirectory, clusterName, file)) 188 if err != nil { 189 return err 190 } 191 192 value, found := kubeadmJoinConfig.NodeRegistration.KubeletExtraArgs["cloud-provider"] 193 return checkMapEntry(provider, value, expected, found) 194 } 195 196 // Compares the `value` found inside of a map against its `expectedValue` 197 // return an error when the check fails 198 func checkMapEntry(expectedValue, value string, expected, found bool) error { 199 if found { 200 if !expected { 201 return fmt.Errorf("cloud-provider integration is accidentally enabled") 202 } 203 if value != expectedValue { 204 return fmt.Errorf("wrong cloud-provider value, expected %s, got %s", expectedValue, value) 205 } 206 } else if expected { 207 return fmt.Errorf("nodeRegistration - couldn't find cloud-provider value") 208 } 209 210 return nil 211 } 212 213 // Create a new temporary directory and switches into it 214 func switchToTemporaryDirectory() (TestFilesystemContext, error) { 215 var ctx TestFilesystemContext 216 217 tmp, err := os.Getwd() 218 if err != nil { 219 return ctx, err 220 } 221 ctx.OldWorkDirectory = tmp 222 223 tmp, err = ioutil.TempDir("", "skuba-cluster-init-test") 224 if err != nil { 225 return ctx, err 226 } 227 ctx.WorkDirectory = tmp 228 229 if err = os.Chdir(ctx.WorkDirectory); err != nil { 230 return ctx, err 231 } 232 233 return ctx, nil 234 } 235 236 // Remove the temporary directory previously created and 237 // moves back to the work directory used at the beginning of 238 // the test 239 func switchBackAndCleanFilesystem(ctx TestFilesystemContext) { 240 if err := os.Chdir(ctx.OldWorkDirectory); err != nil { 241 fmt.Printf("Cannot chdir back to original work directory: %v", err) 242 } 243 if err := os.RemoveAll(ctx.WorkDirectory); err != nil { 244 fmt.Printf("Cannot remove temporary directory: %v", err) 245 } 246 } 247 248 // Checks if the specified file exists. Raises an error if something 249 // unexpected happens. 250 func doesFileExist(ctx TestFilesystemContext, clusterName, file string) (bool, error) { 251 fullpath := filepath.Join(ctx.WorkDirectory, clusterName, file) 252 if _, err := os.Stat(fullpath); err != nil { 253 if os.IsNotExist(err) { 254 return false, nil 255 } 256 return false, err 257 } 258 259 return true, nil 260 }