From 75c03473ee7479b3881aa5bca33006d906a73574 Mon Sep 17 00:00:00 2001 From: Sooyoung Kim Date: Tue, 25 Jun 2024 19:03:00 +0900 Subject: [PATCH] [NHNCloud:PMKS] Allow blank and default node image --- .../nhncloud/resources/ClusterHandler.go | 156 ++++++++++++++++-- go.mod | 8 +- go.sum | 16 +- 3 files changed, 150 insertions(+), 30 deletions(-) diff --git a/cloud-control-manager/cloud-driver/drivers/nhncloud/resources/ClusterHandler.go b/cloud-control-manager/cloud-driver/drivers/nhncloud/resources/ClusterHandler.go index dfb2db317..8bb2050b7 100644 --- a/cloud-control-manager/cloud-driver/drivers/nhncloud/resources/ClusterHandler.go +++ b/cloud-control-manager/cloud-driver/drivers/nhncloud/resources/ClusterHandler.go @@ -38,11 +38,12 @@ import ( ) const ( - clusterTemplateId = "iaas_console" - createTimeout = 60 - secgroupPostfix = "secgroup_kube_minion" - masterNodeGroup = "default-master" - publicNetworkSubnet = "Public Network Subnet" + clusterTemplateId = "iaas_console" + createTimeout = 60 + secgroupPostfix = "secgroup_kube_minion" + masterNodeGroup = "default-master" + publicNetworkSubnet = "Public Network Subnet" + defaultContainerImageNamePrefix = "Ubuntu Server 22" clusterLabelsAvailabilityZone = "availability_zone" clusterLabelsCertManagerApi = "cert_manager_api" @@ -155,7 +156,7 @@ func (nch *NhnCloudClusterHandler) CreateCluster(clusterReqInfo irs.ClusterInfo) // // Create Cluster // - clusterId, err = nch.createCluster(clusterReqInfo) + clusterId, err = nch.createCluster(&clusterReqInfo) if err != nil { createErr = fmt.Errorf("Failed to Create Cluster: %v", err) return emptyClusterInfo, createErr @@ -990,7 +991,7 @@ func (nch *NhnCloudClusterHandler) getLabelsForCluster(clusterInfo *irs.ClusterI // https://docs.nhncloud.com/ko/Container/NKS/ko/public-api/#_15 - nodeImage := nodeGroupInfo.ImageIID.SystemId + nodeImage := nodeGroupInfo.ImageIID.NameId certManagerApi := "True" clusterautoscale := "nodegroupfeature" @@ -1252,8 +1253,36 @@ func (nch *NhnCloudClusterHandler) getClusterSecGroupId(cluster *clusters.Cluste return &irs.IID{}, nil } -func (nch *NhnCloudClusterHandler) createCluster(clusterReqInfo irs.ClusterInfo) (string, error) { - firstNodeGroupInfo := clusterReqInfo.NodeGroupList[0] +func (nch *NhnCloudClusterHandler) createCluster(clusterReqInfo *irs.ClusterInfo) (string, error) { + clusterName := clusterReqInfo.IId.NameId + firstNodeGroupInfo := &clusterReqInfo.NodeGroupList[0] + + imageName := firstNodeGroupInfo.ImageIID.NameId + + if strings.EqualFold(imageName, "") || strings.EqualFold(imageName, "default") { + image, err := nch.getContainerImageByNamePrefix(defaultContainerImageNamePrefix) + if err != nil { + err = fmt.Errorf("failed to create a cluster(%s): %v", clusterName, err) + return "", err + } + firstNodeGroupInfo.ImageIID.NameId = image.ID + } else { + isValid, err := nch.isValidContainerImageId(imageName) + if err != nil { + err = fmt.Errorf("failed to create a cluster(%s): %v", clusterName, err) + return "", err + } + if isValid == false { + imageList, err := nch.getAvailableContainerImageList() + if err != nil { + err = fmt.Errorf("failed to create a cluster(%s): %v", clusterName, err) + return "", err + } + + err = fmt.Errorf("available container images: (" + strings.Join(imageList, ", ") + ")") + return "", fmt.Errorf("failed to create a cluster(%s): %v", clusterName, err) + } + } flavorName := firstNodeGroupInfo.VMSpecName flavorId, err := nch.getFlavorIdByName(flavorName) @@ -1265,13 +1294,12 @@ func (nch *NhnCloudClusterHandler) createCluster(clusterReqInfo irs.ClusterInfo) fixedSubnet := clusterReqInfo.Network.SubnetIIDs[0].SystemId keyPair := firstNodeGroupInfo.KeyPairIID.NameId - labels, err := nch.getLabelsForCluster(&clusterReqInfo, &firstNodeGroupInfo) + labels, err := nch.getLabelsForCluster(clusterReqInfo, firstNodeGroupInfo) if err != nil { return "", err } - clusterName := clusterReqInfo.IId.NameId - nodeCount := clusterReqInfo.NodeGroupList[0].DesiredNodeSize + nodeCount := firstNodeGroupInfo.DesiredNodeSize timeout := createTimeout uuid, err := nhnCreateCluster(nch.ClusterClient, clusterName, timeout, fixedNetwork, fixedSubnet, flavorId, keyPair, labels, nodeCount) @@ -1501,7 +1529,39 @@ func (nch *NhnCloudClusterHandler) createNodeGroup(clusterId string, nodeGroupRe nodeCount := nodeGroupReqInfo.DesiredNodeSize minNodeCount := nodeGroupReqInfo.MinNodeSize maxNodeCount := nodeGroupReqInfo.MaxNodeSize - imageId := nodeGroupReqInfo.ImageIID.SystemId + + imageName := nodeGroupReqInfo.ImageIID.NameId + imageId := "" + + if strings.EqualFold(imageName, "") || strings.EqualFold(imageName, "default") { + image, err := nch.getContainerImageByNamePrefix(defaultContainerImageNamePrefix) + if err != nil { + err = fmt.Errorf("failed to create a node group(%s) of cluster(id=%s): %v", + nodeGroupName, clusterId, err) + return "", err + } + imageId = image.ID + } else { + isValid, err := nch.isValidContainerImageId(imageName) + if err != nil { + err = fmt.Errorf("failed to create a node group(%s) of cluster(id=%s): %v", + nodeGroupName, clusterId, err) + return "", err + } + if isValid == false { + imageList, err := nch.getAvailableContainerImageList() + if err != nil { + err = fmt.Errorf("failed to create a node group(%s) of cluster(id=%s): %v", + nodeGroupName, clusterId, err) + return "", err + } + + err = fmt.Errorf("available container images: (" + strings.Join(imageList, ", ") + ")") + return "", fmt.Errorf("failed to create a node group(%s) of cluster(id=%s): %v", + nodeGroupName, clusterId, err) + } + } + flavorId, err := nch.getFlavorIdByName(nodeGroupReqInfo.VMSpecName) if err != nil { err = fmt.Errorf("failed to create a node group(%s) of cluster(id=%s): %v", @@ -1563,6 +1623,51 @@ func (nch *NhnCloudClusterHandler) getFlavorNameById(flavorId string) (string, e return "", fmt.Errorf("failed to find a flavor by id(%s)", flavorId) } +func (nch *NhnCloudClusterHandler) isValidContainerImageId(imageId string) (bool, error) { + imageList, err := nhnGetContainerImageList(nch.ImageClient) + if err != nil { + return false, err + } + + for _, image := range imageList { + if strings.EqualFold(image.ID, imageId) { + return true, nil + } + } + + return false, nil +} + +func (nch *NhnCloudClusterHandler) getContainerImageByNamePrefix(imageNamePrefix string) (images.Image, error) { + imageList, err := nhnGetContainerImageList(nch.ImageClient) + if err != nil { + return images.Image{}, err + } + + for _, image := range imageList { + if strings.Contains(image.Name, imageNamePrefix) { + return image, nil + } + } + + return images.Image{}, fmt.Errorf("no container image with name prefix(%s)", imageNamePrefix) +} + +func (nch *NhnCloudClusterHandler) getAvailableContainerImageList() ([]string, error) { + var containerImageList []string + imageList, err := nhnGetContainerImageList(nch.ImageClient) + if err != nil { + return []string{}, err + } + + for _, image := range imageList { + nameAndId := fmt.Sprintf("%s[ID=%s]", image.Name, image.ID) + containerImageList = append(containerImageList, nameAndId) + } + + return containerImageList, nil +} + func (nch *NhnCloudClusterHandler) getServerListByAddresses(imageId, flavorId string, addresses []string) ([]servers.Server, error) { emptyServerList := make([]servers.Server, 0) @@ -1775,6 +1880,26 @@ func nhnGetImageList(scImage *nhnsdk.ServiceClient) ([]images.Image, error) { return imageList, nil } +func nhnGetContainerImageList(scImage *nhnsdk.ServiceClient) ([]images.Image, error) { + emptyImageList := make([]images.Image, 0) + + listOpts := images.ListOpts{ + Visibility: images.ImageVisibilityPublic, + NhncloudProduct: images.ImageNhncloudProductContainer, + } + allPages, err := images.List(scImage, listOpts).AllPages() + if err != nil { + return emptyImageList, fmt.Errorf("failed to get container images' list: %v", err) + } + + imageList, err := images.ExtractImages(allPages) + if err != nil { + return emptyImageList, fmt.Errorf("failed to extract images: %v", err) + } + + return imageList, nil +} + func nhnGetImageById(scImage *nhnsdk.ServiceClient, imageId string) (*images.Image, error) { image, err := images.Get(scImage, imageId).Extract() if err != nil { @@ -2008,11 +2133,6 @@ func validateNodeGroupInfoList(nodeGroupInfoList []irs.NodeGroupInfo) error { return fmt.Errorf("Node Group's keypair is required") } firstKeypairId = &nodeGroupInfo.KeyPairIID - - if nodeGroupInfo.ImageIID.NameId == "" && nodeGroupInfo.ImageIID.SystemId == "" { - return fmt.Errorf("Node Group's image is required") - } - } else { // NameId, SystemId 둘다 값이 있음 if nodeGroupInfo.KeyPairIID.NameId != "" && nodeGroupInfo.KeyPairIID.SystemId != "" { diff --git a/go.mod b/go.mod index 046d2eb31..9821341ac 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/aws/aws-sdk-go v1.39.4 github.com/bramvdbogaerde/go-scp v1.0.0 github.com/chyeh/pubip v0.0.0-20170203095919-b7e679cf541c - github.com/cloud-barista/cb-log v0.8.0 + github.com/cloud-barista/cb-log v0.8.2 github.com/davecgh/go-spew v1.1.1 github.com/docker/docker v24.0.9+incompatible github.com/docker/go-connections v0.4.0 @@ -67,14 +67,14 @@ require ( github.com/alibabacloud-go/vpc-20160428/v6 v6.4.0 github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240524035950-e31ad87778e0 - github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240415072030-38f4f47c26a1 + github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240625103041-e12be4707a93 github.com/go-openapi/strfmt v0.21.3 github.com/hashicorp/go-version v1.6.0 github.com/jeremywohl/flatten v1.0.1 github.com/labstack/echo/v4 v4.9.0 github.com/tencentcloud/tencentcloud-sdk-go-intl-en v3.0.531+incompatible github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cbs v1.0.492 - golang.org/x/mod v0.17.0 + golang.org/x/mod v0.18.0 k8s.io/api v0.22.5 k8s.io/apimachinery v0.22.5 k8s.io/client-go v0.22.5 @@ -188,7 +188,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.11.0 // indirect golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect + golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.5.0 // indirect diff --git a/go.sum b/go.sum index 6bbee6a2b..05dcbffcf 100644 --- a/go.sum +++ b/go.sum @@ -176,14 +176,14 @@ github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloud-barista/cb-log v0.8.0 h1:ArWCs1EgpoD3ZnBgcC4cAw5ufI/JHmFKfJswlv4whgk= -github.com/cloud-barista/cb-log v0.8.0/go.mod h1:nGgfTFMPwl1MpCO3FBjexUkNdOYA0BNJoyM9Pd0lMms= +github.com/cloud-barista/cb-log v0.8.2 h1:hPCbLj6TW6m9UWlq002sDuGgxKFVp68w4V3k493+MxY= +github.com/cloud-barista/cb-log v0.8.2/go.mod h1:nGgfTFMPwl1MpCO3FBjexUkNdOYA0BNJoyM9Pd0lMms= github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb h1:JAQQ/wBdkcoGCeim+J84F8hIuxbtn/XTe/iDYRsr+t0= github.com/cloud-barista/ktcloud-sdk-go v0.2.1-0.20240123114820-8684cfc5deeb/go.mod h1:ZIrUxItUvMIGZyX6Re7tUdcS3cwBIzBPcL+Pk/6lt/8= github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240524035950-e31ad87778e0 h1:mnQnZHMwt8V/WihpgnIDcqK9fsLE8A+uTdVSGdPaQ+Q= github.com/cloud-barista/ktcloudvpc-sdk-go v0.0.0-20240524035950-e31ad87778e0/go.mod h1:SDTNI+0ZyoEWhQKHASGwhS1a9kad+mxsXCKSfnpWnSA= -github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240415072030-38f4f47c26a1 h1:o6RVnxI2E6o3l7Sc285gg45S6hcepAklfPPDDmlvKHY= -github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240415072030-38f4f47c26a1/go.mod h1:G+VjfmHi5IUt0oe14A5UXmbrGFlMTMQjLonBuvjy8Yc= +github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240625103041-e12be4707a93 h1:LuBViHtI740uRg6U5g/m//HXsaHLxnTdQIuk85S4XNc= +github.com/cloud-barista/nhncloud-sdk-go v0.0.0-20240625103041-e12be4707a93/go.mod h1:G+VjfmHi5IUt0oe14A5UXmbrGFlMTMQjLonBuvjy8Yc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -843,8 +843,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1013,8 +1013,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=