From febca8e61e96fb1c79be5b4b8948518aee2123c3 Mon Sep 17 00:00:00 2001 From: Daniel Isen Date: Mon, 25 Nov 2024 17:23:07 -0500 Subject: [PATCH] [CLOUDGA-24851] Remove root node info from cluster creation --- Makefile | 3 + cmd/cluster/create_cluster.go | 36 +----- go.mod | 14 +-- go.sum | 18 ++- internal/client/client.go | 216 ++++++++++++---------------------- 5 files changed, 102 insertions(+), 185 deletions(-) diff --git a/Makefile b/Makefile index 5739f74f..ce33d545 100644 --- a/Makefile +++ b/Makefile @@ -38,3 +38,6 @@ update-cli: clean: rm -rf ybm + +fmt: + go fmt ./... diff --git a/cmd/cluster/create_cluster.go b/cmd/cluster/create_cluster.go index f97e1d49..9c2930e7 100644 --- a/cmd/cluster/create_cluster.go +++ b/cmd/cluster/create_cluster.go @@ -18,9 +18,9 @@ package cluster import ( "fmt" "os" - "strconv" "strings" + "encoding/base64" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -29,7 +29,6 @@ import ( ybmAuthClient "github.com/yugabyte/ybm-cli/internal/client" "github.com/yugabyte/ybm-cli/internal/formatter" ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal" - "encoding/base64" ) func encodeBase64(s string) string { @@ -55,25 +54,6 @@ var createClusterCmd = &cobra.Command{ password := credentials["password"] regionInfoMapList := []map[string]string{} changedRegionInfo := cmd.Flags().Changed("region-info") - changedNodeInfo := cmd.Flags().Changed("node-config") - - defaultNumCores := 0 - defaultDiskSizeGb := 0 - defaultDiskIops := 0 - if changedNodeInfo { - nodeConfig, _ := cmd.Flags().GetStringToInt("node-config") - numCores, ok := nodeConfig["num-cores"] - - if ok { - defaultNumCores = numCores - } - if diskSizeGb, ok := nodeConfig["disk-size-gb"]; ok { - defaultDiskSizeGb = diskSizeGb - } - if diskIops, ok := nodeConfig["disk-iops"]; ok { - defaultDiskIops = diskIops - } - } if changedRegionInfo { regionInfoList, _ := cmd.Flags().GetStringArray("region-info") @@ -120,14 +100,11 @@ var createClusterCmd = &cobra.Command{ if _, ok := regionInfoMap["num-nodes"]; !ok { logrus.Fatalln("Number of nodes not specified in region info") } - if _, ok := regionInfoMap["num-cores"]; !ok && defaultNumCores > 0 { - regionInfoMap["num-cores"] = strconv.Itoa(defaultNumCores) - } - if _, ok := regionInfoMap["disk-size-gb"]; !ok && defaultDiskSizeGb > 0 { - regionInfoMap["disk-size-gb"] = strconv.Itoa(defaultDiskSizeGb) + if _, ok := regionInfoMap["num-cores"]; !ok { + logrus.Fatalln("Number of cores not specified in region info") } - if _, ok := regionInfoMap["disk-iops"]; !ok && defaultDiskIops > 0 { - regionInfoMap["disk-iops"] = strconv.Itoa(defaultDiskIops) + if _, ok := regionInfoMap["disk-size-gb"]; !ok { + logrus.Fatalln("Disk size not specified in region info") } regionInfoMapList = append(regionInfoMapList, regionInfoMap) @@ -231,9 +208,8 @@ func init() { If specified, all parameters for that provider are mandatory.`) createClusterCmd.Flags().String("fault-tolerance", "", "[OPTIONAL] Fault tolerance of the cluster. The possible values are NONE, NODE, ZONE, or REGION. Default NONE.") createClusterCmd.Flags().Int32("num-faults-to-tolerate", 0, "[OPTIONAL] The number of domain faults to tolerate for the level specified. The possible values are 0 for NONE, 1 for ZONE and [1-3] for anything else. Defaults to 0 for NONE, 1 otherwise.") - createClusterCmd.Flags().StringToInt("node-config", nil, "[OPTIONAL] Number of vCPUs and disk size per node for the cluster, provided as key-value pairs. Arguments are num-cores=,disk-size-gb=,disk-iops= (AWS only). num-cores is required.") - createClusterCmd.Flags().MarkDeprecated("node-config", "use --region-info to specify num-cores, disk-size-gb, and disk-iops") createClusterCmd.Flags().StringArray("region-info", []string{}, `Region information for the cluster, provided as key-value pairs. Arguments are region=,num-nodes=,vpc=,num-cores=,disk-size-gb=,disk-iops= (AWS only). region, num-nodes, num-cores, disk-size-gb are required. Specify one --region-info flag for each region in the cluster.`) + createClusterCmd.MarkFlagRequired("region-info") createClusterCmd.Flags().String("preferred-region", "", "[OPTIONAL] The preferred region in a multi region cluster. The preferred region handles all read and write requests from clients.") createClusterCmd.Flags().String("default-region", "", "[OPTIONAL] The primary region in a partition-by-region cluster. The primary region is where all the tables not created in a tablespace reside.") } diff --git a/go.mod b/go.mod index 5a02623d..7b89e317 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/jayco/go-emoji-flag v0.0.0-20190810054606-01604da018da github.com/mattn/go-runewidth v0.0.14 github.com/onsi/ginkgo/v2 v2.20.1 - github.com/onsi/gomega v1.34.2 + github.com/onsi/gomega v1.36.0 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/pkg/errors v0.9.1 github.com/robfig/cron v1.2.0 @@ -26,7 +26,7 @@ require ( github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20241116155807-eab59d10ab1c golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/mod v0.20.0 - golang.org/x/term v0.23.0 + golang.org/x/term v0.25.0 gotest.tools/v3 v3.4.0 ) @@ -72,14 +72,14 @@ require ( github.com/spf13/cast v1.5.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - golang.org/x/crypto v0.26.0 // indirect - golang.org/x/net v0.28.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.24.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5009c8de..d395dab1 100644 --- a/go.sum +++ b/go.sum @@ -218,8 +218,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= +github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= @@ -282,8 +282,6 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= -github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20241103123630-73a2876ea773 h1:t+n2/bsR3vGpFoPKjs0vlzErRcxlVR8YHBEZawlYSa0= -github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20241103123630-73a2876ea773/go.mod h1:5vW0xIzIZw+1djkiWKx0qqNmqbRBSf4mjc4qw8lIMik= github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20241116155807-eab59d10ab1c h1:NhSquu8YYg8yQrceEmVkxYg/kwpvqXodSa2qw0/AlGk= github.com/yugabyte/yugabytedb-managed-go-client-internal v0.0.0-20241116155807-eab59d10ab1c/go.mod h1:5vW0xIzIZw+1djkiWKx0qqNmqbRBSf4mjc4qw8lIMik= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -371,8 +369,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -402,8 +400,8 @@ golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -553,8 +551,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= diff --git a/internal/client/client.go b/internal/client/client.go index c6175091..66b110fc 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -38,7 +38,7 @@ import ( "golang.org/x/exp/slices" ) -// AuthApiClient is a auth YugabyteDB Aeon Client +// AuthApiClient is an auth YugabyteDB Aeon Client var cliVersion = "v0.1.0" @@ -57,9 +57,9 @@ func GetVersion() string { return cliVersion } -// NewAuthClient function is returning a new AuthApiClient Client +// NewAuthApiClient NewAuthClient function is returning a new AuthApiClient Client func NewAuthApiClient() (*AuthApiClient, error) { - url, err := ParseURL(viper.GetString("host")) + parseURL, err := ParseURL(viper.GetString("host")) if err != nil { logrus.Error(err) return nil, err @@ -71,7 +71,7 @@ func NewAuthApiClient() (*AuthApiClient, error) { logrus.Fatalln("No valid API key detected. Please run `ybm auth` to authenticate with YugabyteDB Aeon.") } - return NewAuthApiClientCustomUrlKey(url, apiKey) + return NewAuthApiClientCustomUrlKey(parseURL, apiKey) } func NewAuthApiClientCustomUrlKey(url *url.URL, apiKey string) (*AuthApiClient, error) { @@ -148,15 +148,11 @@ func (a *AuthApiClient) GetProjectID(projectID string) (string, error) { func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []map[string]string, regionNodeConfigsMap map[string][]ybmclient.NodeConfigurationResponseItem) (*ybmclient.ClusterSpec, error) { - var diskSizeGb int32 - var diskIops int32 - var memoryMb int32 var trackId string var trackName string - var regionInfoProvided bool var err error - clusterRegionInfo := []ybmclient.ClusterRegionInfo{} + var clusterRegionInfo []ybmclient.ClusterRegionInfo totalNodes := 0 regionNodeInfoMap := map[string]*ybmclient.OptionalClusterNodeInfo{} for _, regionInfo := range regionInfoList { @@ -174,7 +170,7 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma cloudInfo.SetCode(ybmclient.CloudEnum(cloudProvider)) } info := *ybmclient.NewClusterRegionInfo( - *ybmclient.NewPlacementInfo(cloudInfo, int32(regionNodes)), + *ybmclient.NewPlacementInfo(cloudInfo, regionNodes), ) if vpcName, ok := regionInfo["vpc"]; ok { vpcID, err := a.GetVpcIdByName(vpcName) @@ -218,15 +214,13 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma regionNodeInfoMap[region] = regionNodeInfo } - // This is to populate region in top level cloud info - region := "" regionCount := len(clusterRegionInfo) if regionCount > 0 { - regionInfoProvided = true - region = clusterRegionInfo[0].PlacementInfo.CloudInfo.Region if regionCount == 1 { clusterRegionInfo[0].SetIsDefault(true) } + } else { + return nil, fmt.Errorf("region info must be provided") } // For the default tier which is FREE, isProduction has to be false @@ -236,13 +230,10 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma if cmd.Flags().Changed("new-name") { clusterName, _ = cmd.Flags().GetString("new-name") } - cloudInfo := *ybmclient.NewCloudInfoWithDefaults() + cloud := "" if cmd.Flags().Changed("cloud-provider") { cloudProvider, _ := cmd.Flags().GetString("cloud-provider") - cloudInfo.SetCode(ybmclient.CloudEnum(cloudProvider)) - } - if regionInfoProvided { - cloudInfo.SetRegion(region) + cloud = cloudProvider } clusterInfo := *ybmclient.NewClusterInfoWithDefaults() @@ -267,7 +258,7 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma } if cmd.Flags().Changed("preferred-region") { preferredRegion, _ := cmd.Flags().GetString("preferred-region") - if clusterInfo.GetFaultTolerance() != ybmclient.ClusterFaultTolerance("REGION") { + if clusterInfo.GetFaultTolerance() != "REGION" { return nil, fmt.Errorf("preferred region is allowed only for regional level fault tolerance") } @@ -302,115 +293,78 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma clusterInfo.SetClusterType(ybmclient.ClusterType(clusterType)) } - cloud := string(cloudInfo.GetCode()) tier := string(clusterInfo.GetClusterTier()) - if regionInfoProvided { - geoPartitioned := clusterInfo.GetClusterType() == "GEO_PARTITIONED" - clusterNodeInfoWithDefaults := *ybmclient.NewClusterNodeInfoWithDefaults() - // Create slice of desired regions. - regions := make([]string, 0, len(regionNodeInfoMap)) - for k, _ := range regionNodeInfoMap { - regions = append(regions, k) - } + geoPartitioned := clusterInfo.GetClusterType() == "GEO_PARTITIONED" + clusterNodeInfoWithDefaults := *ybmclient.NewClusterNodeInfoWithDefaults() + // Create slice of desired regions. + regions := make([]string, 0, len(regionNodeInfoMap)) + for k := range regionNodeInfoMap { + regions = append(regions, k) + } - if regionNodeConfigsMap == nil { - // Grab available node configurations by region. - regionNodeConfigsMap = a.GetSupportedNodeConfigurationsV2(cloud, tier, regions, geoPartitioned) - } + if regionNodeConfigsMap == nil { + // Grab available node configurations by region. + regionNodeConfigsMap = a.GetSupportedNodeConfigurationsV2(cloud, tier, regions, geoPartitioned) + } - // Create slice of region keys of node configurations response. - nodeConfigurationsRegions := make([]string, 0, len(regionNodeConfigsMap)) - for k, _ := range regionNodeConfigsMap { - nodeConfigurationsRegions = append(nodeConfigurationsRegions, k) + // Create slice of region keys of node configurations response. + nodeConfigurationsRegions := make([]string, 0, len(regionNodeConfigsMap)) + for k := range regionNodeConfigsMap { + nodeConfigurationsRegions = append(nodeConfigurationsRegions, k) + } + // For each desired region, grab appropriate node configuration and set node info. + for _, r := range regions { + var nodeConfigs []ybmclient.NodeConfigurationResponseItem + if slices.Contains(nodeConfigurationsRegions, r) { + nodeConfigs = regionNodeConfigsMap[r] + } else { + // Requested region not found in node configurations map. + // In this case, the map key is a string of all (comma-separated) regions, + // and the value is a list of node configurations that are available in all regions. + // So, we just use look through the first map value to find a node configuration to use. + nodeConfigs = regionNodeConfigsMap[nodeConfigurationsRegions[0]] } - // For each desired region, grab appropriate node configuration and set node info. - for _, r := range regions { - nodeConfigs := []ybmclient.NodeConfigurationResponseItem{} - if slices.Contains(nodeConfigurationsRegions, r) { - nodeConfigs = regionNodeConfigsMap[r] - } else { - // Requested region not found in node configurations map. - // In this case, the map key is a string of all (comma-separated) regions, - // and the value is a list of node configurations that are available in all regions. - // So, we just use look through the first map value to find a node configuration to use. - nodeConfigs = regionNodeConfigsMap[nodeConfigurationsRegions[0]] - } - requestedNodeInfo := regionNodeInfoMap[r] - requestedNumCores := requestedNodeInfo.GetNumCores() - userProvidedNumCores := requestedNumCores != 0 + requestedNodeInfo := regionNodeInfoMap[r] + requestedNumCores := requestedNodeInfo.GetNumCores() + userProvidedNumCores := requestedNumCores != 0 - var nodeConfig *ybmclient.NodeConfigurationResponseItem = nil - if !userProvidedNumCores { - requestedNumCores = clusterNodeInfoWithDefaults.GetNumCores() - } - for i, nc := range nodeConfigs { - if nc.GetNumCores() == requestedNumCores { - nodeConfig = &nodeConfigs[i] - break - } - } - if nodeConfig == nil { - logrus.Fatalf("No instance type found with %d cores in region %s\n", requestedNumCores, r) - } - regionNodeInfoMap[r].SetNumCores(nodeConfig.GetNumCores()) - regionNodeInfoMap[r].SetMemoryMb(nodeConfig.GetMemoryMb()) - if requestedNodeInfo.GetDiskSizeGb() == 0 { - // User did not specify a disk size. Default to included disk size. - regionNodeInfoMap[r].SetDiskSizeGb(nodeConfig.GetIncludedDiskSizeGb()) - } + var nodeConfig *ybmclient.NodeConfigurationResponseItem = nil + if !userProvidedNumCores { + requestedNumCores = clusterNodeInfoWithDefaults.GetNumCores() } - // Set per-region node info and cluster node info. - var currRegionNodeInfo *ybmclient.OptionalClusterNodeInfo = nil - for i, regionInfo := range clusterRegionInfo { - r := regionInfo.GetPlacementInfo().CloudInfo.Region - clusterRegionInfo[i].SetNodeInfo(*regionNodeInfoMap[r]) - logrus.Debugf("region=%s, node-info=%v\n", r, clusterRegionInfo[i].GetNodeInfo()) - if currRegionNodeInfo != nil && !geoPartitioned && *currRegionNodeInfo != clusterRegionInfo[i].GetNodeInfo() { - // Asymmetric node configurations are only allowed for geo-partitioned clusters. - logrus.Fatalln("Synchronous cluster regions must have identical node configurations") + for i, nc := range nodeConfigs { + if nc.GetNumCores() == requestedNumCores { + nodeConfig = &nodeConfigs[i] + break } - currRegionNodeInfo = (&clusterRegionInfo[i]).NodeInfo.Get() } - clusterInfo.SetNodeInfo(ToClusterNodeInfo(regionNodeInfoMap[regions[0]])) - } else { - clusterInfo.SetNodeInfo(*ybmclient.NewClusterNodeInfoWithDefaults()) - if cmd.Flags().Changed("node-config") { - nodeConfig, _ := cmd.Flags().GetStringToInt("node-config") - numCores := nodeConfig["num-cores"] - clusterInfo.NodeInfo.Get().SetNumCores(int32(numCores)) - if diskSize, ok := nodeConfig["disk-size-gb"]; ok { - diskSizeGb = int32(diskSize) - } - if diskIopsInt, ok := nodeConfig["disk-iops"]; ok { - diskIops = int32(diskIopsInt) - } - } - region = cloudInfo.GetRegion() - numCores := clusterInfo.NodeInfo.Get().GetNumCores() - memoryMb, err = a.GetFromInstanceType("memory", cloud, tier, region, numCores) - if err != nil { - return nil, err + if nodeConfig == nil { + logrus.Fatalf("No instance type found with %d cores in region %s\n", requestedNumCores, r) } - clusterInfo.NodeInfo.Get().SetMemoryMb(memoryMb) - - // Computing the default disk size if it is not provided - if diskSizeGb == 0 { - diskSizeGb, err = a.GetFromInstanceType("disk", cloud, tier, region, numCores) - if err != nil { - return nil, err - } + regionNodeInfoMap[r].SetNumCores(nodeConfig.GetNumCores()) + regionNodeInfoMap[r].SetMemoryMb(nodeConfig.GetMemoryMb()) + if requestedNodeInfo.GetDiskSizeGb() == 0 { + // User did not specify a disk size. Default to included disk size. + regionNodeInfoMap[r].SetDiskSizeGb(nodeConfig.GetIncludedDiskSizeGb()) } - clusterInfo.NodeInfo.Get().SetDiskSizeGb(diskSizeGb) - - if diskIops > 0 { - clusterInfo.NodeInfo.Get().SetDiskIops(diskIops) + } + // Set per-region node info and cluster node info. + var currRegionNodeInfo *ybmclient.OptionalClusterNodeInfo = nil + for i, regionInfo := range clusterRegionInfo { + r := regionInfo.GetPlacementInfo().CloudInfo.Region + clusterRegionInfo[i].SetNodeInfo(*regionNodeInfoMap[r]) + logrus.Debugf("region=%s, node-info=%v\n", r, clusterRegionInfo[i].GetNodeInfo()) + if currRegionNodeInfo != nil && !geoPartitioned && *currRegionNodeInfo != clusterRegionInfo[i].GetNodeInfo() { + // Asymmetric node configurations are only allowed for geo-partitioned clusters. + logrus.Fatalln("Synchronous cluster regions must have identical node configurations") } + currRegionNodeInfo = (&clusterRegionInfo[i]).NodeInfo.Get() } if cmd.Flags().Changed("default-region") { defaultRegion, _ := cmd.Flags().GetString("default-region") - if clusterInfo.GetClusterType() != ybmclient.ClusterType("GEO_PARTITIONED") { + if clusterInfo.GetClusterType() != "GEO_PARTITIONED" { return nil, fmt.Errorf("default region is allowed only for geo partitioned clusters") } @@ -440,10 +394,7 @@ func (a *AuthApiClient) buildClusterSpec(cmd *cobra.Command, regionInfoList []ma clusterName, clusterInfo, softwareInfo) - clusterSpec.SetCloudInfo(cloudInfo) - if regionInfoProvided { - clusterSpec.SetClusterRegionInfo(clusterRegionInfo) - } + clusterSpec.SetClusterRegionInfo(clusterRegionInfo) return clusterSpec, nil } @@ -462,17 +413,6 @@ func (a *AuthApiClient) EditClusterSpec(cmd *cobra.Command, regionInfoList []map return a.buildClusterSpec(cmd, regionInfoList, regionNodeConfigsMap) } -func ToClusterNodeInfo(opt *ybmclient.OptionalClusterNodeInfo) ybmclient.ClusterNodeInfo { - clusterNodeInfo := *ybmclient.NewClusterNodeInfoWithDefaults() - clusterNodeInfo.SetNumCores(opt.GetNumCores()) - clusterNodeInfo.SetMemoryMb(opt.GetMemoryMb()) - clusterNodeInfo.SetDiskSizeGb(opt.GetDiskSizeGb()) - if iops, _ := opt.GetDiskIopsOk(); iops != nil { - clusterNodeInfo.SetDiskIops(*iops) - } - return clusterNodeInfo -} - func (a *AuthApiClient) GetInfo(providedAccountID string, providedProjectID string) { var err error a.AccountID, err = a.GetAccountID(providedAccountID) @@ -518,13 +458,13 @@ func (a *AuthApiClient) GetDrByName(drName string) (ybmclient.XClusterDrData, er } } - return ybmclient.XClusterDrData{}, fmt.Errorf("Could not get data for the DR config %s", drName) + return ybmclient.XClusterDrData{}, fmt.Errorf("could not get data for the DR config %s", drName) } func (a *AuthApiClient) ExtractProviderFromClusterName(clusterId string) ([]string, error) { clusterResp, _, err := a.GetCluster(clusterId).Execute() clusterData := clusterResp.GetData() - providers := []string{} + var providers []string if err != nil { return nil, err } @@ -593,7 +533,7 @@ func (a *AuthApiClient) GetDrDetailsByName(drName string) (ybmclient.XClusterDrI return drData.GetInfo(), nil } - return ybmclient.XClusterDrInfo{}, fmt.Errorf("Could not get data for the DR config %s", drName) + return ybmclient.XClusterDrInfo{}, fmt.Errorf("could not get data for the DR config %s", drName) } func (a *AuthApiClient) CreateCluster() ybmclient.ApiCreateClusterRequest { @@ -682,7 +622,7 @@ func (a *AuthApiClient) UpdateDbAuditExporterConfig(clusterId string, integratio } func (a *AuthApiClient) CreatePrivateServiceEndpointRegionSpec(regionArnMap map[string][]string) []ybmclient.PrivateServiceEndpointRegionSpec { - pseSpecs := []ybmclient.PrivateServiceEndpointRegionSpec{} + var pseSpecs []ybmclient.PrivateServiceEndpointRegionSpec for regionId, arnList := range regionArnMap { local := *ybmclient.NewPrivateServiceEndpointRegionSpec(arnList) @@ -693,7 +633,7 @@ func (a *AuthApiClient) CreatePrivateServiceEndpointRegionSpec(regionArnMap map[ } func (a *AuthApiClient) CreatePrivateServiceEndpointSpec(regionArnMap map[string][]string) []ybmclient.PrivateServiceEndpointSpec { - pseSpecs := []ybmclient.PrivateServiceEndpointSpec{} + var pseSpecs []ybmclient.PrivateServiceEndpointSpec for regionId, arnList := range regionArnMap { regionSpec := *ybmclient.NewPrivateServiceEndpointRegionSpec(arnList) @@ -1072,9 +1012,9 @@ func (a *AuthApiClient) ListSystemRbacRolesWithPermissions() ybmclient.ApiListRb func (a *AuthApiClient) CreateRoleSpec(cmd *cobra.Command, name string, permissionsMap map[string][]string) (*ybmclient.RoleSpec, error) { - rolePermissions := []ybmclient.ResourcePermissionInfo{} + var rolePermissions []ybmclient.ResourcePermissionInfo for resource, ops := range permissionsMap { - operationGroups := []ybmclient.ResourceOperationGroup{} + var operationGroups []ybmclient.ResourceOperationGroup for _, op := range ops { operationGroups = append(operationGroups, *ybmclient.NewResourceOperationGroup(ybmclient.ResourceOperationGroupEnum(op))) @@ -1272,7 +1212,7 @@ func (a *AuthApiClient) ListAccountUsers() ybmclient.ApiListAccountUsersRequest } func (a *AuthApiClient) CreateBatchInviteUserSpec(email string, roleId string) (*ybmclient.BatchInviteUserSpec, error) { - users := []ybmclient.InviteUserSpec{} + var users []ybmclient.InviteUserSpec user := *ybmclient.NewInviteUserSpecWithDefaults() user.SetEmail(email) @@ -1350,7 +1290,7 @@ func (a *AuthApiClient) WaitForTaskCompletionCI(entityId string, entityType ybmc return "", fmt.Errorf("receive interrupt signal, operation could still be on-going") case <-checkEveryInSec: apiRequest := a.ListTasks().TaskType(taskType).ProjectId(a.ProjectID).EntityId(entityId).Limit(1) - //Sometime the api do not need any entity type, for example VPC, VPC_PEERING + //Sometimes the api do not need any entity type, for example VPC, VPC_PEERING if len(entityType) > 0 { apiRequest.EntityType(entityType) } @@ -1416,7 +1356,7 @@ func (a *AuthApiClient) WaitForTaskCompletionFull(entityId string, entityType yb return "", fmt.Errorf("receive interrupt signal, operation could still be on-going") case <-checkEveryInSec: apiRequest := a.ListTasks().TaskType(taskType).ProjectId(a.ProjectID).EntityId(entityId).Limit(1) - //Sometime the api do not need any entity type, for example VPC, VPC_PEERING + //Sometimes the api do not need any entity type, for example VPC, VPC_PEERING if len(entityType) > 0 { apiRequest.EntityType(entityType) }