From d0b8249568f50dbe27439e0076a7136331721659 Mon Sep 17 00:00:00 2001 From: Arnav Agarwal <14933889+Arnav15@users.noreply.github.com> Date: Fri, 18 Aug 2023 12:48:02 -0700 Subject: [PATCH] [CLOUDGA-15694] Add support fror RF5/RF7 clusters --- cmd/cluster/create_cluster.go | 3 +- cmd/cluster/update_cluster.go | 2 +- cmd/test/fixtures/list-clusters.json | 1 + cmd/test/fixtures/one-cluster.json | 1 + cmd/test/fixtures/pause-cluster.json | 1 + cmd/test/fixtures/paused-cluster.json | 1 + cmd/test/fixtures/pausing-cluster.json | 1 + cmd/test/fixtures/resume-cluster.json | 1 + cmd/test/fixtures/resume-queue-cluster.json | 1 + cmd/util/feature_flags.go | 1 + cmd/util/util.go | 24 +++++++++++-- docs/ybm_cluster_create.md | 37 +++++++++++---------- docs/ybm_cluster_update.md | 2 +- internal/client/client.go | 9 +++++ internal/formatter/clusters.go | 5 +++ internal/formatter/clusters_full.go | 22 ++++++++++++ 16 files changed, 89 insertions(+), 23 deletions(-) diff --git a/cmd/cluster/create_cluster.go b/cmd/cluster/create_cluster.go index 3d290cad..aee4d4d2 100644 --- a/cmd/cluster/create_cluster.go +++ b/cmd/cluster/create_cluster.go @@ -186,7 +186,8 @@ func init() { For GCP: cloud-provider=GCP,gcp-resource-id=,gcp-service-account-path=. If specified, all parameters for that provider are mandatory.`) - createClusterCmd.Flags().String("fault-tolerance", "", "[OPTIONAL] The fault tolerance of the cluster. The possible values are NONE, ZONE and REGION. Default NONE.") + createClusterCmd.Flags().String("fault-tolerance", "", "[OPTIONAL] The fault tolerance domain of the cluster. The possible values are NONE, ZONE and 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] Configuration of the cluster nodes. Please provide key value pairs num-cores=,disk-size-gb=,disk-iops= as the value. If specified, num-cores is mandatory, while disk-size-gb and disk-iops are optional.") createClusterCmd.Flags().StringArray("region-info", []string{}, `[OPTIONAL] Region information for the cluster. Please provide key value pairs region=,num-nodes=,vpc= as the value. If specified, region and num-nodes are mandatory, vpc is optional. Information about multiple regions can be specified by using multiple --region-info arguments. Default if not specified is us-west-2 AWS region.`) diff --git a/cmd/cluster/update_cluster.go b/cmd/cluster/update_cluster.go index 49776553..b853a908 100644 --- a/cmd/cluster/update_cluster.go +++ b/cmd/cluster/update_cluster.go @@ -174,7 +174,7 @@ func init() { updateClusterCmd.Flags().StringToInt("node-config", nil, "[OPTIONAL] Configuration of the cluster nodes. Please provide key value pairs num-cores=,disk-size-gb=,disk-iops= as the value. If provided, num-cores is mandatory, while disk-size-gb and disk-iops are optional.") updateClusterCmd.Flags().StringArray("region-info", []string{}, `[OPTIONAL] Region information for the cluster. Please provide key value pairs, region=,num-nodes=,vpc= as the value. If provided, region and num-nodes are mandatory, vpc is optional.`) updateClusterCmd.Flags().String("cluster-tier", "", "[OPTIONAL] The tier of the cluster. Sandbox or Dedicated.") - updateClusterCmd.Flags().String("fault-tolerance", "", "[OPTIONAL] The fault tolerance of the cluster. The possible values are NONE, ZONE and REGION.") + updateClusterCmd.Flags().String("fault-tolerance", "", "[OPTIONAL] The fault tolerance domain of the cluster. The possible values are NONE, ZONE and REGION.") updateClusterCmd.Flags().String("database-version", "", "[OPTIONAL] The database version of the cluster. Production or Innovation or Preview.") } diff --git a/cmd/test/fixtures/list-clusters.json b/cmd/test/fixtures/list-clusters.json index c19dd9ed..bcc565e2 100644 --- a/cmd/test/fixtures/list-clusters.json +++ b/cmd/test/fixtures/list-clusters.json @@ -12,6 +12,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/one-cluster.json b/cmd/test/fixtures/one-cluster.json index b623ad66..63543f53 100644 --- a/cmd/test/fixtures/one-cluster.json +++ b/cmd/test/fixtures/one-cluster.json @@ -12,6 +12,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/pause-cluster.json b/cmd/test/fixtures/pause-cluster.json index 1f8c4b13..9d1e246a 100644 --- a/cmd/test/fixtures/pause-cluster.json +++ b/cmd/test/fixtures/pause-cluster.json @@ -11,6 +11,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/paused-cluster.json b/cmd/test/fixtures/paused-cluster.json index f51f2a7d..8649b87d 100644 --- a/cmd/test/fixtures/paused-cluster.json +++ b/cmd/test/fixtures/paused-cluster.json @@ -12,6 +12,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/pausing-cluster.json b/cmd/test/fixtures/pausing-cluster.json index e33602a7..17c7a7a0 100644 --- a/cmd/test/fixtures/pausing-cluster.json +++ b/cmd/test/fixtures/pausing-cluster.json @@ -12,6 +12,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/resume-cluster.json b/cmd/test/fixtures/resume-cluster.json index d07c08f7..dfc5cf19 100644 --- a/cmd/test/fixtures/resume-cluster.json +++ b/cmd/test/fixtures/resume-cluster.json @@ -11,6 +11,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/test/fixtures/resume-queue-cluster.json b/cmd/test/fixtures/resume-queue-cluster.json index b91013b5..a1a2dca9 100644 --- a/cmd/test/fixtures/resume-queue-cluster.json +++ b/cmd/test/fixtures/resume-queue-cluster.json @@ -11,6 +11,7 @@ "cluster_type": "SYNCHRONOUS", "num_nodes": 1, "fault_tolerance": "NONE", + "num_faults_to_tolerate": 0, "node_info": { "num_cores": 2, "memory_mb": 8192, diff --git a/cmd/util/feature_flags.go b/cmd/util/feature_flags.go index eddfb1be..60c37657 100644 --- a/cmd/util/feature_flags.go +++ b/cmd/util/feature_flags.go @@ -32,6 +32,7 @@ const ( AZURE_CIDR_ALLOWED FeatureFlag = "AZURE_CIDR_ALLOWED" CLUSTER_CMK_UPDATE FeatureFlag = "CLUSTER_CMK_UPDATE" ENTERPRISE_SECURITY FeatureFlag = "ENTERPRISE_SECURITY" + CLUSTER_RF FeatureFlag = "CLUSTER_RF" ) func (f FeatureFlag) String() string { diff --git a/cmd/util/util.go b/cmd/util/util.go index 4115a82e..cc3380da 100644 --- a/cmd/util/util.go +++ b/cmd/util/util.go @@ -48,7 +48,27 @@ func GetClusterTier(tierCli string) (string, error) { return "FREE", nil } - return "", fmt.Errorf("The tier must be either 'Sandbox' or 'Dedicated'") + return "", fmt.Errorf("the tier must be either 'Sandbox' or 'Dedicated'") +} + +func ValidateNumFaultsToTolerate(numFaultsToTolerate int32, faultTolerance ybmclient.ClusterFaultTolerance) (bool, error) { + if numFaultsToTolerate < 0 || numFaultsToTolerate > 3 { + return false, fmt.Errorf("number of faults to tolerate must be between 0 and 3") + } + if faultTolerance == ybmclient.CLUSTERFAULTTOLERANCE_NONE && numFaultsToTolerate != 0 { + return false, fmt.Errorf("number of faults to tolerate must be 0 for fault tolerance level 'NONE'") + } + if faultTolerance == ybmclient.CLUSTERFAULTTOLERANCE_NODE && numFaultsToTolerate < 1 { + return false, fmt.Errorf("number of faults to tolerate must be greater than 0 for fault tolerance level 'NODE'") + } + if faultTolerance == ybmclient.CLUSTERFAULTTOLERANCE_REGION && numFaultsToTolerate < 1 { + return false, fmt.Errorf("number of faults to tolerate must be greater than 0 for fault tolerance level 'REGION'") + } + if faultTolerance == ybmclient.CLUSTERFAULTTOLERANCE_ZONE && numFaultsToTolerate != 1 { + return false, fmt.Errorf("number of faults to tolerate must be 1 for fault tolerance level 'ZONE'") + } + + return true, nil } func ValidateCIDR(cidr string) (bool, error) { @@ -68,7 +88,7 @@ func ExtractJwtClaims(tokenStr string) (jwt.MapClaims, error) { if _, ok := token.Claims.(jwt.MapClaims); ok { return token.Claims.(jwt.MapClaims), nil } - return nil, errors.New("Unable to extract claims from token") + return nil, errors.New("unable to extract claims from token") } func IsJwtTokenExpiredWithTime(tokenStr string, now time.Time) (bool, error) { diff --git a/docs/ybm_cluster_create.md b/docs/ybm_cluster_create.md index 03a19bae..707a4baa 100644 --- a/docs/ybm_cluster_create.md +++ b/docs/ybm_cluster_create.md @@ -13,24 +13,25 @@ ybm cluster create [flags] ### Options ``` - --cluster-name string [REQUIRED] Name of the cluster. - --credentials stringToString [REQUIRED] Credentials to login to the cluster. Please provide key value pairs username=,password=. (default []) - --cloud-provider string [OPTIONAL] The cloud provider where database needs to be deployed. AWS, AZURE or GCP. Default AWS. - --cluster-tier string [OPTIONAL] The tier of the cluster. Sandbox or Dedicated. Default Sandbox. - --cluster-type string [OPTIONAL] Cluster replication type. SYNCHRONOUS or GEO_PARTITIONED. Default SYNCHRONOUS. - --database-version string [OPTIONAL] The database version of the cluster. Stable or Preview. Default depends on cluster tier, Sandbox is Preview, Dedicated is Stable. - --encryption-spec string [OPTIONAL] The customer managed key spec for the cluster. - Please provide key value pairs as follows: - For AWS: - cloud-provider=AWS,aws-secret-key=,aws-access-key=,aws-arn=,aws-arn= . - aws-access-key can be ommitted if the environment variable YBM_AWS_SECRET_KEY is set. If the environment variable is not set, the user will be prompted to enter the value. - For GCP: - cloud-provider=GCP,gcp-resource-id=,gcp-service-account-path=. - If specified, all parameters for that provider are mandatory. - --fault-tolerance string [OPTIONAL] The fault tolerance of the cluster. The possible values are NONE, ZONE and REGION. Default NONE. - --node-config stringToInt [OPTIONAL] Configuration of the cluster nodes. Please provide key value pairs num-cores=,disk-size-gb=,disk-iops= as the value. If specified, num-cores is mandatory, while disk-size-gb and disk-iops are optional. (default []) - --region-info stringArray [OPTIONAL] Region information for the cluster. Please provide key value pairs region=,num-nodes=,vpc= as the value. If specified, region and num-nodes are mandatory, vpc is optional. Information about multiple regions can be specified by using multiple --region-info arguments. Default if not specified is us-west-2 AWS region. - -h, --help help for create + --cluster-name string [REQUIRED] Name of the cluster. + --credentials stringToString [REQUIRED] Credentials to login to the cluster. Please provide key value pairs username=,password=. (default []) + --cloud-provider string [OPTIONAL] The cloud provider where database needs to be deployed. AWS, AZURE or GCP. Default AWS. + --cluster-tier string [OPTIONAL] The tier of the cluster. Sandbox or Dedicated. Default Sandbox. + --cluster-type string [OPTIONAL] Cluster replication type. SYNCHRONOUS or GEO_PARTITIONED. Default SYNCHRONOUS. + --database-version string [OPTIONAL] The database version of the cluster. Stable or Preview. Default depends on cluster tier, Sandbox is Preview, Dedicated is Stable. + --encryption-spec string [OPTIONAL] The customer managed key spec for the cluster. + Please provide key value pairs as follows: + For AWS: + cloud-provider=AWS,aws-secret-key=,aws-access-key=,aws-arn=,aws-arn= . + aws-access-key can be ommitted if the environment variable YBM_AWS_SECRET_KEY is set. If the environment variable is not set, the user will be prompted to enter the value. + For GCP: + cloud-provider=GCP,gcp-resource-id=,gcp-service-account-path=. + If specified, all parameters for that provider are mandatory. + --fault-tolerance string [OPTIONAL] The fault tolerance domain of the cluster. The possible values are NONE, ZONE and REGION. Default NONE. + --num-faults-to-tolerate int32 [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. + --node-config stringToInt [OPTIONAL] Configuration of the cluster nodes. Please provide key value pairs num-cores=,disk-size-gb=,disk-iops= as the value. If specified, num-cores is mandatory, while disk-size-gb and disk-iops are optional. (default []) + --region-info stringArray [OPTIONAL] Region information for the cluster. Please provide key value pairs region=,num-nodes=,vpc= as the value. If specified, region and num-nodes are mandatory, vpc is optional. Information about multiple regions can be specified by using multiple --region-info arguments. Default if not specified is us-west-2 AWS region. + -h, --help help for create ``` ### Options inherited from parent commands diff --git a/docs/ybm_cluster_update.md b/docs/ybm_cluster_update.md index df076313..a24c98ba 100644 --- a/docs/ybm_cluster_update.md +++ b/docs/ybm_cluster_update.md @@ -18,7 +18,7 @@ ybm cluster update [flags] --cluster-tier string [OPTIONAL] The tier of the cluster. Sandbox or Dedicated. --cluster-type string [OPTIONAL] Cluster replication type. SYNCHRONOUS or GEO_PARTITIONED. --database-version string [OPTIONAL] The database version of the cluster. Production or Innovation or Preview. - --fault-tolerance string [OPTIONAL] The fault tolerance of the cluster. The possible values are NONE, ZONE and REGION. + --fault-tolerance string [OPTIONAL] The fault tolerance domain of the cluster. The possible values are NONE, ZONE and REGION. -h, --help help for update --new-name string [OPTIONAL] The new name to be given to the cluster. --node-config stringToInt [OPTIONAL] Configuration of the cluster nodes. Please provide key value pairs num-cores=,disk-size-gb=,disk-iops= as the value. If provided, num-cores is mandatory, while disk-size-gb and disk-iops are optional. (default []) diff --git a/internal/client/client.go b/internal/client/client.go index 6deb7f4f..44099528 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -240,6 +240,15 @@ func (a *AuthApiClient) CreateClusterSpec(cmd *cobra.Command, regionInfoList []m faultTolerance, _ := cmd.Flags().GetString("fault-tolerance") clusterInfo.SetFaultTolerance(ybmclient.ClusterFaultTolerance(faultTolerance)) } + if util.IsFeatureFlagEnabled(util.CLUSTER_RF) { + if cmd.Flags().Changed("num-faults-to-tolerate") { + numFaultsToTolerate, _ := cmd.Flags().GetInt32("num-faults-to-tolerate") + if valid, err := util.ValidateNumFaultsToTolerate(numFaultsToTolerate, clusterInfo.GetFaultTolerance()); !valid { + return nil, err + } + clusterInfo.SetNumFaultsToTolerate(numFaultsToTolerate) + } + } if util.IsFeatureFlagEnabled(util.ENTERPRISE_SECURITY) { if cmd.Flags().Changed("enterprise-security") { enterpriseSecurity, _ := cmd.Flags().GetBool("enterprise-security") diff --git a/internal/formatter/clusters.go b/internal/formatter/clusters.go index 0f9d27a8..8de3ca61 100644 --- a/internal/formatter/clusters.go +++ b/internal/formatter/clusters.go @@ -26,6 +26,7 @@ import ( "github.com/enescakir/emoji" "github.com/inhies/go-bytesize" "github.com/sirupsen/logrus" + "github.com/yugabyte/ybm-cli/cmd/util" ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal" "golang.org/x/exp/maps" ) @@ -181,6 +182,10 @@ func (c *ClusterContext) Tier() string { return "Dedicated" } func (c *ClusterContext) FaultTolerance() string { + if util.IsFeatureFlagEnabled(util.CLUSTER_RF) { + rf := *c.c.GetSpec().ClusterInfo.NumFaultsToTolerate.Get()*2 + 1 + return fmt.Sprintf("%s, RF %d", string(c.c.GetSpec().ClusterInfo.FaultTolerance), rf) + } return string(c.c.GetSpec().ClusterInfo.FaultTolerance) } diff --git a/internal/formatter/clusters_full.go b/internal/formatter/clusters_full.go index 11648bcc..9f12b9cf 100644 --- a/internal/formatter/clusters_full.go +++ b/internal/formatter/clusters_full.go @@ -19,9 +19,11 @@ import ( "bytes" "encoding/json" "fmt" + "runtime" "sort" "text/template" + "github.com/enescakir/emoji" "github.com/sirupsen/logrus" "github.com/yugabyte/ybm-cli/internal/client" "github.com/yugabyte/ybm-cli/internal/cluster" @@ -307,6 +309,10 @@ func (c *clusterInfoRegionsContext) DiskSizeGb() string { } func (c *clusterInfoRegionsContext) Region() string { + // If the fault tolerance is regional, check if there is an affinitized region + if c.clusterInfo.FaultTolerance == ybmclient.CLUSTERFAULTTOLERANCE_REGION && c.clusterInfoRegion.IsAffinitized.IsSet() { + return fmt.Sprintf("%s %s", AffinitizedRegionToEmoji(*c.clusterInfoRegion.IsAffinitized.Get()), c.clusterInfoRegion.GetPlacementInfo().CloudInfo.Region) + } return c.clusterInfoRegion.GetPlacementInfo().CloudInfo.Region } @@ -316,3 +322,19 @@ func (c *clusterInfoRegionsContext) VpcName() string { func (c *clusterInfoRegionsContext) MarshalJSON() ([]byte, error) { return json.Marshal(c.clusterInfoRegion) } + +func AffinitizedRegionToEmoji(isAffinitized bool) string { + switch isAffinitized { + case true: + // Windows terminal do not support emoji + // So we return directly the healthstate + if runtime.GOOS == "windows" { + return fmt.Sprintf("*") + } + return emoji.Parse(":star:") + case false: + return fmt.Sprintf("") + default: + return fmt.Sprintf("") + } +}