diff --git a/go.mod b/go.mod index 10f4f130b2..6dbefc0808 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/confluentinc/ccloud-sdk-go-v2/cdx v0.0.5 github.com/confluentinc/ccloud-sdk-go-v2/certificate-authority v0.0.2 github.com/confluentinc/ccloud-sdk-go-v2/cli v0.3.0 - github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.25.0 + github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.26.0 github.com/confluentinc/ccloud-sdk-go-v2/connect v0.7.0 github.com/confluentinc/ccloud-sdk-go-v2/connect-custom-plugin v0.0.9 github.com/confluentinc/ccloud-sdk-go-v2/flink v0.11.0 @@ -111,7 +111,7 @@ require ( go.uber.org/mock v0.4.0 golang.org/x/crypto v0.46.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/oauth2 v0.34.0 + golang.org/x/oauth2 v0.36.0 golang.org/x/term v0.38.0 golang.org/x/text v0.32.0 google.golang.org/protobuf v1.36.10 diff --git a/go.sum b/go.sum index 857ba97598..ce3756cdf3 100644 --- a/go.sum +++ b/go.sum @@ -208,8 +208,8 @@ github.com/confluentinc/ccloud-sdk-go-v2/certificate-authority v0.0.2 h1:stsiO1J github.com/confluentinc/ccloud-sdk-go-v2/certificate-authority v0.0.2/go.mod h1:OU1RGuP2y5l54jX5rA++QBAKeRvSa7GmkfNgJvB9J6M= 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.25.0 h1:EdZzQZ4SI5q+f0DQPjH3lWpygz1wYz7IE0K62Mv06bY= -github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.25.0/go.mod h1:FSSO9mkNPJKMa7Ky66IlXEG7o5H6cpyuKKClvRf9y+0= +github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.26.0 h1:GVGsu/DtcHaQH3yuvovpPbjNrcwez0N7+e4rbCQ/QKU= +github.com/confluentinc/ccloud-sdk-go-v2/cmk v0.26.0/go.mod h1:wtfggR9vJMVda+fMBamv3/nNxSDB+unboplVzzcQlGY= github.com/confluentinc/ccloud-sdk-go-v2/connect v0.7.0 h1:ISrVOX9qJ2Sxiu/fGBqqHeaA0SRJQujc8yP7qAZRL3Y= github.com/confluentinc/ccloud-sdk-go-v2/connect v0.7.0/go.mod h1:zHG/3DzsnoHC81B1AY9K/8bMX3mxbIp5/nHHdypa//w= github.com/confluentinc/ccloud-sdk-go-v2/connect-custom-plugin v0.0.9 h1:o1zKZlKbnN9uv+Y8TxwesBRryUl3lEU6lnfndEJigxQ= @@ -1024,8 +1024,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/internal/kafka/command_cluster_create.go b/internal/kafka/command_cluster_create.go index 58fa936de1..09cdbc842a 100644 --- a/internal/kafka/command_cluster_create.go +++ b/internal/kafka/command_cluster_create.go @@ -65,6 +65,7 @@ func (c *clusterCommand) newCreateCommand() *cobra.Command { cmd.Flags().Int("cku", 0, `Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated".`) cmd.Flags().Int("max-ecku", 0, `Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. `+ `Kafka clusters with "HIGH" availability must have at least two eCKUs.`) + cmd.Flags().Bool("deletion-protection", false, "Enable deletion protection for the Kafka cluster.") pcmd.AddByokKeyFlag(cmd, c.AuthenticatedCLICommand) pcmd.AddNetworkFlag(cmd, c.AuthenticatedCLICommand) pcmd.AddContextFlag(cmd, c.CLICommand) @@ -171,6 +172,14 @@ func (c *clusterCommand) create(cmd *cobra.Command, args []string) error { setClusterConfigCku(&createCluster, int32(cku)) } + if cmd.Flags().Changed("deletion-protection") { + deletionProtection, err := cmd.Flags().GetBool("deletion-protection") + if err != nil { + return err + } + createCluster.Spec.SetDeletionProtection(deletionProtection) + } + if cmd.Flags().Changed("network") { network, err := cmd.Flags().GetString("network") if err != nil { diff --git a/internal/kafka/command_cluster_delete.go b/internal/kafka/command_cluster_delete.go index 33e084434f..2aadc74574 100644 --- a/internal/kafka/command_cluster_delete.go +++ b/internal/kafka/command_cluster_delete.go @@ -1,6 +1,12 @@ package kafka import ( + "bytes" + "encoding/json" + "io" + "net/http" + "strings" + "github.com/hashicorp/go-multierror" "github.com/spf13/cobra" @@ -10,6 +16,11 @@ import ( "github.com/confluentinc/cli/v4/pkg/resource" ) +const ( + errorCodeDeletionProtectionEnabled = "deletion_protection_enabled" + clusterDeletionProtectionDetail = "Cluster deletion is blocked by deletion protection." +) + func (c *clusterCommand) newDeleteCommand() *cobra.Command { cmd := &cobra.Command{ Use: "delete [id-2] ... [id-n]", @@ -43,8 +54,12 @@ func (c *clusterCommand) delete(cmd *cobra.Command, args []string) error { return errors.NewErrorWithSuggestions(err.Error(), PluralClusterEnvironmentSuggestions) } + deletionProtectionDetail := "" deleteFunc := func(id string) error { if httpResp, err := c.V2Client.DeleteKafkaCluster(id, environmentId); err != nil { + if detail, ok := parseDeletionProtectionErrDetail(httpResp); ok { + deletionProtectionDetail = detail + } return errors.CatchKafkaNotFoundError(err, id, httpResp) } return nil @@ -54,16 +69,68 @@ func (c *clusterCommand) delete(cmd *cobra.Command, args []string) error { errs := multierror.Append(err, c.removeKafkaClusterConfigs(deletedIds)) if errs.ErrorOrNil() != nil { + if suggestion := deletionProtectionErrorToSuggestion(deletionProtectionDetail); suggestion != "" { + return errors.NewErrorWithSuggestions(errs.Error(), suggestion) + } if len(args)-len(deletedIds) > 1 { - return errors.NewErrorWithSuggestions(err.Error(), "Ensure the clusters are not associated with any active Connect clusters.") + return errors.NewErrorWithSuggestions(errs.Error(), + "Ensure the clusters are not associated with any active Connect clusters.") } else { - return errors.NewErrorWithSuggestions(err.Error(), "Ensure the cluster is not associated with any active Connect clusters.") + return errors.NewErrorWithSuggestions(errs.Error(), + "Ensure the cluster is not associated with any active Connect clusters.") } } return nil } +type apiError struct { + Code string `json:"code"` + Detail string `json:"detail"` +} + +type apiErrorResponse struct { + Errors []apiError `json:"errors"` +} + +// parseDeletionProtectionErrDetail checks if the HTTP response indicates a deletion protection error +// Returns the error detail and true if the error is a deletion protection error, or empty string and false otherwise. +func parseDeletionProtectionErrDetail(r *http.Response) (string, bool) { + if r == nil || r.StatusCode != http.StatusConflict || r.Body == nil { + return "", false + } + + body, err := io.ReadAll(r.Body) + if err != nil { + return "", false + } + // Restore the body so downstream handlers can read it + r.Body = io.NopCloser(bytes.NewBuffer(body)) + + var res apiErrorResponse + if err := json.Unmarshal(body, &res); err != nil { + return "", false + } + + for _, apiErr := range res.Errors { + if apiErr.Code == errorCodeDeletionProtectionEnabled { + return apiErr.Detail, true + } + } + + return "", false +} + +// deletionProtectionErrorToSuggestion maps a deletion protection error detail to a user-facing suggestion. +func deletionProtectionErrorToSuggestion(errorMsg string) string { + switch { + case strings.EqualFold(errorMsg, clusterDeletionProtectionDetail): + return `Disable deletion_protection before deleting the cluster.` + default: + return "" + } +} + func (c *clusterCommand) removeKafkaClusterConfigs(deletedIds []string) error { for _, id := range deletedIds { c.Context.KafkaClusterContext.RemoveKafkaCluster(id) diff --git a/internal/kafka/command_cluster_delete_test.go b/internal/kafka/command_cluster_delete_test.go new file mode 100644 index 0000000000..00764839cd --- /dev/null +++ b/internal/kafka/command_cluster_delete_test.go @@ -0,0 +1,146 @@ +package kafka + +import ( + "io" + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseDeletionProtectionErrDetail(t *testing.T) { + tests := []struct { + name string + response *http.Response + expectedDetail string + expectedOk bool + }{ + { + name: "nil response", + response: nil, + expectedOk: false, + }, + { + name: "non-conflict status code", + response: &http.Response{ + StatusCode: http.StatusBadRequest, + Body: io.NopCloser(strings.NewReader(`{"errors": [{"code": "deletion_protection_enabled", "detail": "test"}]}`)), + }, + expectedOk: false, + }, + { + name: "conflict with deletion protection error code", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`{"errors": [{"code": "deletion_protection_enabled", "detail": "Cluster deletion is blocked by deletion protection."}]}`)), + }, + expectedDetail: "Cluster deletion is blocked by deletion protection.", + expectedOk: true, + }, + { + name: "conflict with different error code", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`{"errors": [{"code": "some_other_error", "detail": "some detail"}]}`)), + }, + expectedOk: false, + }, + { + name: "conflict with empty errors array", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`{"errors": []}`)), + }, + expectedOk: false, + }, + { + name: "conflict with invalid JSON body", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`not json`)), + }, + expectedOk: false, + }, + { + name: "conflict with nil body", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: nil, + }, + expectedOk: false, + }, + { + name: "deletion protection error is not first in errors array", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`{"errors": [` + + `{"code": "some_other_error", "detail": "other error"},` + + `{"code": "deletion_protection_enabled", "detail": "Cluster deletion is blocked by deletion protection."}` + + `]}`)), + }, + expectedDetail: "Cluster deletion is blocked by deletion protection.", + expectedOk: true, + }, + { + name: "body is restored after reading", + response: &http.Response{ + StatusCode: http.StatusConflict, + Body: io.NopCloser(strings.NewReader(`{"errors": [{"code": "deletion_protection_enabled", "detail": "Cluster deletion is blocked by deletion protection."}]}`)), + }, + expectedDetail: "Cluster deletion is blocked by deletion protection.", + expectedOk: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + detail, ok := parseDeletionProtectionErrDetail(tt.response) + require.Equal(t, tt.expectedOk, ok) + require.Equal(t, tt.expectedDetail, detail) + + // Verify body is restored for downstream handlers + if tt.response != nil && tt.response.Body != nil && ok { + body, err := io.ReadAll(tt.response.Body) + require.NoError(t, err) + require.NotEmpty(t, body) + } + }) + } +} + +func TestDeletionProtectionErrorToSuggestion(t *testing.T) { + tests := []struct { + name string + errorMsg string + expectedSuggestion string + }{ + { + name: "cluster deletion protection", + errorMsg: "Cluster deletion is blocked by deletion protection.", + expectedSuggestion: `Disable deletion_protection before deleting the cluster.`, + }, + { + name: "cluster deletion protection case insensitive", + errorMsg: "cluster deletion is blocked by deletion protection.", + expectedSuggestion: `Disable deletion_protection before deleting the cluster.`, + }, + { + name: "unknown deletion protection error", + errorMsg: "Some other deletion protection error.", + expectedSuggestion: "", + }, + { + name: "empty string", + errorMsg: "", + expectedSuggestion: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + suggestion := deletionProtectionErrorToSuggestion(tt.errorMsg) + require.Equal(t, tt.expectedSuggestion, suggestion) + }) + } +} diff --git a/internal/kafka/command_cluster_describe.go b/internal/kafka/command_cluster_describe.go index 00d64fbaaf..e0d260f016 100644 --- a/internal/kafka/command_cluster_describe.go +++ b/internal/kafka/command_cluster_describe.go @@ -18,7 +18,7 @@ import ( "github.com/confluentinc/cli/v4/pkg/resource" ) -var basicDescribeFields = []string{"IsCurrent", "Id", "Name", "Type", "IngressLimit", "EgressLimit", "Storage", "Cloud", "Availability", "Region", "Network", "Status", "Endpoint", "RestEndpoint"} +var basicDescribeFields = []string{"IsCurrent", "Id", "Name", "Type", "IngressLimit", "EgressLimit", "Storage", "Cloud", "Availability", "Region", "Network", "Status", "DeletionProtection", "Endpoint", "RestEndpoint"} type describeStruct struct { IsCurrent bool `human:"Current" serialized:"is_current"` @@ -35,6 +35,7 @@ type describeStruct struct { Availability string `human:"Availability" serialized:"availability"` Network string `human:"Network,omitempty" serialized:"network,omitempty"` Status string `human:"Status" serialized:"status"` + DeletionProtection bool `human:"Deletion Protection" serialized:"deletion_protection"` Endpoint string `human:"Endpoint" serialized:"endpoint"` ByokKeyId string `human:"BYOK Key ID" serialized:"byok_key_id"` EncryptionKeyId string `human:"Encryption Key ID" serialized:"encryption_key_id"` @@ -146,6 +147,7 @@ func convertClusterToDescribeStruct(cluster *cmkv2.CmkV2Cluster, usageLimits *ka Availability: ccloudv2.ToLower(cluster.Spec.GetAvailability()), Network: cluster.Spec.Network.GetId(), Status: getCmkClusterStatus(cluster), + DeletionProtection: cluster.Spec.GetDeletionProtection(), Endpoint: cluster.Spec.GetKafkaBootstrapEndpoint(), ByokKeyId: getCmkByokId(cluster), EncryptionKeyId: getCmkEncryptionKey(cluster), diff --git a/internal/kafka/command_cluster_list.go b/internal/kafka/command_cluster_list.go index 2959b21063..59f626d39e 100644 --- a/internal/kafka/command_cluster_list.go +++ b/internal/kafka/command_cluster_list.go @@ -68,6 +68,6 @@ func (c *clusterCommand) list(cmd *cobra.Command, _ []string) error { for _, cluster := range clusters { list.Add(convertClusterToDescribeStruct(&cluster, nil, c.Context)) } - list.Filter([]string{"IsCurrent", "Id", "Name", "Type", "Cloud", "Region", "Availability", "Network", "Status", "Endpoint"}) + list.Filter([]string{"IsCurrent", "Id", "Name", "Type", "Cloud", "Region", "Availability", "Network", "Status", "DeletionProtection", "Endpoint"}) return list.Print() } diff --git a/internal/kafka/command_cluster_update.go b/internal/kafka/command_cluster_update.go index 78eaeb50d0..f45624a785 100644 --- a/internal/kafka/command_cluster_update.go +++ b/internal/kafka/command_cluster_update.go @@ -44,12 +44,13 @@ func (c *clusterCommand) newUpdateCommand() *cobra.Command { cmd.Flags().String("type", "", `Type of the Kafka cluster. Only supports upgrading from "Basic" to "Standard".`) cmd.Flags().Int("max-ecku", 0, `Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. `+ `Kafka clusters with "HIGH" availability must have at least two eCKUs.`) + cmd.Flags().Bool("deletion-protection", false, "Enable deletion protection for the Kafka cluster. Use \"--deletion-protection=false\" to disable.") pcmd.AddContextFlag(cmd, c.CLICommand) pcmd.AddEnvironmentFlag(cmd, c.AuthenticatedCLICommand) pcmd.AddEndpointFlag(cmd, c.AuthenticatedCLICommand) pcmd.AddOutputFlag(cmd) - cmd.MarkFlagsOneRequired("name", "cku", "type", "max-ecku") + cmd.MarkFlagsOneRequired("name", "cku", "type", "max-ecku", "deletion-protection") return cmd } @@ -85,6 +86,14 @@ func (c *clusterCommand) update(cmd *cobra.Command, args []string) error { update.Spec.SetDisplayName(name) } + if cmd.Flags().Changed("deletion-protection") { + deletionProtection, err := cmd.Flags().GetBool("deletion-protection") + if err != nil { + return err + } + update.Spec.SetDeletionProtection(deletionProtection) + } + if cmd.Flags().Changed("cku") { cku, err := cmd.Flags().GetUint32("cku") if err != nil { diff --git a/test/fixtures/output/kafka/1.golden b/test/fixtures/output/kafka/1.golden index fa1f225136..39e7ee3218 100644 --- a/test/fixtures/output/kafka/1.golden +++ b/test/fixtures/output/kafka/1.golden @@ -24,6 +24,7 @@ Flags: --type string Specify the type of the Kafka cluster as "basic", "standard", "enterprise", "freight", or "dedicated". (default "basic") --cku int Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. --byok string Confluent Cloud Key ID of a registered encryption key (use "confluent byok create" to register a key). --network string Network ID. --context string CLI context name. diff --git a/test/fixtures/output/kafka/17.golden b/test/fixtures/output/kafka/17.golden index 2bde275f08..b92b70cdf9 100644 --- a/test/fixtures/output/kafka/17.golden +++ b/test/fixtures/output/kafka/17.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/18.golden b/test/fixtures/output/kafka/18.golden index 7d1785b75b..748a246120 100644 --- a/test/fixtures/output/kafka/18.golden +++ b/test/fixtures/output/kafka/18.golden @@ -10,6 +10,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "topic_count": 2 diff --git a/test/fixtures/output/kafka/19.golden b/test/fixtures/output/kafka/19.golden index 4424d28108..1502917f64 100644 --- a/test/fixtures/output/kafka/19.golden +++ b/test/fixtures/output/kafka/19.golden @@ -9,6 +9,7 @@ cloud: aws region: us-west-2 availability: single-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 topic_count: 2 diff --git a/test/fixtures/output/kafka/2.golden b/test/fixtures/output/kafka/2.golden index a2cb2d4c52..1557248bd0 100644 --- a/test/fixtures/output/kafka/2.golden +++ b/test/fixtures/output/kafka/2.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/22.golden b/test/fixtures/output/kafka/22.golden index cf08aa4c9f..50042662f2 100644 --- a/test/fixtures/output/kafka/22.golden +++ b/test/fixtures/output/kafka/22.golden @@ -12,6 +12,7 @@ It may take up to 1 hour for the Kafka cluster to be ready. The organization adm | Region | us-east-1 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/23.golden b/test/fixtures/output/kafka/23.golden index 473316b731..c9932c1677 100644 --- a/test/fixtures/output/kafka/23.golden +++ b/test/fixtures/output/kafka/23.golden @@ -10,6 +10,7 @@ "region": "us-east-1", "availability": "single-zone", "status": "PROVISIONING", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "https://pkc-endpoint" } diff --git a/test/fixtures/output/kafka/24.golden b/test/fixtures/output/kafka/24.golden index e0aae74983..d33073e6cb 100644 --- a/test/fixtures/output/kafka/24.golden +++ b/test/fixtures/output/kafka/24.golden @@ -9,5 +9,6 @@ cloud: aws region: us-east-1 availability: single-zone status: PROVISIONING +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: https://pkc-endpoint diff --git a/test/fixtures/output/kafka/26.golden b/test/fixtures/output/kafka/26.golden index 9d0a6819aa..712a920704 100644 --- a/test/fixtures/output/kafka/26.golden +++ b/test/fixtures/output/kafka/26.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/27.golden b/test/fixtures/output/kafka/27.golden index 0359fb0e5c..d400669998 100644 --- a/test/fixtures/output/kafka/27.golden +++ b/test/fixtures/output/kafka/27.golden @@ -12,6 +12,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | EXPANDING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/28.golden b/test/fixtures/output/kafka/28.golden index 5bdc59e2fd..1ce09cafd7 100644 --- a/test/fixtures/output/kafka/28.golden +++ b/test/fixtures/output/kafka/28.golden @@ -10,6 +10,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "topic_count": 2 diff --git a/test/fixtures/output/kafka/29.golden b/test/fixtures/output/kafka/29.golden index e4661fe709..045466eb78 100644 --- a/test/fixtures/output/kafka/29.golden +++ b/test/fixtures/output/kafka/29.golden @@ -9,6 +9,7 @@ cloud: aws region: us-west-2 availability: single-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 topic_count: 2 diff --git a/test/fixtures/output/kafka/30.golden b/test/fixtures/output/kafka/30.golden index cbc0854814..99c6f087db 100644 --- a/test/fixtures/output/kafka/30.golden +++ b/test/fixtures/output/kafka/30.golden @@ -11,6 +11,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/31.golden b/test/fixtures/output/kafka/31.golden index cdbcb85cfa..990969c8eb 100644 --- a/test/fixtures/output/kafka/31.golden +++ b/test/fixtures/output/kafka/31.golden @@ -11,6 +11,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "topic_count": 2 diff --git a/test/fixtures/output/kafka/32.golden b/test/fixtures/output/kafka/32.golden index 5fd804db85..3fba339683 100644 --- a/test/fixtures/output/kafka/32.golden +++ b/test/fixtures/output/kafka/32.golden @@ -10,6 +10,7 @@ cloud: aws region: us-west-2 availability: single-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 topic_count: 2 diff --git a/test/fixtures/output/kafka/33.golden b/test/fixtures/output/kafka/33.golden index 14b64e1817..822fdbd48d 100644 --- a/test/fixtures/output/kafka/33.golden +++ b/test/fixtures/output/kafka/33.golden @@ -12,6 +12,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | EXPANDING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/34.golden b/test/fixtures/output/kafka/34.golden index fcc393208a..29e82169ab 100644 --- a/test/fixtures/output/kafka/34.golden +++ b/test/fixtures/output/kafka/34.golden @@ -12,6 +12,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "EXPANDING", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "topic_count": 2 diff --git a/test/fixtures/output/kafka/35.golden b/test/fixtures/output/kafka/35.golden index 8998600878..a8975ce4dd 100644 --- a/test/fixtures/output/kafka/35.golden +++ b/test/fixtures/output/kafka/35.golden @@ -11,6 +11,7 @@ cloud: aws region: us-west-2 availability: single-zone status: EXPANDING +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 topic_count: 2 diff --git a/test/fixtures/output/kafka/36.golden b/test/fixtures/output/kafka/36.golden index 489d5633e2..de4a583ac0 100644 --- a/test/fixtures/output/kafka/36.golden +++ b/test/fixtures/output/kafka/36.golden @@ -11,6 +11,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | Encryption Key ID | abc123 | | REST Endpoint | http://127.0.0.1:1025 | diff --git a/test/fixtures/output/kafka/37.golden b/test/fixtures/output/kafka/37.golden index ad128d3e73..9bfd16350d 100644 --- a/test/fixtures/output/kafka/37.golden +++ b/test/fixtures/output/kafka/37.golden @@ -11,6 +11,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "encryption_key_id": "abc123", "rest_endpoint": "http://127.0.0.1:1025", diff --git a/test/fixtures/output/kafka/38.golden b/test/fixtures/output/kafka/38.golden index c31eb650d6..a76dd99ed8 100644 --- a/test/fixtures/output/kafka/38.golden +++ b/test/fixtures/output/kafka/38.golden @@ -10,6 +10,7 @@ cloud: aws region: us-west-2 availability: single-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint encryption_key_id: abc123 rest_endpoint: http://127.0.0.1:1025 diff --git a/test/fixtures/output/kafka/39.golden b/test/fixtures/output/kafka/39.golden index b7a77ed6e0..8de01fe7ed 100644 --- a/test/fixtures/output/kafka/39.golden +++ b/test/fixtures/output/kafka/39.golden @@ -12,6 +12,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | EXPANDING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/41.golden b/test/fixtures/output/kafka/41.golden index 9365ba57a7..c2f66adc8e 100644 --- a/test/fixtures/output/kafka/41.golden +++ b/test/fixtures/output/kafka/41.golden @@ -11,6 +11,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/42.golden b/test/fixtures/output/kafka/42.golden index ede8a871a9..ce834d043b 100644 --- a/test/fixtures/output/kafka/42.golden +++ b/test/fixtures/output/kafka/42.golden @@ -11,6 +11,7 @@ "region": "us-west-2", "availability": "single-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "topic_count": 2 diff --git a/test/fixtures/output/kafka/43.golden b/test/fixtures/output/kafka/43.golden index 8505cfbb8e..9a325d0b4e 100644 --- a/test/fixtures/output/kafka/43.golden +++ b/test/fixtures/output/kafka/43.golden @@ -10,6 +10,7 @@ cloud: aws region: us-west-2 availability: single-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 topic_count: 2 diff --git a/test/fixtures/output/kafka/44.golden b/test/fixtures/output/kafka/44.golden index 825de56471..e779546fb0 100644 --- a/test/fixtures/output/kafka/44.golden +++ b/test/fixtures/output/kafka/44.golden @@ -12,6 +12,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | SHRINKING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/45.golden b/test/fixtures/output/kafka/45.golden index 56b4076af6..ab0591676d 100644 --- a/test/fixtures/output/kafka/45.golden +++ b/test/fixtures/output/kafka/45.golden @@ -12,6 +12,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | SHRINKING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/47.golden b/test/fixtures/output/kafka/47.golden index 491851940b..a6cfe30200 100644 --- a/test/fixtures/output/kafka/47.golden +++ b/test/fixtures/output/kafka/47.golden @@ -1,14 +1,14 @@ - Current | ID | Name | Type | Cloud | Region | Availability | Network | Status | Endpoint -----------+---------+------+-----------+-------+-------------+--------------+----------+--------------+---------------------------- - | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | - | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | - | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | - | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | - | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | - | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | - | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | - | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | - | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | SASL_SSL://kafka-endpoint - | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | SASL_SSL://kafka-endpoint - | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | SASL_SSL://kafka-endpoint - | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | SASL_SSL://kafka-endpoint + Current | ID | Name | Type | Cloud | Region | Availability | Network | Status | Deletion Protection | Endpoint +----------+---------+------+-----------+-------+-------------+--------------+----------+--------------+---------------------+---------------------------- + | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | false | + | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | false | + | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | false | + | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | false | + | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | true | + | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | true | + | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | true | + | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | true | + | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | false | SASL_SSL://kafka-endpoint + | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | false | SASL_SSL://kafka-endpoint + | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | false | SASL_SSL://kafka-endpoint + | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | false | SASL_SSL://kafka-endpoint diff --git a/test/fixtures/output/kafka/6.golden b/test/fixtures/output/kafka/6.golden index b9040c2961..f5819a23a3 100644 --- a/test/fixtures/output/kafka/6.golden +++ b/test/fixtures/output/kafka/6.golden @@ -1,5 +1,5 @@ - Current | ID | Name | Type | Cloud | Region | Availability | Network | Status | Endpoint -----------+---------+------+-----------+-------+-------------+--------------+----------+--------------+---------------------------- - | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | - | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | - | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | SASL_SSL://kafka-endpoint + Current | ID | Name | Type | Cloud | Region | Availability | Network | Status | Deletion Protection | Endpoint +----------+---------+------+-----------+-------+-------------+--------------+----------+--------------+---------------------+---------------------------- + | lkc-123 | abc | BASIC | gcp | us-central1 | single-zone | | PROVISIONING | false | + | lkc-456 | def | BASIC | gcp | us-central1 | multi-zone | | PROVISIONING | true | + | lkc-789 | ghi | DEDICATED | aws | us-west-2 | single-zone | n-abcde1 | UP | false | SASL_SSL://kafka-endpoint diff --git a/test/fixtures/output/kafka/7.golden b/test/fixtures/output/kafka/7.golden index 3f4f2a34ab..a482e04b68 100644 --- a/test/fixtures/output/kafka/7.golden +++ b/test/fixtures/output/kafka/7.golden @@ -8,6 +8,7 @@ "region": "us-central1", "availability": "single-zone", "status": "PROVISIONING", + "deletion_protection": false, "endpoint": "" }, { @@ -19,6 +20,7 @@ "region": "us-central1", "availability": "multi-zone", "status": "PROVISIONING", + "deletion_protection": true, "endpoint": "" }, { @@ -31,6 +33,7 @@ "availability": "single-zone", "network": "n-abcde1", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint" } ] diff --git a/test/fixtures/output/kafka/8.golden b/test/fixtures/output/kafka/8.golden index 6542b38632..989bfba36c 100644 --- a/test/fixtures/output/kafka/8.golden +++ b/test/fixtures/output/kafka/8.golden @@ -6,6 +6,7 @@ region: us-central1 availability: single-zone status: PROVISIONING + deletion_protection: false endpoint: "" - is_current: false id: lkc-456 @@ -15,6 +16,7 @@ region: us-central1 availability: multi-zone status: PROVISIONING + deletion_protection: true endpoint: "" - is_current: false id: lkc-789 @@ -25,4 +27,5 @@ availability: single-zone network: n-abcde1 status: UP + deletion_protection: false endpoint: SASL_SSL://kafka-endpoint diff --git a/test/fixtures/output/kafka/cluster-describe-dedicated-provisioning.golden b/test/fixtures/output/kafka/cluster-describe-dedicated-provisioning.golden index cca32f3ad3..7ec52de5d8 100644 --- a/test/fixtures/output/kafka/cluster-describe-dedicated-provisioning.golden +++ b/test/fixtures/output/kafka/cluster-describe-dedicated-provisioning.golden @@ -12,6 +12,7 @@ | Availability | single-zone | | Network | n-abcde1 | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | | | REST Endpoint | | +----------------------+-------------------------------------+ diff --git a/test/fixtures/output/kafka/cluster/cck-byok.golden b/test/fixtures/output/kafka/cluster/cck-byok.golden index ee70b745c0..d113f63a72 100644 --- a/test/fixtures/output/kafka/cluster/cck-byok.golden +++ b/test/fixtures/output/kafka/cluster/cck-byok.golden @@ -12,6 +12,7 @@ It may take up to 1 hour for the Kafka cluster to be ready. The organization adm | Region | us-east-1 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/cck-network.golden b/test/fixtures/output/kafka/cluster/cck-network.golden index d7a4ea3209..269e12df66 100644 --- a/test/fixtures/output/kafka/cluster/cck-network.golden +++ b/test/fixtures/output/kafka/cluster/cck-network.golden @@ -13,6 +13,7 @@ It may take up to 1 hour for the Kafka cluster to be ready. The organization adm | Availability | single-zone | | Network | n-abcde1 | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-basic-with-ecku-limits.golden b/test/fixtures/output/kafka/cluster/create-basic-with-ecku-limits.golden index 559718c63f..e6d8e24cf9 100644 --- a/test/fixtures/output/kafka/cluster/create-basic-with-ecku-limits.golden +++ b/test/fixtures/output/kafka/cluster/create-basic-with-ecku-limits.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-west-2 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+-----------------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-deletion-protection-false.golden b/test/fixtures/output/kafka/cluster/create-deletion-protection-false.golden new file mode 100644 index 0000000000..42ab988d2a --- /dev/null +++ b/test/fixtures/output/kafka/cluster/create-deletion-protection-false.golden @@ -0,0 +1,17 @@ +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) | 600 | +| Egress Limit (MB/s) | 1800 | +| Storage | Unlimited | +| Cloud | aws | +| Region | us-east-1 | +| Availability | multi-zone | +| Status | PROVISIONING | +| Deletion Protection | false | +| Endpoint | SASL_SSL://kafka-endpoint | +| REST Endpoint | https://pkc-endpoint | ++----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-basic.golden b/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-basic.golden new file mode 100644 index 0000000000..465a2c0ee6 --- /dev/null +++ b/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-basic.golden @@ -0,0 +1 @@ +Error: Deletion protection is not supported for BASIC clusters. diff --git a/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-standard.golden b/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-standard.golden new file mode 100644 index 0000000000..d6dcca83da --- /dev/null +++ b/test/fixtures/output/kafka/cluster/create-deletion-protection-unsupported-standard.golden @@ -0,0 +1 @@ +Error: Deletion protection is not supported for STANDARD clusters. diff --git a/test/fixtures/output/kafka/cluster/create-deletion-protection.golden b/test/fixtures/output/kafka/cluster/create-deletion-protection.golden new file mode 100644 index 0000000000..e585a9b79a --- /dev/null +++ b/test/fixtures/output/kafka/cluster/create-deletion-protection.golden @@ -0,0 +1,17 @@ +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) | 600 | +| Egress Limit (MB/s) | 1800 | +| Storage | Unlimited | +| Cloud | aws | +| Region | us-east-1 | +| Availability | multi-zone | +| Status | PROVISIONING | +| Deletion Protection | true | +| Endpoint | SASL_SSL://kafka-endpoint | +| REST Endpoint | https://pkc-endpoint | ++----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-enterprise-max-ecku.golden b/test/fixtures/output/kafka/cluster/create-enterprise-max-ecku.golden index ec0a3de673..83925414c1 100644 --- a/test/fixtures/output/kafka/cluster/create-enterprise-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/create-enterprise-max-ecku.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | multi-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | | Max eCKU | 4 | diff --git a/test/fixtures/output/kafka/cluster/create-enterprise.golden b/test/fixtures/output/kafka/cluster/create-enterprise.golden index c29b50c469..42ab988d2a 100644 --- a/test/fixtures/output/kafka/cluster/create-enterprise.golden +++ b/test/fixtures/output/kafka/cluster/create-enterprise.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | multi-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-flag-error.golden b/test/fixtures/output/kafka/cluster/create-flag-error.golden index aa23c33f72..461a7dd007 100644 --- a/test/fixtures/output/kafka/cluster/create-flag-error.golden +++ b/test/fixtures/output/kafka/cluster/create-flag-error.golden @@ -1,4 +1,4 @@ -Error: at least one of the flags in the group [name cku type max-ecku] is required +Error: at least one of the flags in the group [name cku type max-ecku deletion-protection] is required Usage: confluent kafka cluster update [flags] @@ -20,6 +20,7 @@ Flags: --cku uint32 Number of Confluent Kafka Units. For Kafka clusters of type "dedicated" only. When shrinking a cluster, you must reduce capacity one CKU at a time. --type string Type of the Kafka cluster. Only supports upgrading from "Basic" to "Standard". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. Use "--deletion-protection=false" to disable. --context string CLI context name. --environment string Environment ID. --kafka-endpoint string Endpoint to be used for this Kafka cluster. diff --git a/test/fixtures/output/kafka/cluster/create-freight-low.golden b/test/fixtures/output/kafka/cluster/create-freight-low.golden index afdb69b999..a7f89a3c62 100644 --- a/test/fixtures/output/kafka/cluster/create-freight-low.golden +++ b/test/fixtures/output/kafka/cluster/create-freight-low.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | low | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-freight-max-ecku.golden b/test/fixtures/output/kafka/cluster/create-freight-max-ecku.golden index f5750a5db7..edfd079aff 100644 --- a/test/fixtures/output/kafka/cluster/create-freight-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/create-freight-max-ecku.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | low | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | | Max eCKU | 3 | diff --git a/test/fixtures/output/kafka/cluster/create-freight.golden b/test/fixtures/output/kafka/cluster/create-freight.golden index 580cfb60c5..39e304ce7a 100644 --- a/test/fixtures/output/kafka/cluster/create-freight.golden +++ b/test/fixtures/output/kafka/cluster/create-freight.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | high | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/create-help.golden b/test/fixtures/output/kafka/cluster/create-help.golden index f5c8203cfd..dfbe293899 100644 --- a/test/fixtures/output/kafka/cluster/create-help.golden +++ b/test/fixtures/output/kafka/cluster/create-help.golden @@ -27,6 +27,7 @@ Flags: --type string Specify the type of the Kafka cluster as "basic", "standard", "enterprise", "freight", or "dedicated". (default "basic") --cku int Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. --byok string Confluent Cloud Key ID of a registered encryption key (use "confluent byok create" to register a key). --network string Network ID. --context string CLI context name. diff --git a/test/fixtures/output/kafka/cluster/create-standard-with-ecku-limits.golden b/test/fixtures/output/kafka/cluster/create-standard-with-ecku-limits.golden index 7a6a62963e..e9b1db9af3 100644 --- a/test/fixtures/output/kafka/cluster/create-standard-with-ecku-limits.golden +++ b/test/fixtures/output/kafka/cluster/create-standard-with-ecku-limits.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-west-2 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | +----------------------+--------------------------------------+ diff --git a/test/fixtures/output/kafka/cluster/delete-deletion-protected.golden b/test/fixtures/output/kafka/cluster/delete-deletion-protected.golden new file mode 100644 index 0000000000..79f2c00d68 --- /dev/null +++ b/test/fixtures/output/kafka/cluster/delete-deletion-protected.golden @@ -0,0 +1,4 @@ +Error: failed to delete lkc-deletion-protected: Cluster deletion is blocked by deletion protection. + +Suggestions: + Disable deletion_protection before deleting the cluster. diff --git a/test/fixtures/output/kafka/cluster/describe-basic-with-default-v2-limits.golden b/test/fixtures/output/kafka/cluster/describe-basic-with-default-v2-limits.golden index 759f334365..ab9bfd5b1d 100644 --- a/test/fixtures/output/kafka/cluster/describe-basic-with-default-v2-limits.golden +++ b/test/fixtures/output/kafka/cluster/describe-basic-with-default-v2-limits.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/cluster/describe-basic-with-ecku-limits.golden b/test/fixtures/output/kafka/cluster/describe-basic-with-ecku-limits.golden index 41f860ce36..6d5463354a 100644 --- a/test/fixtures/output/kafka/cluster/describe-basic-with-ecku-limits.golden +++ b/test/fixtures/output/kafka/cluster/describe-basic-with-ecku-limits.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 5 | diff --git a/test/fixtures/output/kafka/cluster/describe-deletion-protected.golden b/test/fixtures/output/kafka/cluster/describe-deletion-protected.golden new file mode 100644 index 0000000000..e1b6ee211c --- /dev/null +++ b/test/fixtures/output/kafka/cluster/describe-deletion-protected.golden @@ -0,0 +1,17 @@ ++----------------------+---------------------------------+ +| Current | true | +| ID | lkc-describe-deletion-protected | +| Name | kafka-cluster | +| Type | BASIC | +| Ingress Limit (MB/s) | 250 | +| Egress Limit (MB/s) | 750 | +| Storage | 5000 GB | +| Cloud | aws | +| Region | us-west-2 | +| Availability | single-zone | +| Status | UP | +| Deletion Protection | true | +| Endpoint | SASL_SSL://kafka-endpoint | +| REST Endpoint | http://127.0.0.1:1025 | +| Topic Count | 2 | ++----------------------+---------------------------------+ diff --git a/test/fixtures/output/kafka/cluster/describe-with-usage-limits-error.golden b/test/fixtures/output/kafka/cluster/describe-with-usage-limits-error.golden index 5a84f8d52c..3285ad5f7a 100644 --- a/test/fixtures/output/kafka/cluster/describe-with-usage-limits-error.golden +++ b/test/fixtures/output/kafka/cluster/describe-with-usage-limits-error.golden @@ -15,6 +15,7 @@ Suggestions: | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/fixtures/output/kafka/cluster/update-basic-with-ecku-limits.golden b/test/fixtures/output/kafka/cluster/update-basic-with-ecku-limits.golden index e260479c13..5476d56511 100644 --- a/test/fixtures/output/kafka/cluster/update-basic-with-ecku-limits.golden +++ b/test/fixtures/output/kafka/cluster/update-basic-with-ecku-limits.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 5 | diff --git a/test/fixtures/output/kafka/cluster/update-deletion-protection-disable.golden b/test/fixtures/output/kafka/cluster/update-deletion-protection-disable.golden new file mode 100644 index 0000000000..30758b57a3 --- /dev/null +++ b/test/fixtures/output/kafka/cluster/update-deletion-protection-disable.golden @@ -0,0 +1,17 @@ ++----------------------+---------------------------+ +| Current | true | +| ID | lkc-update | +| Name | | +| Type | BASIC | +| Ingress Limit (MB/s) | 250 | +| Egress Limit (MB/s) | 750 | +| Storage | 5000 GB | +| Cloud | aws | +| Region | us-west-2 | +| Availability | single-zone | +| Status | UP | +| Deletion Protection | false | +| Endpoint | SASL_SSL://kafka-endpoint | +| REST Endpoint | http://127.0.0.1:1025 | +| Topic Count | 2 | ++----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/update-deletion-protection-enable.golden b/test/fixtures/output/kafka/cluster/update-deletion-protection-enable.golden new file mode 100644 index 0000000000..2cfb5c15ca --- /dev/null +++ b/test/fixtures/output/kafka/cluster/update-deletion-protection-enable.golden @@ -0,0 +1,17 @@ ++----------------------+---------------------------+ +| Current | true | +| ID | lkc-update-enterprise | +| Name | | +| Type | ENTERPRISE | +| Ingress Limit (MB/s) | 600 | +| Egress Limit (MB/s) | 1800 | +| Storage | Unlimited | +| Cloud | aws | +| Region | us-west-2 | +| Availability | multi-zone | +| Status | UP | +| Deletion Protection | true | +| Endpoint | SASL_SSL://kafka-endpoint | +| REST Endpoint | http://127.0.0.1:1025 | +| Topic Count | 2 | ++----------------------+---------------------------+ diff --git a/test/fixtures/output/kafka/cluster/update-deletion-protection-unsupported-basic.golden b/test/fixtures/output/kafka/cluster/update-deletion-protection-unsupported-basic.golden new file mode 100644 index 0000000000..ab07c8abb0 --- /dev/null +++ b/test/fixtures/output/kafka/cluster/update-deletion-protection-unsupported-basic.golden @@ -0,0 +1,4 @@ +Error: failed to update Kafka cluster: Deletion protection is not supported for BASIC clusters. + +Suggestions: + A cluster can't be updated while still provisioning. If you just created this cluster, retry in a few minutes. diff --git a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-json.golden b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-json.golden index 37a86d918a..5887d4ebda 100644 --- a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-json.golden +++ b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-json.golden @@ -10,6 +10,7 @@ "region": "us-west-2", "availability": "multi-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "max_ecku": 5, diff --git a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-with-name.golden b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-with-name.golden index 5c9899f15d..59ea10708e 100644 --- a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-with-name.golden +++ b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-with-name.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | multi-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 7 | diff --git a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-yaml.golden b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-yaml.golden index f85c1199d4..957a966fda 100644 --- a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-yaml.golden +++ b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku-yaml.golden @@ -9,6 +9,7 @@ cloud: aws region: us-west-2 availability: multi-zone status: UP +deletion_protection: false endpoint: SASL_SSL://kafka-endpoint rest_endpoint: http://127.0.0.1:1025 max_ecku: 5 diff --git a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku.golden b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku.golden index 9de273af1d..d1081c69e5 100644 --- a/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/update-enterprise-max-ecku.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | multi-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 5 | diff --git a/test/fixtures/output/kafka/cluster/update-freight-max-ecku-json.golden b/test/fixtures/output/kafka/cluster/update-freight-max-ecku-json.golden index c94b54b835..dbeff6df5d 100644 --- a/test/fixtures/output/kafka/cluster/update-freight-max-ecku-json.golden +++ b/test/fixtures/output/kafka/cluster/update-freight-max-ecku-json.golden @@ -10,6 +10,7 @@ "region": "us-west-2", "availability": "multi-zone", "status": "UP", + "deletion_protection": false, "endpoint": "SASL_SSL://kafka-endpoint", "rest_endpoint": "http://127.0.0.1:1025", "max_ecku": 50, diff --git a/test/fixtures/output/kafka/cluster/update-freight-max-ecku-with-name.golden b/test/fixtures/output/kafka/cluster/update-freight-max-ecku-with-name.golden index 6b724df33d..63a37dffdf 100644 --- a/test/fixtures/output/kafka/cluster/update-freight-max-ecku-with-name.golden +++ b/test/fixtures/output/kafka/cluster/update-freight-max-ecku-with-name.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | multi-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 75 | diff --git a/test/fixtures/output/kafka/cluster/update-freight-max-ecku.golden b/test/fixtures/output/kafka/cluster/update-freight-max-ecku.golden index 7474503c02..e513083ab2 100644 --- a/test/fixtures/output/kafka/cluster/update-freight-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/update-freight-max-ecku.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | multi-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 50 | diff --git a/test/fixtures/output/kafka/cluster/update-help.golden b/test/fixtures/output/kafka/cluster/update-help.golden index e3ae69c2e2..c8ab12b6b8 100644 --- a/test/fixtures/output/kafka/cluster/update-help.golden +++ b/test/fixtures/output/kafka/cluster/update-help.golden @@ -21,6 +21,7 @@ Flags: --cku uint32 Number of Confluent Kafka Units. For Kafka clusters of type "dedicated" only. When shrinking a cluster, you must reduce capacity one CKU at a time. --type string Type of the Kafka cluster. Only supports upgrading from "Basic" to "Standard". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. Use "--deletion-protection=false" to disable. --context string CLI context name. --environment string Environment ID. --kafka-endpoint string Endpoint to be used for this Kafka cluster. diff --git a/test/fixtures/output/kafka/cluster/update-max-ecku.golden b/test/fixtures/output/kafka/cluster/update-max-ecku.golden index e0bd2e41ce..bd89d23b7c 100644 --- a/test/fixtures/output/kafka/cluster/update-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/update-max-ecku.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 4 | diff --git a/test/fixtures/output/kafka/cluster/update-standard-max-ecku.golden b/test/fixtures/output/kafka/cluster/update-standard-max-ecku.golden index 34d0feb165..67b207c965 100644 --- a/test/fixtures/output/kafka/cluster/update-standard-max-ecku.golden +++ b/test/fixtures/output/kafka/cluster/update-standard-max-ecku.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 2 | diff --git a/test/fixtures/output/kafka/cluster/update-type-empty-error.golden b/test/fixtures/output/kafka/cluster/update-type-empty-error.golden index ac44cb2c0c..16eaf7e6be 100644 --- a/test/fixtures/output/kafka/cluster/update-type-empty-error.golden +++ b/test/fixtures/output/kafka/cluster/update-type-empty-error.golden @@ -20,6 +20,7 @@ Flags: --cku uint32 Number of Confluent Kafka Units. For Kafka clusters of type "dedicated" only. When shrinking a cluster, you must reduce capacity one CKU at a time. --type string Type of the Kafka cluster. Only supports upgrading from "Basic" to "Standard". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. Use "--deletion-protection=false" to disable. --context string CLI context name. --environment string Environment ID. --kafka-endpoint string Endpoint to be used for this Kafka cluster. diff --git a/test/fixtures/output/kafka/cluster/update-type-max-ecku-success.golden b/test/fixtures/output/kafka/cluster/update-type-max-ecku-success.golden index 7377231241..5d3f725283 100644 --- a/test/fixtures/output/kafka/cluster/update-type-max-ecku-success.golden +++ b/test/fixtures/output/kafka/cluster/update-type-max-ecku-success.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 6 | diff --git a/test/fixtures/output/kafka/cluster/update-type-success.golden b/test/fixtures/output/kafka/cluster/update-type-success.golden index b4ce5a1a87..06da726e61 100644 --- a/test/fixtures/output/kafka/cluster/update-type-success.golden +++ b/test/fixtures/output/kafka/cluster/update-type-success.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Max eCKU | 10 | diff --git a/test/fixtures/output/kafka/create-basic-max-ecku-error.golden b/test/fixtures/output/kafka/create-basic-max-ecku-error.golden index 329d9e0b65..8a54ce193c 100644 --- a/test/fixtures/output/kafka/create-basic-max-ecku-error.golden +++ b/test/fixtures/output/kafka/create-basic-max-ecku-error.golden @@ -24,6 +24,7 @@ Flags: --type string Specify the type of the Kafka cluster as "basic", "standard", "enterprise", "freight", or "dedicated". (default "basic") --cku int Number of Confluent Kafka Units (non-negative). Required for Kafka clusters of type "dedicated". --max-ecku int Maximum number of Elastic Confluent Kafka Units (eCKUs) that Kafka clusters should auto-scale to. Kafka clusters with "HIGH" availability must have at least two eCKUs. + --deletion-protection Enable deletion protection for the Kafka cluster. --byok string Confluent Cloud Key ID of a registered encryption key (use "confluent byok create" to register a key). --network string Network ID. --context string CLI context name. diff --git a/test/fixtures/output/kafka/create-basic-max-ecku.golden b/test/fixtures/output/kafka/create-basic-max-ecku.golden index 45875acf82..f602f2aa3b 100644 --- a/test/fixtures/output/kafka/create-basic-max-ecku.golden +++ b/test/fixtures/output/kafka/create-basic-max-ecku.golden @@ -11,6 +11,7 @@ It may take up to 5 minutes for the Kafka cluster to be ready. | Region | us-east-1 | | Availability | single-zone | | Status | PROVISIONING | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | https://pkc-endpoint | | Max eCKU | 2 | diff --git a/test/fixtures/output/kafka/describe-unknown-cluster-type.golden b/test/fixtures/output/kafka/describe-unknown-cluster-type.golden index caed4e63d1..f80ef83411 100644 --- a/test/fixtures/output/kafka/describe-unknown-cluster-type.golden +++ b/test/fixtures/output/kafka/describe-unknown-cluster-type.golden @@ -10,6 +10,7 @@ | Region | us-west-2 | | Availability | single-zone | | Status | UP | +| Deletion Protection | false | | Endpoint | SASL_SSL://kafka-endpoint | | REST Endpoint | http://127.0.0.1:1025 | | Topic Count | 2 | diff --git a/test/kafka_test.go b/test/kafka_test.go index 750388175d..a223001b70 100644 --- a/test/kafka_test.go +++ b/test/kafka_test.go @@ -77,6 +77,19 @@ func (s *CLITestSuite) TestKafka() { {args: "kafka cluster update lkc-update --type", fixture: "kafka/cluster/update-type-empty-error.golden", exitCode: 1}, {args: "kafka cluster update lkc-update --type basic", fixture: "kafka/cluster/update-type-invalid-error.golden", exitCode: 1}, + // Deletion protection tests + {args: "kafka cluster describe lkc-describe-deletion-protected", fixture: "kafka/cluster/describe-deletion-protected.golden"}, + {args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type enterprise --availability multi-zone --deletion-protection", fixture: "kafka/cluster/create-deletion-protection.golden"}, + {args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type enterprise --availability multi-zone --deletion-protection=true", fixture: "kafka/cluster/create-deletion-protection.golden"}, + {args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type enterprise --availability multi-zone --deletion-protection=false", fixture: "kafka/cluster/create-deletion-protection-false.golden"}, + {args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type basic --deletion-protection", fixture: "kafka/cluster/create-deletion-protection-unsupported-basic.golden", exitCode: 1}, + {args: "kafka cluster create my-new-cluster --cloud aws --region us-east-1 --type standard --deletion-protection", fixture: "kafka/cluster/create-deletion-protection-unsupported-standard.golden", exitCode: 1}, + {args: "kafka cluster update lkc-update --deletion-protection", fixture: "kafka/cluster/update-deletion-protection-unsupported-basic.golden", exitCode: 1}, + {args: "kafka cluster update lkc-update --deletion-protection=true", fixture: "kafka/cluster/update-deletion-protection-unsupported-basic.golden", exitCode: 1}, + {args: "kafka cluster update lkc-update --deletion-protection=false", fixture: "kafka/cluster/update-deletion-protection-disable.golden"}, + {args: "kafka cluster update lkc-update-enterprise --deletion-protection", fixture: "kafka/cluster/update-deletion-protection-enable.golden"}, + {args: "kafka cluster delete lkc-deletion-protected --force", fixture: "kafka/cluster/delete-deletion-protected.golden", exitCode: 1}, + {args: "kafka cluster delete --force", fixture: "kafka/3.golden", exitCode: 1}, {args: "kafka cluster delete lkc-unknown --force", fixture: "kafka/cluster/delete-unknown-error.golden", exitCode: 1}, {args: "kafka cluster delete lkc-def973 --force", fixture: "kafka/5.golden"}, @@ -97,7 +110,6 @@ func (s *CLITestSuite) TestKafka() { {args: "kafka cluster describe lkc-describe", fixture: "kafka/17.golden"}, {args: "kafka cluster describe lkc-describe -o json", fixture: "kafka/18.golden"}, {args: "kafka cluster describe lkc-describe -o yaml", fixture: "kafka/19.golden"}, - {args: "kafka cluster describe lkc-describe-dedicated", fixture: "kafka/30.golden"}, {args: "kafka cluster describe lkc-describe-dedicated -o json", fixture: "kafka/31.golden"}, {args: "kafka cluster describe lkc-describe-dedicated -o yaml", fixture: "kafka/32.golden"}, diff --git a/test/test-server/cmk_handlers.go b/test/test-server/cmk_handlers.go index aa6f86d765..e7cf5ec338 100644 --- a/test/test-server/cmk_handlers.go +++ b/test/test-server/cmk_handlers.go @@ -2,6 +2,7 @@ package testserver import ( "encoding/json" + "fmt" "net/http" "strings" "testing" @@ -88,6 +89,22 @@ func handleCmkKafkaClusterCreate(t *testing.T) http.HandlerFunc { } } + if req.Spec.GetDeletionProtection() { + skuName := "BASIC" + if req.Spec.Config.CmkV2Standard != nil { + skuName = "STANDARD" + } + if req.Spec.Config.CmkV2Basic != nil || req.Spec.Config.CmkV2Standard != nil { + err := writeError(w, fmt.Sprintf("Deletion protection is not supported for %s clusters.", skuName)) + require.NoError(t, err) + return + } + } + + if req.Spec.HasDeletionProtection() { + cluster.Spec.SetDeletionProtection(req.Spec.GetDeletionProtection()) + } + if req.Spec.GetCloud() == "oops" { err := writeError(w, "Service provider must be set to AWS, GCP or AZURE.") require.NoError(t, err) @@ -120,28 +137,47 @@ func handleCmkClusters(t *testing.T) http.HandlerFunc { cluster := cmkv2.CmkV2Cluster{ Id: cmkv2.PtrString("lkc-123"), Spec: &cmkv2.CmkV2ClusterSpec{ - DisplayName: cmkv2.PtrString("abc"), - Cloud: cmkv2.PtrString("gcp"), - Region: cmkv2.PtrString("us-central1"), - Config: &cmkv2.CmkV2ClusterSpecConfigOneOf{CmkV2Basic: &cmkv2.CmkV2Basic{Kind: "Basic"}}, - Availability: cmkv2.PtrString("SINGLE_ZONE"), + DisplayName: cmkv2.PtrString("abc"), + Cloud: cmkv2.PtrString("gcp"), + Region: cmkv2.PtrString("us-central1"), + Config: &cmkv2.CmkV2ClusterSpecConfigOneOf{CmkV2Basic: &cmkv2.CmkV2Basic{Kind: "Basic"}}, + Availability: cmkv2.PtrString("SINGLE_ZONE"), + DeletionProtection: cmkv2.PtrBool(false), }, Status: &cmkv2.CmkV2ClusterStatus{Phase: "PROVISIONING"}, } clusterMultizone := cmkv2.CmkV2Cluster{ Id: cmkv2.PtrString("lkc-456"), Spec: &cmkv2.CmkV2ClusterSpec{ - DisplayName: cmkv2.PtrString("def"), - Cloud: cmkv2.PtrString("gcp"), - Region: cmkv2.PtrString("us-central1"), - Config: &cmkv2.CmkV2ClusterSpecConfigOneOf{CmkV2Basic: &cmkv2.CmkV2Basic{Kind: "Basic"}}, - Availability: cmkv2.PtrString("MULTI_ZONE"), + DisplayName: cmkv2.PtrString("def"), + Cloud: cmkv2.PtrString("gcp"), + Region: cmkv2.PtrString("us-central1"), + Config: &cmkv2.CmkV2ClusterSpecConfigOneOf{CmkV2Basic: &cmkv2.CmkV2Basic{Kind: "Basic"}}, + Availability: cmkv2.PtrString("MULTI_ZONE"), + DeletionProtection: cmkv2.PtrBool(true), }, Status: &cmkv2.CmkV2ClusterStatus{Phase: "PROVISIONING"}, } clusterDedicated := getCmkDedicatedDescribeCluster("lkc-789", "ghi", 1) clusterDedicated.Spec.Network = &cmkv2.EnvScopedObjectReference{Id: "n-abcde1"} - clusterList := &cmkv2.CmkV2ClusterList{Data: []cmkv2.CmkV2Cluster{cluster, clusterMultizone, *clusterDedicated}} + clusterDedicated.Spec.DeletionProtection = cmkv2.PtrBool(false) + + allClusters := []cmkv2.CmkV2Cluster{cluster, clusterMultizone, *clusterDedicated} + + // Filter by spec.deletion_protection if specified + if dpFilter := r.URL.Query().Get("spec.deletion_protection"); dpFilter != "" { + var filtered []cmkv2.CmkV2Cluster + for _, c := range allClusters { + if dpFilter == "true" && c.Spec.GetDeletionProtection() { + filtered = append(filtered, c) + } else if dpFilter == "false" && !c.Spec.GetDeletionProtection() { + filtered = append(filtered, c) + } + } + allClusters = filtered + } + + clusterList := &cmkv2.CmkV2ClusterList{Data: allClusters} setPageToken(clusterList, &clusterList.Metadata, r.URL) err := json.NewEncoder(w).Encode(clusterList) require.NoError(t, err) @@ -163,6 +199,8 @@ func handleCmkCluster(t *testing.T) http.HandlerFunc { handleCmkKafkaClusterDescribeDedicatedProvisioning(t)(w, r) case "lkc-describe-dedicated-with-encryption": handleCmkKafkaClusterDescribeDedicatedWithEncryption(t)(w, r) + case "lkc-describe-deletion-protected": + handleCmkKafkaClusterDescribeDeletionProtected(t)(w, r) case "lkc-describe-infinite": handleCmkKafkaClusterDescribeInfinite(t)(w, r) case "lkc-update", "lkc-with-ecku-limits": @@ -179,6 +217,8 @@ func handleCmkCluster(t *testing.T) http.HandlerFunc { handleCmkKafkaDedicatedClusterShrink(t)(w, r) case "lkc-update-dedicated-shrink-multi": handleCmkKafkaDedicatedClusterShrinkMulti(t)(w, r) + case "lkc-deletion-protected": + handleCmkKafkaDeletionProtectedCluster(t)(w, r) case "lkc-unknown": handleCmkKafkaUnknown(t)(w, r) case "lkc-unknown-type": @@ -249,6 +289,39 @@ func handleCmkKafkaClusterDescribeDedicatedWithEncryption(t *testing.T) http.Han } } +// Handler for GET "/cmk/v2/clusters/lkc-describe-deletion-protected" +func handleCmkKafkaClusterDescribeDeletionProtected(t *testing.T) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + id := vars["id"] + cluster := getCmkBasicDescribeCluster(id, "kafka-cluster") + cluster.Spec.SetDeletionProtection(true) + err := json.NewEncoder(w).Encode(cluster) + require.NoError(t, err) + } +} + +// Handler for GET/DELETE "/cmk/v2/clusters/lkc-deletion-protected" +func handleCmkKafkaDeletionProtectedCluster(t *testing.T) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodDelete { + w.WriteHeader(http.StatusConflict) + body := map[string]any{ + "errors": []map[string]string{ + { + "code": "deletion_protection_enabled", + "detail": "Cluster deletion is blocked by deletion protection.", + }, + }, + } + err := json.NewEncoder(w).Encode(body) + require.NoError(t, err) + return + } + handleCmkKafkaClusterDescribeDeletionProtected(t)(w, r) + } +} + // Handler for GET "/cmk/v2/clusters/lkc-describe-infinite func handleCmkKafkaClusterDescribeInfinite(t *testing.T) http.HandlerFunc { return handleCmkKafkaClusterDescribeDedicated(t) // dedicated cluster has infinite storage @@ -325,9 +398,19 @@ func handleCmkKafkaClusterUpdateRequest(t *testing.T) http.HandlerFunc { return } + // Reject deletion protection on Basic clusters + if req.Spec.GetDeletionProtection() { + err = writeError(w, "Deletion protection is not supported for BASIC clusters.") + require.NoError(t, err) + return + } + // Handle other update cases if req.Spec.Config == nil || req.Spec.Config.CmkV2Dedicated.Cku == 0 { cluster := getCmkBasicDescribeCluster(req.GetId(), req.Spec.GetDisplayName()) + if req.Spec.DeletionProtection != nil { + cluster.Spec.SetDeletionProtection(req.Spec.GetDeletionProtection()) + } err := json.NewEncoder(w).Encode(cluster) require.NoError(t, err) } @@ -406,6 +489,15 @@ func handleCmkKafkaEnterpriseClusterUpdateRequest(t *testing.T) http.HandlerFunc require.NoError(t, err) return } + + // Handle deletion protection update + if req.Spec.DeletionProtection != nil { + cluster := getCmkEnterpriseDescribeCluster(req.GetId(), req.Spec.GetDisplayName()) + cluster.Spec.SetDeletionProtection(req.Spec.GetDeletionProtection()) + err = json.NewEncoder(w).Encode(cluster) + require.NoError(t, err) + return + } } } }