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  }