Skip to content

Commit

Permalink
[CLI-2132] Add Enterprise SKU support (#2149)
Browse files Browse the repository at this point in the history
Co-authored-by: Brian Strauch <bstrauch@confluent.io>
Co-authored-by: Luca Filipponi <lfilipponi@confluent.io>
  • Loading branch information
3 people committed Jul 31, 2023
1 parent fb5c9a1 commit b191035
Show file tree
Hide file tree
Showing 18 changed files with 63 additions and 16 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/confluentinc/ccloud-sdk-go-v2/byok v0.0.1
github.com/confluentinc/ccloud-sdk-go-v2/cdx v0.0.5
github.com/confluentinc/ccloud-sdk-go-v2/cli v0.3.0
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.8.0
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.10.0
github.com/confluentinc/ccloud-sdk-go-v2/connect v0.3.0
github.com/confluentinc/ccloud-sdk-go-v2/flink v0.3.0
github.com/confluentinc/ccloud-sdk-go-v2/flink-gateway v0.4.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ github.com/confluentinc/ccloud-sdk-go-v2/cdx v0.0.5 h1:w0Z2hFxg8ng8gycWKRZFdus1R
github.com/confluentinc/ccloud-sdk-go-v2/cdx v0.0.5/go.mod h1:L8U9xs2duASJnjIYkwGrSbZNpApsbh+vlxsJlZMHJPA=
github.com/confluentinc/ccloud-sdk-go-v2/cli v0.3.0 h1:OOFNqtZN3Spuzz4TX6K6JfDM7zNDIE6BE1TtK78jFHQ=
github.com/confluentinc/ccloud-sdk-go-v2/cli v0.3.0/go.mod h1:Mv0WTsBXUfKjmF+r2t2Dv/xJzZf17shhf5J1cttU2Qo=
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.8.0 h1:n0F+4nIBXGOy7uDSw9i7tuBv11I6flEd47gxeuNbjeQ=
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.8.0/go.mod h1:357Zo3HvVAe5iQgUFxUbQPAKJasGm8vFMkOB+krVmR8=
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.10.0 h1:YQEcSvhX5ODllg0mhxLivckKU3f5OF7s6zgABZporgA=
github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.10.0/go.mod h1:357Zo3HvVAe5iQgUFxUbQPAKJasGm8vFMkOB+krVmR8=
github.com/confluentinc/ccloud-sdk-go-v2/connect v0.3.0 h1:hnYc/T55dGEqhFBYJIGBfSCMhyhT78U31kqEj9vdS94=
github.com/confluentinc/ccloud-sdk-go-v2/connect v0.3.0/go.mod h1:vzL/maQvg76G8BMXM9Mx0FNrXI1ctdBr46/EbZ0VJso=
github.com/confluentinc/ccloud-sdk-go-v2/flink v0.3.0 h1:FthbzhN2e13/1Ugv6Zk9d31hvYglpkBpqTAIqDp3bK8=
Expand Down
15 changes: 10 additions & 5 deletions internal/cmd/kafka/command_cluster_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ import (
"github.com/confluentinc/cli/internal/pkg/errors"
"github.com/confluentinc/cli/internal/pkg/examples"
"github.com/confluentinc/cli/internal/pkg/form"
"github.com/confluentinc/cli/internal/pkg/kafka"
"github.com/confluentinc/cli/internal/pkg/output"
"github.com/confluentinc/cli/internal/pkg/utils"
)

const (
skuBasic = "basic"
skuStandard = "standard"
skuDedicated = "dedicated"
skuBasic = "basic"
skuStandard = "standard"
skuEnterprise = "enterprise"
skuDedicated = "dedicated"
)

var permitBYOKGCP = template.Must(template.New("byok_gcp_permissions").Parse(`Create a role with these permissions, add the identity as a member of your key, and grant your role to the member:
Expand Down Expand Up @@ -259,11 +262,11 @@ func stringToAvailability(s string) (string, error) {
func stringToSku(skuType string) (ccstructs.Sku, error) {
sku := ccstructs.Sku(ccstructs.Sku_value[strings.ToUpper(skuType)])
switch sku {
case ccstructs.Sku_BASIC, ccstructs.Sku_STANDARD, ccstructs.Sku_DEDICATED:
case ccstructs.Sku_BASIC, ccstructs.Sku_STANDARD, ccstructs.Sku_ENTERPRISE, ccstructs.Sku_DEDICATED:
break
default:
return ccstructs.Sku_UNKNOWN, errors.NewErrorWithSuggestions(fmt.Sprintf(errors.InvalidTypeFlagErrorMsg, skuType),
fmt.Sprintf(errors.InvalidTypeFlagSuggestions, skuBasic, skuStandard, skuDedicated))
fmt.Sprintf("Allowed values for `--type` flag are: %s.", utils.ArrayToCommaDelimitedString(kafka.Types, "and")))
}
return sku, nil
}
Expand All @@ -278,6 +281,8 @@ func setCmkClusterConfig(typeString string, cku int32, encryptionKeyID string) *
return &cmkv2.CmkV2ClusterSpecConfigOneOf{
CmkV2Standard: &cmkv2.CmkV2Standard{Kind: "Standard"},
}
case skuEnterprise:
return &cmkv2.CmkV2ClusterSpecConfigOneOf{CmkV2Enterprise: &cmkv2.CmkV2Enterprise{Kind: "Enterprise"}}
case skuDedicated:
var encryptionPtr *string
if encryptionKeyID != "" {
Expand Down
7 changes: 7 additions & 0 deletions internal/cmd/kafka/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ func getCmkClusterType(cluster *cmkv2.CmkV2Cluster) string {
if isDedicated(cluster) {
return ccstructs.Sku_name[4]
}
if isEnterprise(cluster) {
return ccstructs.Sku_name[6]
}
return ccstructs.Sku_name[0] // UNKNOWN
}

Expand Down Expand Up @@ -167,6 +170,10 @@ func isStandard(cluster *cmkv2.CmkV2Cluster) bool {
return cluster.Spec.Config != nil && cluster.Spec.Config.CmkV2Standard != nil
}

func isEnterprise(cluster *cmkv2.CmkV2Cluster) bool {
return cluster.Spec.Config != nil && cluster.Spec.Config.CmkV2Enterprise != nil
}

func isDedicated(cluster *cmkv2.CmkV2Cluster) bool {
return cluster.Spec.Config != nil && cluster.Spec.Config.CmkV2Dedicated != nil
}
Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/price/command_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
"basic": "basic",
"custom": "custom-legacy",
"dedicated": "dedicated",
"enterprise": "enterprise",
"standard": "basic-legacy",
"standard_v2": "standard",
}
Expand All @@ -47,6 +48,7 @@ var (
"basic": "Basic",
"custom": "Legacy - Custom",
"dedicated": "Dedicated",
"enterprise": "Enterprise",
"standard": "Legacy - Standard",
"standard_v2": "Standard",
}
Expand Down
3 changes: 3 additions & 0 deletions internal/pkg/ccstructs/product_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const (
Sku_STANDARD Sku = 3
Sku_DEDICATED Sku = 4
Sku_DEDICATED_LEGACY Sku = 5
Sku_ENTERPRISE Sku = 6
)

var Sku_name = map[int32]string{
Expand All @@ -18,6 +19,7 @@ var Sku_name = map[int32]string{
3: "STANDARD",
4: "DEDICATED",
5: "DEDICATED_LEGACY",
6: "ENTERPRISE",
}

var Sku_value = map[string]int32{
Expand All @@ -27,4 +29,5 @@ var Sku_value = map[string]int32{
"STANDARD": 3,
"DEDICATED": 4,
"DEDICATED_LEGACY": 5,
"ENTERPRISE": 6,
}
5 changes: 4 additions & 1 deletion internal/pkg/errors/catcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,10 @@ func CatchClusterConfigurationNotValidError(err error, r *http.Response) error {

err = CatchCCloudV2Error(err, r)
if strings.Contains(err.Error(), "CKU must be greater") {
return New(InvalidCkuErrorMsg)
return New("CKU must be greater than 1 for multi-zone dedicated clusters")
}
if strings.Contains(err.Error(), "Durability must be HIGH for an Enterprise cluster") {
return New(`availability must be "multi-zone" for enterprise clusters`)
}

return err
Expand Down
2 changes: 0 additions & 2 deletions internal/pkg/errors/error_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ const (
InvalidAvailableFlagErrorMsg = "invalid value \"%s\" for `--availability` flag"
InvalidAvailableFlagSuggestions = "Allowed values for `--availability` flag are: %s, %s."
InvalidTypeFlagErrorMsg = "invalid value \"%s\" for `--type` flag"
InvalidTypeFlagSuggestions = "Allowed values for `--type` flag are: %s, %s, %s."
NameOrCKUFlagErrorMsg = "must either specify --name with non-empty value or --cku (for dedicated clusters) with positive integer"
NonEmptyNameErrorMsg = "`--name` flag value must not be empty"
KafkaClusterNotFoundErrorMsg = `Kafka cluster "%s" not found`
Expand Down Expand Up @@ -399,7 +398,6 @@ const (
NoKafkaForDescribeSuggestions = "You must provide the cluster ID argument or set an active Kafka cluster in your context with `confluent kafka cluster use`."
NoAPISecretStoredErrorMsg = `no API secret for API key "%s" of resource "%s" stored in local CLI state`
NoAPISecretStoredSuggestions = "Store the API secret with `confluent api-key store %s --resource %s`."
InvalidCkuErrorMsg = "cku must be greater than 1 for multi-zone dedicated cluster"

// Kafka REST Proxy errors
InternalServerErrorMsg = "internal server error"
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/kafka/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ const Requester ListACLsContextKey = "requester"
var (
Clouds = []string{"aws", "azure", "gcp"}
Availabilities = []string{"single-zone", "multi-zone"}
Types = []string{"basic", "standard", "dedicated"}
Types = []string{"basic", "standard", "enterprise", "dedicated"}
)
2 changes: 1 addition & 1 deletion test/fixtures/output/kafka/1.golden
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Flags:
--cloud string Specify the cloud provider as "aws", "azure", or "gcp".
--region string Cloud region ID for cluster (use "confluent kafka region list" to see all).
--availability string Specify the availability of the cluster as "single-zone" or "multi-zone". (default "single-zone")
--type string Specify the type of the Kafka cluster as "basic", "standard", or "dedicated". (default "basic")
--type string Specify the type of the Kafka cluster as "basic", "standard", "enterprise", or "dedicated". (default "basic")
--cku int Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated".
--encryption-key string Resource ID of the Cloud Key Management Service key (GCP only).
--context string CLI context name.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Error: availability must be "multi-zone" for enterprise clusters
16 changes: 16 additions & 0 deletions test/fixtures/output/kafka/cluster/create-enterprise.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
It may take up to 5 minutes for the Kafka cluster to be ready.
+----------------------+---------------------------+
| Current | false |
| ID | lkc-def963 |
| Name | my-new-cluster |
| Type | ENTERPRISE |
| Ingress Limit (MB/s) | 250 |
| Egress Limit (MB/s) | 750 |
| Storage | Infinite |
| Provider | aws |
| Region | us-east-1 |
| Availability | multi-zone |
| Status | PROVISIONING |
| Endpoint | SASL_SSL://kafka-endpoint |
| REST Endpoint | https://pkc-endpoint |
+----------------------+---------------------------+
2 changes: 1 addition & 1 deletion test/fixtures/output/kafka/cluster/create-help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Flags:
--cloud string REQUIRED: Specify the cloud provider as "aws", "azure", or "gcp".
--region string REQUIRED: Cloud region ID for cluster (use "confluent kafka region list" to see all).
--availability string Specify the availability of the cluster as "single-zone" or "multi-zone". (default "single-zone")
--type string Specify the type of the Kafka cluster as "basic", "standard", or "dedicated". (default "basic")
--type string Specify the type of the Kafka cluster as "basic", "standard", "enterprise", or "dedicated". (default "basic")
--cku int Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated".
--encryption-key string Resource ID of the Cloud Key Management Service key (GCP only).
--context string CLI context name.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Error: invalid value "oops" for `--type` flag

Suggestions:
Allowed values for `--type` flag are: basic, standard, dedicated.
Allowed values for `--type` flag are: "basic", "standard", "enterprise", and "dedicated".
1 change: 1 addition & 0 deletions test/fixtures/output/kafka/create-type-autocomplete.golden
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
basic
standard
enterprise
dedicated
:4
Completion ended with directive: ShellCompDirectiveNoFileComp
2 changes: 1 addition & 1 deletion test/fixtures/output/price/list-help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Flags:
--cloud string REQUIRED: Specify the cloud provider as "aws", "azure", or "gcp".
--region string REQUIRED: Cloud region ID for cluster (use "confluent kafka region list" to see all).
--availability string Filter by availability (high, low).
--cluster-type string Filter by cluster type (basic, basic-legacy, custom-legacy, dedicated, standard).
--cluster-type string Filter by cluster type (basic, basic-legacy, custom-legacy, dedicated, enterprise, standard).
--network-type string Filter by network type (internet, peered-vpc, private-link, transit-gateway).
--metric string Filter by metric (ClusterLinkingBase, ClusterLinkingPerLink, ClusterLinkingRead, ClusterLinkingWrite, ConnectCapacity, ConnectNumRecords, ConnectNumTasks, ConnectThroughput, KSQLNumCSUs, KafkaBase, KafkaCKUUnit, KafkaNetworkRead, KafkaNetworkWrite, KafkaNumCKUs, KafkaPartition, KafkaRestProduce, KafkaStorage).
--legacy Show legacy cluster types.
Expand Down
2 changes: 2 additions & 0 deletions test/kafka_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func (s *CLITestSuite) TestKafka() {
{args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --availability single-zone -o json", fixture: "kafka/23.golden"},
{args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --availability single-zone -o yaml", fixture: "kafka/24.golden"},
{args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --availability oops-zone", fixture: "kafka/cluster/create-availability-zone-error.golden", exitCode: 1},
{args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type enterprise --availability multi-zone", fixture: "kafka/cluster/create-enterprise.golden"},
{args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type enterprise", fixture: "kafka/cluster/create-enterprise-availability-zone-error.golden", exitCode: 1},

{args: "kafka cluster update lkc-update", fixture: "kafka/cluster/create-flag-error.golden", exitCode: 1},
{args: "kafka cluster update lkc-update --name lkc-update-name", fixture: "kafka/26.golden"},
Expand Down
9 changes: 9 additions & 0 deletions test/test-server/cmk_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testserver

import (
"encoding/json"
"io"
"net/http"
"testing"

Expand Down Expand Up @@ -44,6 +45,14 @@ func handleCmkKafkaClusterCreate(t *testing.T) http.HandlerFunc {
cluster.Spec.Byok = req.Spec.Byok
}
cluster.Status.Cku = cmkv2.PtrInt32(1)
} else if req.Spec.Config.CmkV2Enterprise != nil {
if *req.Spec.Availability == "SINGLE_ZONE" {
w.WriteHeader(http.StatusUnprocessableEntity)
_, err := io.WriteString(w, `{"errors":[{"status":"422","detail":"Durability must be HIGH for an Enterprise cluster"}]}`)
require.NoError(t, err)
return
}
cluster.Spec.Config.CmkV2Enterprise = &cmkv2.CmkV2Enterprise{Kind: "Enterprise"}
} else {
cluster.Spec.Config.CmkV2Basic = &cmkv2.CmkV2Basic{Kind: "Basic"}
}
Expand Down

0 comments on commit b191035

Please sign in to comment.