github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/infra/aliyun/ali_provider.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 aliyun
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"path/filepath"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/sealerio/sealer/common"
    25  	"github.com/sealerio/sealer/utils/yaml"
    26  
    27  	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
    28  	"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
    29  	"github.com/sirupsen/logrus"
    30  
    31  	v1 "github.com/sealerio/sealer/types/api/v1"
    32  )
    33  
    34  type ActionName string
    35  
    36  const (
    37  	CreateVPC           ActionName = "CreateVPC"
    38  	CreateVSwitch       ActionName = "CreateVSwitch"
    39  	CreateSecurityGroup ActionName = "CreateSecurityGroup"
    40  	ReconcileInstance   ActionName = "ReconcileInstance"
    41  	BindEIP             ActionName = "BindEIP"
    42  	ReleaseEIP          ActionName = "ReleaseEIP"
    43  	ClearInstances      ActionName = "ClearInstances"
    44  	DeleteVSwitch       ActionName = "DeleteVSwitch"
    45  	DeleteSecurityGroup ActionName = "DeleteSecurityGroup"
    46  	DeleteVPC           ActionName = "DeleteVPC"
    47  	GetZoneID           ActionName = "GetZoneID"
    48  )
    49  
    50  type AliProvider struct {
    51  	Config    Config
    52  	EcsClient ecs.Client
    53  	VpcClient vpc.Client
    54  	Cluster   *v1.Cluster
    55  }
    56  
    57  type Config struct {
    58  	AccessKey    string
    59  	AccessSecret string
    60  	RegionID     string
    61  }
    62  
    63  type Alifunc func() error
    64  
    65  const (
    66  	Scheme                     = "https"
    67  	IPProtocol                 = "tcp"
    68  	APIServerPortRange         = "6443/6443"
    69  	SSHPortRange               = "22/22"
    70  	SourceCidrIP               = "0.0.0.0/0"
    71  	CidrBlock                  = "172.16.0.0/24"
    72  	Policy                     = "accept"
    73  	DestinationResource        = "InstanceType"
    74  	InstanceChargeType         = "PostPaid"
    75  	InternetChargeType         = "PayByTraffic"
    76  	ImageID                    = "centos_7_9_x64_20G_alibase_20210927.vhd"
    77  	AccessKey                  = "ACCESSKEYID"
    78  	AccessSecret               = "ACCESSKEYSECRET"
    79  	Product                    = "product"
    80  	Role                       = "role"
    81  	Master                     = "master"
    82  	Node                       = "node"
    83  	Stopped                    = "Stopped"
    84  	AvailableTypeStatus        = "WithStock"
    85  	Bandwidth                  = "100"
    86  	Digits                     = "0123456789"
    87  	Specials                   = "~=+%^*/()[]{}/!@#$?|"
    88  	Letter                     = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    89  	PasswordLength             = 16
    90  	DataCategory               = "cloud_ssd"
    91  	AliDomain                  = "sea.aliyun.com/"
    92  	AliCloud                   = "ALI_CLOUD"
    93  	EipID                      = AliDomain + "EipID"
    94  	Master0ID                  = AliDomain + "Master0ID"
    95  	Master0InternalIP          = AliDomain + "Master0InternalIP"
    96  	VpcID                      = AliDomain + "VpcID"
    97  	VSwitchID                  = AliDomain + "VSwitchID"
    98  	SecurityGroupID            = AliDomain + "SecurityGroupID"
    99  	Eip                        = AliDomain + "ClusterEIP"
   100  	ZoneID                     = AliDomain + "ZoneID"
   101  	RegionID                   = "RegionID"
   102  	AliRegionID                = AliDomain + RegionID
   103  	AliMasterIDs               = AliDomain + "MasterIDs"
   104  	AliNodeIDs                 = AliDomain + "NodeIDs"
   105  	DefaultRegionID            = "cn-chengdu"
   106  	AliCloudEssd               = "cloud_essd"
   107  	TryTimes                   = 10
   108  	TrySleepTime               = time.Second
   109  	JustGetInstanceInfo        = ""
   110  	ShouldBeDeleteInstancesIDs = "ShouldBeDeleteInstancesIDs"
   111  )
   112  
   113  func (a *AliProvider) ReconcileResource(resourceKey string, action Alifunc) error {
   114  	if a.Cluster.Annotations[resourceKey] == "" {
   115  		err := action()
   116  		if err != nil {
   117  			return err
   118  		}
   119  		logrus.Infof("create resource success %s: %s", resourceKey, a.Cluster.Annotations[resourceKey])
   120  		return a.SaveToDisk()
   121  	}
   122  	return nil
   123  }
   124  
   125  func (a *AliProvider) SaveToDisk() error {
   126  	fileName := common.GetDefaultClusterfile()
   127  	err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm)
   128  	if err != nil {
   129  		return fmt.Errorf("mkdir failed %s %v", fileName, err)
   130  	}
   131  
   132  	return yaml.MarshalToFile(fileName, a.Cluster)
   133  }
   134  
   135  func (a *AliProvider) DeleteResource(resourceKey string, action Alifunc) {
   136  	if a.Cluster.Annotations[resourceKey] != "" {
   137  		err := action()
   138  		if err != nil {
   139  			logrus.Errorf("delete resource %s failed err: %s", resourceKey, err)
   140  		} else {
   141  			logrus.Infof("delete resource Success %s", a.Cluster.Annotations[resourceKey])
   142  		}
   143  	}
   144  }
   145  
   146  var RecocileFuncMap = map[ActionName]func(provider *AliProvider) error{
   147  	CreateVPC: func(aliProvider *AliProvider) error {
   148  		return aliProvider.ReconcileResource(VpcID, aliProvider.CreateVPC)
   149  	},
   150  
   151  	CreateVSwitch: func(aliProvider *AliProvider) error {
   152  		return aliProvider.ReconcileResource(VSwitchID, aliProvider.CreateVSwitch)
   153  	},
   154  	CreateSecurityGroup: func(aliProvider *AliProvider) error {
   155  		return aliProvider.ReconcileResource(SecurityGroupID, aliProvider.CreateSecurityGroup)
   156  	},
   157  	ReconcileInstance: func(aliProvider *AliProvider) error {
   158  		err := aliProvider.ReconcileInstances(Master)
   159  		if err != nil {
   160  			return err
   161  		}
   162  
   163  		err = aliProvider.ReconcileInstances(Node)
   164  		if err != nil {
   165  			return err
   166  		}
   167  		return nil
   168  	},
   169  	GetZoneID: func(aliProvider *AliProvider) error {
   170  		return aliProvider.ReconcileResource(ZoneID, aliProvider.GetZoneID)
   171  	},
   172  	BindEIP: func(aliProvider *AliProvider) error {
   173  		return aliProvider.ReconcileResource(EipID, aliProvider.BindEipForMaster0)
   174  	},
   175  }
   176  
   177  var DeleteFuncMap = map[ActionName]func(provider *AliProvider){
   178  	ReleaseEIP: func(aliProvider *AliProvider) {
   179  		aliProvider.DeleteResource(EipID, aliProvider.ReleaseEipAddress)
   180  	},
   181  	ClearInstances: func(aliProvider *AliProvider) {
   182  		var instanceIDs []string
   183  		roles := []string{Master, Node}
   184  		for _, role := range roles {
   185  			instances, err := aliProvider.GetInstancesInfo(role, JustGetInstanceInfo)
   186  			if err != nil {
   187  				logrus.Errorf("get %s instanceinfo failed %v", role, err)
   188  			}
   189  			for _, instance := range instances {
   190  				instanceIDs = append(instanceIDs, instance.InstanceID)
   191  			}
   192  		}
   193  		if len(instanceIDs) != 0 {
   194  			aliProvider.Cluster.Annotations[ShouldBeDeleteInstancesIDs] = strings.Join(instanceIDs, ",")
   195  		}
   196  		aliProvider.DeleteResource(ShouldBeDeleteInstancesIDs, aliProvider.DeleteInstances)
   197  	},
   198  	DeleteVSwitch: func(aliProvider *AliProvider) {
   199  		aliProvider.DeleteResource(VSwitchID, aliProvider.DeleteVSwitch)
   200  	},
   201  	DeleteSecurityGroup: func(aliProvider *AliProvider) {
   202  		aliProvider.DeleteResource(SecurityGroupID, aliProvider.DeleteSecurityGroup)
   203  	},
   204  	DeleteVPC: func(aliProvider *AliProvider) {
   205  		aliProvider.DeleteResource(VpcID, aliProvider.DeleteVPC)
   206  	},
   207  }
   208  
   209  func (a *AliProvider) NewClient() error {
   210  	ecsClient, err := ecs.NewClientWithAccessKey(a.Config.RegionID, a.Config.AccessKey, a.Config.AccessSecret)
   211  	if err != nil {
   212  		return err
   213  	}
   214  	vpcClient, err := vpc.NewClientWithAccessKey(a.Config.RegionID, a.Config.AccessKey, a.Config.AccessSecret)
   215  	if err != nil {
   216  		return err
   217  	}
   218  	a.EcsClient = *ecsClient
   219  	a.VpcClient = *vpcClient
   220  	return nil
   221  }
   222  
   223  func (a *AliProvider) ClearCluster() {
   224  	todolist := []ActionName{
   225  		ReleaseEIP,
   226  		ClearInstances,
   227  		DeleteVSwitch,
   228  		DeleteSecurityGroup,
   229  		DeleteVPC,
   230  	}
   231  	for _, name := range todolist {
   232  		DeleteFuncMap[name](a)
   233  	}
   234  }
   235  
   236  func (a *AliProvider) Reconcile() error {
   237  	if a.Cluster.Annotations == nil {
   238  		a.Cluster.Annotations = make(map[string]string)
   239  	}
   240  	if a.Cluster.DeletionTimestamp != nil {
   241  		logrus.Info("DeletionTimestamp not nil Clear Cluster")
   242  		a.ClearCluster()
   243  		return nil
   244  	}
   245  	if a.Cluster.Spec.SSH.Passwd == "" {
   246  		// Create ssh password
   247  		a.CreatePassword()
   248  	}
   249  	todolist := []ActionName{
   250  		CreateVPC,
   251  		GetZoneID,
   252  		CreateVSwitch,
   253  		CreateSecurityGroup,
   254  		ReconcileInstance,
   255  		BindEIP,
   256  	}
   257  
   258  	for _, actionname := range todolist {
   259  		err := RecocileFuncMap[actionname](a)
   260  		if err != nil {
   261  			return err
   262  		}
   263  	}
   264  
   265  	return nil
   266  }
   267  
   268  func (a *AliProvider) Apply() error {
   269  	return a.Reconcile()
   270  }