Skip to content

Commit

Permalink
[k8scluster] update k8scluster dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
cb-github-robot authored Nov 1, 2024
2 parents 05e4991 + 7b75eff commit 654e1e3
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 112 deletions.
10 changes: 5 additions & 5 deletions src/api/rest/server/resource/k8scluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ func RestPostK8sClusterDynamicCheckRequest(c echo.Context) error {
// @Accept json
// @Produce json
// @Param nsId path string true "Namespace ID" default(default)
// @Param k8sclusterReq body model.TbK8sClusterDynamicReq true "Request body to provision K8sCluster dynamically. <br> Must include commonSpec and commonImage info. <br> (ex: {name: k8scluster-01, commonImage: azure+koreacentral+ubuntu22.04, commonSpec: azure+koreacentral+Standard_B2s}]}) <br> You can use /k8sclusterRecommendNode and /k8sclusterDynamicCheckRequest to get it. <br> Check the guide: https://github.com/cloud-barista/cb-tumblebug/discussions/1570"
// @Param k8sclusterReq body model.TbK8sClusterDynamicReq true "Request body to provision K8sCluster dynamically. <br> Must include commonSpec and commonImage info. <br> (ex: {name: k8scluster-01, commonImage: azure+koreacentral+ubuntu22.04, commonSpec: azure+koreacentral+Standard_B2s}]}) <br> You can use /k8sclusterRecommendNode and /k8sclusterDynamicCheckRequest to get it. <br> Check the guide: https://github.com/cloud-barista/cb-tumblebug/discussions/1913"
// @Param option query string false "Option for K8sCluster creation" Enums(hold)
// @Param x-request-id header string false "Custom request ID"
// @Success 200 {object} model.TbK8sClusterInfo
Expand Down Expand Up @@ -640,8 +640,8 @@ func RestGetControlK8sCluster(c echo.Context) error {
}
}

// RestRecommendNode godoc
// @ID RecommendNode
// RestRecommendK8sNode godoc
// @ID RecommendK8sNode
// @Summary Recommend K8sCluster's Node plan (filter and priority)
// @Description Recommend K8sCluster's Node plan (filter and priority) Find details from https://github.com/cloud-barista/cb-tumblebug/discussions/1234
// @Tags [Kubernetes] Cluster Management
Expand All @@ -652,7 +652,7 @@ func RestGetControlK8sCluster(c echo.Context) error {
// @Failure 404 {object} model.SimpleMsg
// @Failure 500 {object} model.SimpleMsg
// @Router /k8sclusterRecommendNode [post]
func RestRecommendNode(c echo.Context) error {
func RestRecommendK8sNode(c echo.Context) error {

nsId := model.SystemCommonNs

Expand All @@ -661,6 +661,6 @@ func RestRecommendNode(c echo.Context) error {
return common.EndRequestWithLog(c, err, nil)
}

content, err := infra.RecommendVm(nsId, *u)
content, err := infra.RecommendK8sNode(nsId, *u)
return common.EndRequestWithLog(c, err, content)
}
2 changes: 1 addition & 1 deletion src/api/rest/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ func RunServer() {
g.DELETE("/:nsId/k8scluster", rest_resource.RestDeleteAllK8sCluster)
g.PUT("/:nsId/k8scluster/:k8sClusterId/upgrade", rest_resource.RestPutUpgradeK8sCluster)

e.POST("/tumblebug/k8sclusterRecommendNode", rest_resource.RestRecommendNode)
e.POST("/tumblebug/k8sclusterRecommendNode", rest_resource.RestRecommendK8sNode)
e.POST("/tumblebug/k8sclusterDynamicCheckRequest", rest_resource.RestPostK8sClusterDynamicCheckRequest)
g.POST("/:nsId/k8sclusterDynamic", rest_resource.RestPostK8sClusterDynamic)
g.GET("/:nsId/control/k8scluster/:k8sClusterId", rest_resource.RestGetControlK8sCluster)
Expand Down
101 changes: 24 additions & 77 deletions src/core/common/utility.go
Original file line number Diff line number Diff line change
Expand Up @@ -1498,92 +1498,39 @@ func GetModelK8sRequiredSubnetCount(providerName string) (*model.K8sClusterRequi
}, nil
}

/*
func isValidSpecForK8sCluster(spec *resource.TbSpecInfo) bool {
//
// Check for Provider
//
func FilterDigitsAndDots(input string) string {
re := regexp.MustCompile(`[^0-9.]`)
return re.ReplaceAllString(input, "")
}

providerName := strings.ToLower(spec.ProviderName)
func CompareVersions(version1, version2 string) int {
v1Parts := strings.Split(version1, ".")
v2Parts := strings.Split(version2, ".")

var k8sClusterDetail *common.model.K8sClusterDetail = nil
for provider, detail := range common.RuntimeK8sClusterInfo.CSPs {
provider = strings.ToLower(provider)
if provider == providerName {
k8sClusterDetail = &detail
break
}
}
if k8sClusterDetail == nil {
return false
// Adjust length by appending 0 if necessary
maxLength := len(v1Parts)
if len(v2Parts) > maxLength {
maxLength = len(v2Parts)
}

//
// Check for Region
//
regionName := strings.ToLower(spec.RegionName)
for i := 0; i < maxLength; i++ {
var v1, v2 int

// Check for Version
isExist := false
for _, versionDetail := range k8sClusterDetail.Version {
for _, region := range versionDetail.Region {
region = strings.ToLower(region)
if region == "all" || region == regionName {
if len(versionDetail.Available) > 0 {
isExist = true
break
}
}
// If a part is missing, treat it as 0
if i < len(v1Parts) {
v1, _ = strconv.Atoi(v1Parts[i])
}
if isExist == true {
break
if i < len(v2Parts) {
v2, _ = strconv.Atoi(v2Parts[i])
}
}
if isExist == false {
return false
}

// Check for NodeImage
isExist = false
for _, nodeImageDetail := range k8sClusterDetail.NodeImage {
for _, region := range nodeImageDetail.Region {
region = strings.ToLower(region)
if region == "all" || region == regionName {
if len(nodeImageDetail.Available) > 0 {
isExist = true
break
}
}
}
if isExist == true {
break
// Compare each part
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
}
if isExist == false {
return false
}

// Check for RootDisk
isExist = false
for _, rootDiskDetail := range k8sClusterDetail.RootDisk {
for _, region := range rootDiskDetail.Region {
region = strings.ToLower(region)
if region == "all" || region == regionName {
if len(rootDiskDetail.Type) > 0 {
isExist = true
break
}
}
}
if isExist == true {
break
}
}
if isExist == false {
return false
}
return true
return 0
}
*/
69 changes: 44 additions & 25 deletions src/core/infra/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package infra
import (
"encoding/json"
"fmt"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -1669,15 +1668,17 @@ func filterCheckMciDynamicReqInfoToCheckK8sClusterDynamicReqInfo(mciDReqInfo *mo
}
}

nodeDReqInfo := model.CheckNodeDynamicReqInfo{
ConnectionConfigCandidates: k.ConnectionConfigCandidates,
Spec: k.Spec,
Image: imageListForK8s,
Region: k.Region,
SystemMessage: k.SystemMessage,
}
if len(imageListForK8s) > 0 {
nodeDReqInfo := model.CheckNodeDynamicReqInfo{
ConnectionConfigCandidates: k.ConnectionConfigCandidates,
Spec: k.Spec,
Image: imageListForK8s,
Region: k.Region,
SystemMessage: k.SystemMessage,
}

k8sDReqInfo.ReqCheck = append(k8sDReqInfo.ReqCheck, nodeDReqInfo)
k8sDReqInfo.ReqCheck = append(k8sDReqInfo.ReqCheck, nodeDReqInfo)
}
}
}
}
Expand All @@ -1703,11 +1704,6 @@ func CheckK8sClusterDynamicReq(req *model.K8sClusterConnectionConfigCandidatesRe
return k8sDReqInfo, err
}

func filterDigitsAndDots(input string) string {
re := regexp.MustCompile(`[^0-9.]`)
return re.ReplaceAllString(input, "")
}

func getK8sRecommendVersion(providerName, regionName, reqVersion string) (string, error) {
availableVersion, err := common.GetAvailableK8sVersion(providerName, regionName)
if err != nil {
Expand All @@ -1718,17 +1714,29 @@ func getK8sRecommendVersion(providerName, regionName, reqVersion string) (string

recVersion := model.StrEmpty
versionIdList := []string{}
for _, verDetail := range *availableVersion {
versionIdList = append(versionIdList, verDetail.Id)
if strings.EqualFold(reqVersion, verDetail.Id) {
recVersion = verDetail.Id
break
} else {
availVersion := filterDigitsAndDots(verDetail.Id)
filteredReqVersion := filterDigitsAndDots(reqVersion)
if strings.HasPrefix(availVersion, filteredReqVersion) {
recVersion = availVersion

if reqVersion == "" {
for _, verDetail := range *availableVersion {
versionIdList = append(versionIdList, verDetail.Id)
filteredRecVersion := common.FilterDigitsAndDots(recVersion)
filteredAvailVersion := common.FilterDigitsAndDots(verDetail.Id)
if common.CompareVersions(filteredRecVersion, filteredAvailVersion) < 0 {
recVersion = verDetail.Id
}
}
} else {
for _, verDetail := range *availableVersion {
versionIdList = append(versionIdList, verDetail.Id)
if strings.EqualFold(reqVersion, verDetail.Id) {
recVersion = verDetail.Id
break
} else {
availVersion := common.FilterDigitsAndDots(verDetail.Id)
filteredReqVersion := common.FilterDigitsAndDots(reqVersion)
if strings.HasPrefix(availVersion, filteredReqVersion) {
recVersion = availVersion
break
}
}
}
}
Expand Down Expand Up @@ -1943,10 +1951,21 @@ func getK8sClusterReqFromDynamicReq(reqID string, nsId string, dReq *model.TbK8s
k8sngReq.RootDiskType = dReq.RootDiskType
k8sngReq.RootDiskSize = dReq.RootDiskSize
k8sngReq.OnAutoScaling = dReq.OnAutoScaling
if k8sngReq.OnAutoScaling == "" {
k8sngReq.OnAutoScaling = "true"
}
k8sngReq.DesiredNodeSize = dReq.DesiredNodeSize
if k8sngReq.DesiredNodeSize == "" {
k8sngReq.DesiredNodeSize = "1"
}
k8sngReq.MinNodeSize = dReq.MinNodeSize
if k8sngReq.MinNodeSize == "" {
k8sngReq.MinNodeSize = "1"
}
k8sngReq.MaxNodeSize = dReq.MaxNodeSize

if k8sngReq.MaxNodeSize == "" {
k8sngReq.MaxNodeSize = "2"
}
k8sReq.Description = dReq.Description
k8sReq.Name = dReq.Name
if k8sReq.Name == "" {
Expand Down
33 changes: 33 additions & 0 deletions src/core/infra/recommendation.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,39 @@ func RecommendVmPerformance(nsId string, specList *[]model.TbSpecInfo) ([]model.
return result, nil
}

// RecommendK8sNode is func to recommend a node for K8sCluster
func RecommendK8sNode(nsId string, plan model.DeploymentPlan) ([]model.TbSpecInfo, error) {
emptyObjList := []model.TbSpecInfo{}

limitOrig := plan.Limit
plan.Limit = strconv.Itoa(math.MaxInt)

tbSpecInfoListForVm, err := RecommendVm(nsId, plan)
if err != nil {
return emptyObjList, err
}

limitNum, err := strconv.Atoi(limitOrig)
if err != nil {
limitNum = math.MaxInt
}

tbSpecInfoListForK8s := []model.TbSpecInfo{}
count := 0
for _, tbSpecInfo := range tbSpecInfoListForVm {
if strings.Contains(tbSpecInfo.InfraType, model.StrK8s) ||
strings.Contains(tbSpecInfo.InfraType, model.StrKubernetes) {
tbSpecInfoListForK8s = append(tbSpecInfoListForK8s, tbSpecInfo)
count++
if count == limitNum {
break
}
}
}

return tbSpecInfoListForK8s, nil
}

// // GetRecommendList is func to get recommendation list
// func GetRecommendList(nsId string, cpuSize string, memSize string, diskSize string) ([]TbVmPriority, error) {

Expand Down
8 changes: 4 additions & 4 deletions src/core/model/k8scluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ type TbK8sAddonsInfo struct {
// K8sClusterConnectionConfigCandidatesReq is struct for a request to check requirements to create a new K8sCluster instance dynamically (with default resource option)
type K8sClusterConnectionConfigCandidatesReq struct {
// CommonSpec is field for id of a spec in common namespace
CommonSpecs []string `json:"commonSpec" validate:"required" example:"azure+koreacentral+Standard_B2s"`
CommonSpecs []string `json:"commonSpec" validate:"required" example:"tencent+ap-seoul+S2.MEDIUM4"`
}

// CheckK8sClusterDynamicReqInfo is struct to check requirements to create a new K8sCluster instance dynamically (with default resource option)
Expand Down Expand Up @@ -500,10 +500,10 @@ type TbK8sClusterDynamicReq struct {
NodeGroupName string `json:"nodeGroupName" example:"nodegroup-01"`

// CommonSpec is field for id of a spec in common namespace
CommonSpec string `json:"commonSpec" validate:"required" example:"azure+koreacentral+standard_b2s"`
CommonSpec string `json:"commonSpec" validate:"required" example:"tencent+ap-seoul+S2.MEDIUM4"`

// CommonImage is field for id of a image in common namespace
CommonImage string `json:"commonImage" validate:"required" example:"default, azure+koreacentrall+ubuntu20.04"`
CommonImage string `json:"commonImage" validate:"required" example:"default, tencent+ap-seoul+ubuntu20.04"`

RootDiskType string `json:"rootDiskType,omitempty" example:"default, TYPE1, ..." default:"default"` // "", "default", "TYPE1", AWS: ["standard", "gp2", "gp3"], Azure: ["PremiumSSD", "StandardSSD", "StandardHDD"], GCP: ["pd-standard", "pd-balanced", "pd-ssd", "pd-extreme"], ALIBABA: ["cloud_efficiency", "cloud", "cloud_essd"], TENCENT: ["CLOUD_PREMIUM", "CLOUD_SSD"]
RootDiskSize string `json:"rootDiskSize,omitempty" example:"default, 30, 42, ..." default:"default"` // "default", Integer (GB): ["50", ..., "1000"]
Expand All @@ -515,5 +515,5 @@ type TbK8sClusterDynamicReq struct {

// if ConnectionName is given, the VM tries to use associtated credential.
// if not, it will use predefined ConnectionName in Spec objects
ConnectionName string `json:"connectionName,omitempty" default:"azure-koreacentral"`
ConnectionName string `json:"connectionName,omitempty" default:"tencent-ap-seoul"`
}

0 comments on commit 654e1e3

Please sign in to comment.