github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/test/suites/apply/apply.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package apply 16 17 import ( 18 "bytes" 19 "fmt" 20 "path/filepath" 21 "strconv" 22 "strings" 23 "time" 24 25 "github.com/alibaba/sealer/pkg/checker" 26 "github.com/alibaba/sealer/utils/ssh" 27 28 "github.com/onsi/gomega" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "sigs.k8s.io/yaml" 31 32 "github.com/alibaba/sealer/pkg/infra" 33 "github.com/alibaba/sealer/test/testhelper" 34 "github.com/alibaba/sealer/test/testhelper/settings" 35 v1 "github.com/alibaba/sealer/types/api/v1" 36 "github.com/alibaba/sealer/utils" 37 ) 38 39 func getFixtures() string { 40 pwd := settings.DefaultTestEnvDir 41 return filepath.Join(pwd, "suites", "apply", "fixtures") 42 } 43 44 func GetRawClusterFilePath() string { 45 fixtures := getFixtures() 46 return filepath.Join(fixtures, "cluster_file_for_test.yaml") 47 } 48 49 func GetRawConfigPluginFilePath() string { 50 fixtures := getFixtures() 51 return filepath.Join(fixtures, "config_plugin_for_test.yaml") 52 } 53 54 func DeleteClusterByFile(clusterFile string) { 55 testhelper.RunCmdAndCheckResult(SealerDeleteCmd(clusterFile), 0) 56 } 57 58 func WriteClusterFileToDisk(cluster *v1.Cluster, clusterFilePath string) { 59 testhelper.CheckNotNil(cluster) 60 err := testhelper.MarshalYamlToFile(clusterFilePath, cluster) 61 testhelper.CheckErr(err) 62 } 63 64 func LoadClusterFileFromDisk(clusterFilePath string) *v1.Cluster { 65 clusters, err := utils.DecodeCluster(clusterFilePath) 66 testhelper.CheckErr(err) 67 testhelper.CheckNotNil(clusters[0]) 68 return &clusters[0] 69 } 70 71 func LoadConfigFromDisk(clusterFilePath string) []v1.Config { 72 configs, err := utils.DecodeConfigs(clusterFilePath) 73 testhelper.CheckErr(err) 74 testhelper.CheckNotNil(configs) 75 return configs 76 } 77 78 func LoadPluginFromDisk(clusterFilePath string) []v1.Plugin { 79 plugins, err := utils.DecodePlugins(clusterFilePath) 80 testhelper.CheckErr(err) 81 testhelper.CheckNotNil(plugins) 82 return plugins 83 } 84 85 func GenerateClusterfile(clusterfile string) { 86 filepath := GetRawConfigPluginFilePath() 87 cluster := LoadClusterFileFromDisk(clusterfile) 88 cluster.Spec.Env = []string{"env=TestEnv"} 89 data, err := yaml.Marshal(cluster) 90 testhelper.CheckErr(err) 91 appendData := [][]byte{data} 92 plugins := LoadPluginFromDisk(filepath) 93 configs := LoadConfigFromDisk(filepath) 94 for _, plugin := range plugins { 95 if plugin.Spec.Type == "LABEL" { 96 pluginData := "\n" 97 for _, ip := range cluster.Spec.Masters.IPList { 98 pluginData += fmt.Sprintf(" %s sealer-test=true \n", ip) 99 } 100 plugin.Spec.Data = pluginData 101 } 102 if plugin.Spec.Type == "HOSTNAME" { 103 pluginData := "\n" 104 for i, ip := range cluster.Spec.Masters.IPList { 105 pluginData += fmt.Sprintf("%s master-%s\n", ip, strconv.Itoa(i)) 106 } 107 for i, ip := range cluster.Spec.Nodes.IPList { 108 pluginData += fmt.Sprintf("%s node-%s\n", ip, strconv.Itoa(i)) 109 } 110 plugin.Spec.Data = pluginData 111 } 112 data, err := yaml.Marshal(plugin) 113 testhelper.CheckErr(err) 114 appendData = append(appendData, []byte("---\n"), data) 115 } 116 for _, config := range configs { 117 data, err := yaml.Marshal(config) 118 testhelper.CheckErr(err) 119 appendData = append(appendData, []byte("---\n"), data) 120 } 121 err = utils.WriteFile(clusterfile, bytes.Join(appendData, []byte(""))) 122 testhelper.CheckErr(err) 123 } 124 125 func SealerDeleteCmd(clusterFile string) string { 126 return fmt.Sprintf("%s delete -f %s --force -d", settings.DefaultSealerBin, clusterFile) 127 } 128 129 func SealerApplyCmd(clusterFile string) string { 130 return fmt.Sprintf("%s apply -f %s --force -d", settings.DefaultSealerBin, clusterFile) 131 } 132 133 func SealerRunCmd(masters, nodes, passwd string, provider string) string { 134 if masters != "" { 135 masters = fmt.Sprintf("-m %s", masters) 136 } 137 if nodes != "" { 138 nodes = fmt.Sprintf("-n %s", nodes) 139 } 140 if passwd != "" { 141 passwd = fmt.Sprintf("-p %s", passwd) 142 } 143 if provider != "" { 144 provider = fmt.Sprintf("--provider %s", provider) 145 } 146 return fmt.Sprintf("%s run %s %s %s %s %s -d", settings.DefaultSealerBin, settings.TestImageName, masters, nodes, passwd, provider) 147 } 148 149 func SealerRun(masters, nodes, passwd, provider string) { 150 testhelper.RunCmdAndCheckResult(SealerRunCmd(masters, nodes, passwd, provider), 0) 151 } 152 153 func SealerJoinCmd(masters, nodes string) string { 154 if masters != "" { 155 masters = fmt.Sprintf("-m %s", masters) 156 } 157 if nodes != "" { 158 nodes = fmt.Sprintf("-n %s", nodes) 159 } 160 return fmt.Sprintf("%s join %s %s -c my-test-cluster -d", settings.DefaultSealerBin, masters, nodes) 161 } 162 163 func SealerJoin(masters, nodes string) { 164 testhelper.RunCmdAndCheckResult(SealerJoinCmd(masters, nodes), 0) 165 } 166 167 func CreateAliCloudInfraAndSave(cluster *v1.Cluster, clusterFile string) *v1.Cluster { 168 CreateAliCloudInfra(cluster) 169 //save used cluster file 170 cluster.Spec.Provider = settings.BAREMETAL 171 MarshalClusterToFile(clusterFile, cluster) 172 cluster.Spec.Provider = settings.AliCloud 173 return cluster 174 } 175 176 func ChangeMasterOrderAndSave(cluster *v1.Cluster, clusterFile string) *v1.Cluster { 177 cluster.Spec.Masters.Count = strconv.Itoa(3) 178 CreateAliCloudInfra(cluster) 179 //change master order and save used cluster file 180 cluster.Spec.Masters.IPList[0], cluster.Spec.Masters.IPList[1] = cluster.Spec.Masters.IPList[1], cluster.Spec.Masters.IPList[0] 181 cluster.Spec.Provider = settings.BAREMETAL 182 MarshalClusterToFile(clusterFile, cluster) 183 cluster.Spec.Provider = settings.AliCloud 184 return cluster 185 } 186 187 func CreateAliCloudInfra(cluster *v1.Cluster) { 188 cluster.DeletionTimestamp = nil 189 infraManager, err := infra.NewDefaultProvider(cluster) 190 testhelper.CheckErr(err) 191 err = infraManager.Apply() 192 testhelper.CheckErr(err) 193 } 194 195 func SendAndApplyCluster(sshClient *testhelper.SSHClient, clusterFile string) { 196 SendAndRemoteExecCluster(sshClient, clusterFile, SealerApplyCmd(clusterFile)) 197 } 198 199 func SendAndJoinCluster(sshClient *testhelper.SSHClient, clusterFile string, joinMasters, joinNodes string) { 200 SendAndRemoteExecCluster(sshClient, clusterFile, SealerJoinCmd(joinMasters, joinNodes)) 201 } 202 203 func SendAndRunCluster(sshClient *testhelper.SSHClient, clusterFile string, joinMasters, joinNodes, passwd string) { 204 SendAndRemoteExecCluster(sshClient, clusterFile, SealerRunCmd(joinMasters, joinNodes, passwd, "")) 205 } 206 207 func SendAndRemoteExecCluster(sshClient *testhelper.SSHClient, clusterFile string, remoteCmd string) { 208 // send tmp cluster file to remote server and run apply cmd 209 gomega.Eventually(func() bool { 210 err := sshClient.SSH.Copy(sshClient.RemoteHostIP, clusterFile, clusterFile) 211 return err == nil 212 }, settings.MaxWaiteTime).Should(gomega.BeTrue()) 213 err := sshClient.SSH.CmdAsync(sshClient.RemoteHostIP, remoteCmd) 214 testhelper.CheckErr(err) 215 } 216 217 func CleanUpAliCloudInfra(cluster *v1.Cluster) { 218 if cluster == nil { 219 return 220 } 221 if cluster.Spec.Provider != settings.AliCloud { 222 cluster.Spec.Provider = settings.AliCloud 223 } 224 t := metav1.Now() 225 cluster.DeletionTimestamp = &t 226 infraManager, err := infra.NewDefaultProvider(cluster) 227 testhelper.CheckErr(err) 228 err = infraManager.Apply() 229 testhelper.CheckErr(err) 230 } 231 232 // CheckNodeNumWithSSH check node mum of remote cluster;for bare metal apply 233 func CheckNodeNumWithSSH(sshClient *testhelper.SSHClient, expectNum int) { 234 if sshClient == nil { 235 return 236 } 237 cmd := "kubectl get nodes | wc -l" 238 result, err := sshClient.SSH.CmdToString(sshClient.RemoteHostIP, cmd, "") 239 testhelper.CheckErr(err) 240 num, err := strconv.Atoi(strings.ReplaceAll(result, "\n", "")) 241 testhelper.CheckErr(err) 242 testhelper.CheckEqual(num, expectNum+1) 243 } 244 245 // CheckNodeNumLocally check node mum of remote cluster;for cloud apply 246 func CheckNodeNumLocally(expectNum int) { 247 cmd := "sudo -E kubectl get nodes | wc -l" 248 result, err := utils.RunSimpleCmd(cmd) 249 testhelper.CheckErr(err) 250 num, err := strconv.Atoi(strings.ReplaceAll(result, "\n", "")) 251 testhelper.CheckErr(err) 252 testhelper.CheckEqual(num, expectNum+1) 253 } 254 255 func WaitAllNodeRunning() { 256 time.Sleep(30 * time.Second) 257 err := utils.Retry(10, 5*time.Second, func() error { 258 return checker.NewNodeChecker().Check(nil, checker.PhasePost) 259 }) 260 testhelper.CheckErr(err) 261 } 262 263 func WaitAllNodeRunningBySSH(s ssh.Interface, masterIP string) { 264 time.Sleep(30 * time.Second) 265 err := utils.Retry(10, 5*time.Second, func() error { 266 result, err := s.CmdToString(masterIP, "kubectl get nodes", "") 267 if err != nil { 268 return err 269 } 270 if strings.Contains(result, "NotReady") { 271 return fmt.Errorf("node not ready: \n %s", result) 272 } 273 return nil 274 }) 275 testhelper.CheckErr(err) 276 } 277 278 func MarshalClusterToFile(ClusterFile string, cluster *v1.Cluster) { 279 err := testhelper.MarshalYamlToFile(ClusterFile, &cluster) 280 testhelper.CheckErr(err) 281 testhelper.CheckNotNil(cluster) 282 } 283 284 func CheckDockerAndSwapOff() { 285 _, err := utils.RunSimpleCmd("docker -v") 286 testhelper.CheckErr(err) 287 _, err = utils.RunSimpleCmd("swapoff -a") 288 testhelper.CheckErr(err) 289 }