github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/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  	"time"
    23  
    24  	"github.com/sealerio/sealer/common"
    25  	"github.com/sealerio/sealer/pkg/checker"
    26  	k "github.com/sealerio/sealer/pkg/client/k8s"
    27  	"github.com/sealerio/sealer/pkg/infra"
    28  	"github.com/sealerio/sealer/test/testhelper"
    29  	"github.com/sealerio/sealer/test/testhelper/client/k8s"
    30  	"github.com/sealerio/sealer/test/testhelper/settings"
    31  	"github.com/sealerio/sealer/types/api/constants"
    32  	v1 "github.com/sealerio/sealer/types/api/v1"
    33  	"github.com/sealerio/sealer/utils"
    34  	"github.com/sealerio/sealer/utils/exec"
    35  	"github.com/sealerio/sealer/utils/os"
    36  
    37  	"github.com/onsi/gomega"
    38  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    39  	"sigs.k8s.io/yaml"
    40  )
    41  
    42  func getFixtures() string {
    43  	pwd := settings.DefaultTestEnvDir
    44  	return filepath.Join(pwd, "suites", "apply", "fixtures")
    45  }
    46  
    47  func GetRawClusterFilePath() string {
    48  	fixtures := getFixtures()
    49  	return filepath.Join(fixtures, "cluster_file_for_test.yaml")
    50  }
    51  
    52  func GetRawConfigPluginFilePath() string {
    53  	fixtures := getFixtures()
    54  	return filepath.Join(fixtures, "config_plugin_for_test.yaml")
    55  }
    56  
    57  func DeleteClusterByFile(clusterFile string) {
    58  	testhelper.RunCmdAndCheckResult(SealerDeleteCmd(clusterFile), 0)
    59  }
    60  
    61  func WriteClusterFileToDisk(cluster *v1.Cluster, clusterFilePath string) {
    62  	testhelper.CheckNotNil(cluster)
    63  	//convert clusterfilev1 to clusterfilev2
    64  	clusterv2 := utils.ConvertV1ClusterToV2Cluster(cluster)
    65  	clusterv2.Spec.Env = []string{"env=TestEnv"}
    66  	err := testhelper.MarshalYamlToFile(clusterFilePath, clusterv2)
    67  	testhelper.CheckErr(err)
    68  }
    69  
    70  func LoadClusterFileFromDisk(clusterFilePath string) *v1.Cluster {
    71  	cluster, err := utils.DecodeV1ClusterFromFile(clusterFilePath)
    72  	testhelper.CheckErr(err)
    73  	testhelper.CheckNotNil(cluster)
    74  	return cluster
    75  }
    76  
    77  func LoadConfigFromDisk(clusterFilePath string) []v1.Config {
    78  	configs, err := utils.DecodeCRDFromFile(clusterFilePath, constants.ConfigKind)
    79  	testhelper.CheckErr(err)
    80  	testhelper.CheckNotNil(configs)
    81  	return configs.([]v1.Config)
    82  }
    83  
    84  func LoadPluginFromDisk(clusterFilePath string) []v1.Plugin {
    85  	plugins, err := utils.DecodeCRDFromFile(clusterFilePath, constants.PluginKind)
    86  	testhelper.CheckErr(err)
    87  	testhelper.CheckNotNil(plugins)
    88  	return plugins.([]v1.Plugin)
    89  }
    90  
    91  func GenerateClusterfile(clusterfile string) {
    92  	fp := GetRawConfigPluginFilePath()
    93  	cluster := LoadClusterFileFromDisk(clusterfile)
    94  	//convert clusterfilev1 to clusterfilev2
    95  	clusterv2 := utils.ConvertV1ClusterToV2Cluster(cluster)
    96  	clusterv2.Spec.Env = []string{"env=TestEnv"}
    97  	data, err := yaml.Marshal(clusterv2)
    98  	testhelper.CheckErr(err)
    99  	appendData := [][]byte{data}
   100  	plugins := LoadPluginFromDisk(fp)
   101  	configs := LoadConfigFromDisk(fp)
   102  	for _, plugin := range plugins {
   103  		if plugin.Spec.Type == common.LABEL {
   104  			pluginData := "\n"
   105  			for _, ip := range cluster.Spec.Masters.IPList {
   106  				pluginData += fmt.Sprintf(" %s sealer-test=true \n", ip)
   107  			}
   108  			plugin.Spec.Data = pluginData
   109  		}
   110  		if plugin.Spec.Type == common.HOSTNAME {
   111  			pluginData := "\n"
   112  			for i, ip := range cluster.Spec.Masters.IPList {
   113  				pluginData += fmt.Sprintf("%s master-%s\n", ip, strconv.Itoa(i))
   114  			}
   115  			for i, ip := range cluster.Spec.Nodes.IPList {
   116  				pluginData += fmt.Sprintf("%s node-%s\n", ip, strconv.Itoa(i))
   117  			}
   118  			plugin.Spec.Data = pluginData
   119  		}
   120  		if plugin.Spec.Type == common.TAINT {
   121  			pluginData := "\n"
   122  			for _, ip := range cluster.Spec.Masters.IPList {
   123  				pluginData += fmt.Sprintf("%s node-role.kubernetes.io/master:NoSchedule-\n", ip)
   124  			}
   125  			for _, ip := range cluster.Spec.Nodes.IPList {
   126  				pluginData += fmt.Sprintf("%s sealer-test=true:NoSchedule\n", ip)
   127  			}
   128  			plugin.Spec.Data = pluginData
   129  		}
   130  		data, err := yaml.Marshal(plugin)
   131  		testhelper.CheckErr(err)
   132  		appendData = append(appendData, []byte("---\n"), data)
   133  	}
   134  	for _, config := range configs {
   135  		data, err := yaml.Marshal(config)
   136  		testhelper.CheckErr(err)
   137  		appendData = append(appendData, []byte("---\n"), data)
   138  	}
   139  	err = os.NewCommonWriter(clusterfile).WriteFile(bytes.Join(appendData, []byte("")))
   140  	testhelper.CheckErr(err)
   141  }
   142  
   143  func SealerDeleteCmd(clusterFile string) string {
   144  	return fmt.Sprintf("%s delete -f %s --force -d", settings.DefaultSealerBin, clusterFile)
   145  }
   146  
   147  func SealerDeleteAll() string {
   148  	return fmt.Sprintf("%s delete --all --force -d", settings.DefaultSealerBin)
   149  }
   150  
   151  func SealerDeleteNodeCmd(ip string) string {
   152  	return fmt.Sprintf("%s delete -n %s --force -d", settings.DefaultSealerBin, ip)
   153  }
   154  
   155  func SealerApplyCmd(clusterFile string) string {
   156  	return fmt.Sprintf("%s apply -f %s --force -d", settings.DefaultSealerBin, clusterFile)
   157  }
   158  
   159  func SealerRunCmd(masters, nodes, passwd string, provider string) string {
   160  	if masters != "" {
   161  		masters = fmt.Sprintf("-m %s", masters)
   162  	}
   163  	if nodes != "" {
   164  		nodes = fmt.Sprintf("-n %s", nodes)
   165  	}
   166  	if passwd != "" {
   167  		passwd = fmt.Sprintf("-p %s", passwd)
   168  	}
   169  	if provider != "" {
   170  		provider = fmt.Sprintf("--provider %s", provider)
   171  	}
   172  	return fmt.Sprintf("%s run %s %s %s %s %s -d", settings.DefaultSealerBin, settings.TestImageName, masters, nodes, passwd, provider)
   173  }
   174  
   175  func SealerRun(masters, nodes, passwd, provider string) {
   176  	testhelper.RunCmdAndCheckResult(SealerRunCmd(masters, nodes, passwd, provider), 0)
   177  }
   178  
   179  func SealerJoinCmd(masters, nodes string) string {
   180  	if masters != "" {
   181  		masters = fmt.Sprintf("-m %s", masters)
   182  	}
   183  	if nodes != "" {
   184  		nodes = fmt.Sprintf("-n %s", nodes)
   185  	}
   186  	return fmt.Sprintf("%s join %s %s -d", settings.DefaultSealerBin, masters, nodes)
   187  }
   188  
   189  func SealerJoin(masters, nodes string) {
   190  	testhelper.RunCmdAndCheckResult(SealerJoinCmd(masters, nodes), 0)
   191  }
   192  
   193  func CreateContainerInfraAndSave(cluster *v1.Cluster, clusterFile string) *v1.Cluster {
   194  	CreateContainerInfra(cluster)
   195  	//save used cluster file
   196  	cluster.Spec.Provider = settings.BAREMETAL
   197  	MarshalClusterToFile(clusterFile, cluster)
   198  	cluster.Spec.Provider = settings.CONTAINER
   199  	return cluster
   200  }
   201  
   202  func ChangeMasterOrderAndSave(cluster *v1.Cluster, clusterFile string) *v1.Cluster {
   203  	cluster.Spec.Masters.Count = strconv.Itoa(3)
   204  	CreateContainerInfra(cluster)
   205  	//change master order and save used cluster file
   206  	cluster.Spec.Masters.IPList[0], cluster.Spec.Masters.IPList[1] = cluster.Spec.Masters.IPList[1], cluster.Spec.Masters.IPList[0]
   207  	cluster.Spec.Provider = settings.BAREMETAL
   208  	MarshalClusterToFile(clusterFile, cluster)
   209  	cluster.Spec.Provider = settings.CONTAINER
   210  	return cluster
   211  }
   212  
   213  func CreateContainerInfra(cluster *v1.Cluster) {
   214  	cluster.DeletionTimestamp = nil
   215  	infraManager, err := infra.NewDefaultProvider(cluster)
   216  	testhelper.CheckErr(err)
   217  	err = infraManager.Apply()
   218  	testhelper.CheckErr(err)
   219  }
   220  
   221  func SendAndApplyCluster(sshClient *testhelper.SSHClient, clusterFile string) {
   222  	SendAndRemoteExecCluster(sshClient, clusterFile, SealerApplyCmd(clusterFile))
   223  }
   224  
   225  func SendAndJoinCluster(sshClient *testhelper.SSHClient, clusterFile string, joinMasters, joinNodes string) {
   226  	SendAndRemoteExecCluster(sshClient, clusterFile, SealerJoinCmd(joinMasters, joinNodes))
   227  }
   228  
   229  func SendAndRunCluster(sshClient *testhelper.SSHClient, clusterFile string, joinMasters, joinNodes, passwd string) {
   230  	SendAndRemoteExecCluster(sshClient, clusterFile, SealerRunCmd(joinMasters, joinNodes, passwd, ""))
   231  }
   232  
   233  func SendAndRemoteExecCluster(sshClient *testhelper.SSHClient, clusterFile string, remoteCmd string) {
   234  	// send tmp cluster file to remote server and run apply cmd
   235  	gomega.Eventually(func() bool {
   236  		err := sshClient.SSH.Copy(sshClient.RemoteHostIP, clusterFile, clusterFile)
   237  		return err == nil
   238  	}, settings.MaxWaiteTime).Should(gomega.BeTrue())
   239  	err := sshClient.SSH.CmdAsync(sshClient.RemoteHostIP, nil, remoteCmd)
   240  	testhelper.CheckErr(err)
   241  }
   242  
   243  func CleanUpContainerInfra(cluster *v1.Cluster) {
   244  	if cluster == nil {
   245  		return
   246  	}
   247  	if cluster.Spec.Provider != settings.CONTAINER {
   248  		cluster.Spec.Provider = settings.CONTAINER
   249  	}
   250  	t := metav1.Now()
   251  	cluster.DeletionTimestamp = &t
   252  	infraManager, err := infra.NewDefaultProvider(cluster)
   253  	testhelper.CheckErr(err)
   254  	err = infraManager.Apply()
   255  	testhelper.CheckErr(err)
   256  }
   257  
   258  // CheckNodeNumWithSSH check node num of remote cluster
   259  func CheckNodeNumWithSSH(client *k8s.Client, expectNum int) {
   260  	if client == nil {
   261  		return
   262  	}
   263  	nodes, err := client.ListNodes()
   264  	testhelper.CheckErr(err)
   265  	num := len(nodes.Items)
   266  	testhelper.CheckEqual(num, expectNum)
   267  }
   268  
   269  // CheckNodeNumLocally check node num of local cluster
   270  func CheckNodeNumLocally(client *k.Client, expectNum int) {
   271  	if client == nil {
   272  		return
   273  	}
   274  	nodes, err := client.ListNodes()
   275  	testhelper.CheckErr(err)
   276  	num := len(nodes.Items)
   277  	testhelper.CheckEqual(num, expectNum)
   278  }
   279  
   280  func WaitAllNodeRunning() {
   281  	time.Sleep(30 * time.Second)
   282  	err := utils.Retry(10, 5*time.Second, func() error {
   283  		return checker.NewNodeChecker().Check(nil, checker.PhasePost)
   284  	})
   285  	testhelper.CheckErr(err)
   286  }
   287  
   288  func WaitAllNodeRunningBySSH(client *k8s.Client) {
   289  	time.Sleep(30 * time.Second)
   290  	err := utils.Retry(10, 5*time.Second, func() error {
   291  		flag, err := client.CheckAllNodeReady()
   292  		if err != nil {
   293  			return err
   294  		}
   295  		if !flag {
   296  			err = client.OutputNotReadyPodInfo()
   297  			if err != nil {
   298  				return err
   299  			}
   300  			return fmt.Errorf("node not ready")
   301  		}
   302  		return nil
   303  	})
   304  	testhelper.CheckErr(err)
   305  }
   306  
   307  func MarshalClusterToFile(ClusterFile string, cluster *v1.Cluster) {
   308  	err := testhelper.MarshalYamlToFile(ClusterFile, &cluster)
   309  	testhelper.CheckErr(err)
   310  	testhelper.CheckNotNil(cluster)
   311  }
   312  
   313  func CheckDockerAndSwapOff() {
   314  	_, err := exec.RunSimpleCmd("docker -v")
   315  	testhelper.CheckErr(err)
   316  	_, err = exec.RunSimpleCmd("swapoff -a")
   317  	testhelper.CheckErr(err)
   318  }