KSQL-14849: add 'confluent ksql cluster update --csu N' command#3368
KSQL-14849: add 'confluent ksql cluster update --csu N' command#3368Vedarth Sharma (VedarthConfluent) wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new confluent ksql cluster update <id> --csu <N> command intended to trigger self-serve ksqlDB cluster resizes via a forthcoming PATCH /ksqldbcm/v2/clusters/{id} control-plane endpoint.
Changes:
- Adds a new
ksql cluster updatecobra subcommand with--csuvalidation, pre-check via Describe, and a rolling-restart notice. - Wires the new
updatesubcommand into the existingksql clustercommand group (cloud-login branch). - Introduces a
Client.UpdateKsqlClustershim inpkg/ccloudv2(currently returns a placeholder error until the SDK supports the endpoint), plus unit tests for CSU validation helpers.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
pkg/ccloudv2/ksql.go |
Adds UpdateKsqlCluster shim for future PATCH support (currently returns placeholder error). |
internal/ksql/command_cluster.go |
Registers the new update subcommand under ksql cluster for cloud-login. |
internal/ksql/command_cluster_update.go |
Implements the ksql cluster update command, CSU validation, pre-check logic, and user messaging. |
internal/ksql/command_cluster_update_test.go |
Adds tests for CSU validation and CSU list formatting helpers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| cmd.AddCommand(c.newDeleteCommand()) | ||
| cmd.AddCommand(c.newDescribeCommand()) | ||
| cmd.AddCommand(c.newListCommand()) | ||
| cmd.AddCommand(c.newUpdateCommand()) |
There was a problem hiding this comment.
Done in 9b9eee25: added Hidden: true on the cobra command. The subcommand is still reachable for testing and review, but won't appear in ksql cluster --help or in customer-facing discovery. Drop Hidden when the SDK is regenerated and the shim is replaced with the real PATCH call.
| output.ErrPrintf(c.Config.EnableColor, | ||
| "Resizing ksqlDB cluster %q from %d to %d CSUs. A rolling restart will be "+ | ||
| "performed asynchronously; the cluster will continue serving queries during the resize.\n", | ||
| clusterId, currentCsu, csu) | ||
|
|
||
| cluster, err := c.V2Client.UpdateKsqlCluster(clusterId, environmentId, csu) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
There was a problem hiding this comment.
Done in 9b9eee25: moved the rolling-restart output.ErrPrintf to AFTER UpdateKsqlCluster returns nil. On failure (including the current shim that always fails) the notice is no longer printed.
| func buildUpdateLongDescription() string { | ||
| return fmt.Sprintf( | ||
| `Update an existing ksqlDB cluster. Currently only the CSU count may be | ||
| modified, and only to larger sizes (shrink is not supported). | ||
|
|
||
| Valid CSU values are %s. Larger sizes require a support ticket. | ||
| The cluster will undergo a rolling restart to apply the new size; the | ||
| command returns once the resize has been accepted by the control plane.`, | ||
| formatCsuList(validCsuSizes)) |
There was a problem hiding this comment.
Done in 9b9eee25: replaced the raw multi-line string with concatenated string literals and an explicit \n\n paragraph break. No more leading whitespace on continuation lines.
| func validateCsuForUpdate(csu int32) error { | ||
| if csu > 28 { | ||
| return fmt.Errorf("%d CSUs: %s", csu, csuSupportTicketMessage) | ||
| } |
There was a problem hiding this comment.
Done in 9b9eee25: added maxSelfServeCSU derived once from validCsuSizes (max over the slice). Both validateCsuForUpdate and csuSupportTicketMessage reference it, so extending validCsuSizes later moves the threshold automatically.
| "ksqlDB cluster update is not yet available in this CLI build; " + | ||
| "this command is pending a ccloud-sdk-go-v2/ksql regeneration " + | ||
| "after cc-api PR #2507 (KSQL-14844) merges. Track KSQL-14849 for status.") |
There was a problem hiding this comment.
Done in 9b9eee25: error is now "ksqlDB cluster update is not yet available in this CLI build. Please upgrade to a newer version of the Confluent CLI and retry." The internal cc-api / KSQL-* references stay in the doc comment on Client.UpdateKsqlCluster for engineers.
|
🎉 All Contributor License Agreements have been signed. Ready to merge. |
6658a3a to
0ff2c6b
Compare
…ommand CI failure on #3368 was two integration-test golden-file mismatches: - test/fixtures/output/ksql/cluster/help.golden was missing the new 'update' line under Available Commands. - test/fixtures/output/ksql/cluster/update-help.golden didn't exist; the new subcommand needs its own --help fixture. help-onprem.golden is unchanged: the update subcommand is registered only on the cloud-login branch in internal/ksql/command_cluster.go, so on-prem builds don't include it.
|
1. Hide subcommand while SDK call is shimmed (Copilot:command_cluster.go:24). The 'update' subcommand was wired into the cloud command tree but Client.UpdateKsqlCluster always returned an error, so a released build would expose a permanently failing command to customers. Add Hidden: true on the cobra.Command — the command stays reachable for testing and review, but doesn't appear in 'ksql cluster --help' or discovery. Drop Hidden when the SDK is regenerated. 2. Move rolling-restart notice to AFTER successful PATCH (Copilot:command_cluster_update.go:110). Printing 'Resizing…' before the call was misleading on failure (and is always wrong with the current shim that always fails). Now printed only once UpdateKsqlCluster returns nil error. 3. Fix long-description indentation (Copilot:command_cluster_update.go:63). The raw multi-line string had leading whitespace on wrapped lines that would render with extra leading spaces in --help. Use a concatenated string literal with explicit \n\n paragraph break and no embedded indentation. 4. Derive support-ticket threshold from validCsuSizes (Copilot:command_cluster_update.go:123). The hard-coded '28' in validateCsuForUpdate duplicated knowledge already in the validCsuSizes slice. Added maxSelfServeCSU computed once from the slice; validateCsuForUpdate and csuSupportTicketMessage both use it. If validCsuSizes is extended later, the threshold moves with it. 5. Customer-safe error message in SDK shim (Copilot:ksql.go:101). The shim error referenced cc-api PR #2507 and KSQL-* Jira IDs, which are internal tracking artifacts. Replaced with a generic 'this command is not yet available in this CLI build; please upgrade and retry' message. Internal context stays in the doc comment on UpdateKsqlCluster where reviewers and future maintainers can find it. Golden-file impact: - help.golden: 'update' no longer listed under Available Commands (because Hidden=true). - update-help.golden: deleted; testHelp removes fixtures for !cmd.IsAvailableCommand(), and Hidden makes update unavailable in the parent's listing (own --help still works at runtime).
Adds the `confluent ksql cluster update <id> --csu <N>` command for
self-serve CSU alteration of ksqlDB clusters. The command targets the
new public-API PATCH /ksqldbcm/v2/clusters/{id} endpoint being added by
cc-control-plane-ksql PR #313 (KSQL-14845) and gated server-side by the
ksql.self_serve_csu_alteration.enable LD flag.
Behavior:
- Validates --csu client-side against {4, 8, 12, 16, 20, 24, 28}. The
server's validCSUSizes map remains authoritative; the client check
exists to fail fast with a clearer error.
- CSU > 28 returns a customer-safe support-ticket message rather than
the generic "not a valid CSU size" error.
- Pre-checks the current CSU via DescribeKsqlCluster: a no-op resize
(same CSU) is rejected client-side with "already at N CSUs; no
change requested" instead of relying on the server's 400 no-op. A
shrink is also rejected client-side, mirroring the server contract.
- Prints a clear "rolling restart will be performed asynchronously,
cluster keeps serving queries" notice before the PATCH.
Files:
- internal/ksql/command_cluster_update.go: cobra command + validation
- internal/ksql/command_cluster_update_test.go: validation unit tests
- internal/ksql/command_cluster.go: wires new subcommand under cluster
- pkg/ccloudv2/ksql.go: UpdateKsqlCluster shim
SDK dependency (the actual wire call is gated):
The ccloud-sdk-go-v2/ksql/v2 SDK at v0.2.0 does not yet expose
ClustersKsqldbcmV2Api.UpdateKsqldbcmV2Cluster — that method will be
generated once cc-api PR #2507 (KSQL-14844) merges and the SDK is
regenerated. Until then, UpdateKsqlCluster returns a clear,
customer-safe error explaining the feature is pending. The unblock
procedure (one-line SDK call, doc comment in the file) is documented
inline. All other command logic (flag parsing, validation, pre-check,
no-op detection, output formatting) is fully wired and unit-tested today.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ommand CI failure on #3368 was two integration-test golden-file mismatches: - test/fixtures/output/ksql/cluster/help.golden was missing the new 'update' line under Available Commands. - test/fixtures/output/ksql/cluster/update-help.golden didn't exist; the new subcommand needs its own --help fixture. help-onprem.golden is unchanged: the update subcommand is registered only on the cloud-login branch in internal/ksql/command_cluster.go, so on-prem builds don't include it.
1. Hide subcommand while SDK call is shimmed (Copilot:command_cluster.go:24). The 'update' subcommand was wired into the cloud command tree but Client.UpdateKsqlCluster always returned an error, so a released build would expose a permanently failing command to customers. Add Hidden: true on the cobra.Command — the command stays reachable for testing and review, but doesn't appear in 'ksql cluster --help' or discovery. Drop Hidden when the SDK is regenerated. 2. Move rolling-restart notice to AFTER successful PATCH (Copilot:command_cluster_update.go:110). Printing 'Resizing…' before the call was misleading on failure (and is always wrong with the current shim that always fails). Now printed only once UpdateKsqlCluster returns nil error. 3. Fix long-description indentation (Copilot:command_cluster_update.go:63). The raw multi-line string had leading whitespace on wrapped lines that would render with extra leading spaces in --help. Use a concatenated string literal with explicit \n\n paragraph break and no embedded indentation. 4. Derive support-ticket threshold from validCsuSizes (Copilot:command_cluster_update.go:123). The hard-coded '28' in validateCsuForUpdate duplicated knowledge already in the validCsuSizes slice. Added maxSelfServeCSU computed once from the slice; validateCsuForUpdate and csuSupportTicketMessage both use it. If validCsuSizes is extended later, the threshold moves with it. 5. Customer-safe error message in SDK shim (Copilot:ksql.go:101). The shim error referenced cc-api PR #2507 and KSQL-* Jira IDs, which are internal tracking artifacts. Replaced with a generic 'this command is not yet available in this CLI build; please upgrade and retry' message. Internal context stays in the doc comment on UpdateKsqlCluster where reviewers and future maintainers can find it. Golden-file impact: - help.golden: 'update' no longer listed under Available Commands (because Hidden=true). - update-help.golden: deleted; testHelp removes fixtures for !cmd.IsAvailableCommand(), and Hidden makes update unavailable in the parent's listing (own --help still works at runtime).
…Update For non-prod end-to-end validation of the self-serve CSU PATCH endpoint. See the doc comment on Client.UpdateKsqlCluster for the temporary-nature context and the unswap procedure that runs before merging this PR. Three categories of changes: 1. Import path swap (6 files): github.com/confluentinc/ccloud-sdk-go-v2/ksql/v2 → github.com/confluentinc/ccloud-sdk-go-v2-internal/ksql/v2 go.mod bumped to ccloud-sdk-go-v2-internal/ksql v0.5.0 (the tag cut today from ccloud-sdk-go-v2-internal #820, generated from cc-api PR #2507's branch). The public ccloud-sdk-go-v2/ksql line is replaced, not added alongside — keeping a single SDK dep avoids type-collision in shared paths like Client. 2. ObjectReference type renames. The internal SDK's generator emits more granular reference types per field (cc-api spec captures the distinction); the public v0.2.0 SDK used a single ObjectReference for everything. Three mechanical swaps in pkg/ccloudv2/ksql.go and test/test-server/ksql_handlers.go: - Spec.KafkaCluster: ObjectReference → EnvScopedObjectReference - Spec.CredentialIdentity: ObjectReference → TypedGlobalObjectReference - Spec.Environment: ObjectReference → GlobalObjectReference plus NewObjectReference("sa-...", "", "") → NewTypedGlobalObjectReference(...). 3. Real PATCH call. Client.UpdateKsqlCluster now constructs KsqldbcmV2ClusterUpdate{Spec: {Environment, Csu}} and calls ClustersKsqldbcmV2Api.UpdateKsqldbcmV2Cluster(...).Execute() — no SDK Environment(...) query-param builder on PATCH, env lives in spec.environment.id in the body (matches cc-control-plane-ksql codec change in PR #335 / v0.224.0 — the server reads env from spec.environment.id with a query-param fallback for back-compat). Build, vet, and ksql unit tests all clean. Before merging this PR (post cc-api #2507 merge + public SDK release): - Swap import path back: internal/ksql → public ksql - Bump go.mod to the new public ccloud-sdk-go-v2/ksql tag (which will have the same Environment/typed-reference shape because it's generated from the same minispec) - Drop Hidden: true on the cobra command in command_cluster_update.go - Un-draft and final review
4bb1ca8 to
88d7aa6
Compare
cc-control-plane-ksql PR #340 (KSQL-15168) wires the shrink-direction PATCH server-side. This CLI change unblocks the customer surface so users can actually issue shrink requests. Changes: - Drop the client-side shrink reject (was: refuse target < current with "shrinking is not supported"). Direction is no longer something the CLI knows or cares about; the server's preflight is authoritative — it runs a Metrics-API-backed PQ-count check against the new CSU's PQ limit and refuses with a 400 + actionable message if the cluster is over-subscribed. Letting the server arbitrate avoids drift between CLI and control-plane policy. - Update buildUpdateLongDescription: drop the "only to larger sizes (shrink is not supported)" language. Mention both directions and explain the shrink precondition + how to fix it ("TERMINATE <query_id> and retry") so customers know what to do if a shrink is refused. - Add a "Shrink ksqlDB cluster lksqlc-12345 to 4 CSUs" example next to the expand one — both directions visible in the help. - Hidden: true stays. The SDK shim in pkg/ccloudv2/ksql.go is still in place; once the internal SDK is regenerated against the merged cc-api PATCH op, the shim goes away and we can drop Hidden in a separate commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


Summary
Adds the `confluent ksql cluster update --csu ` command for self-serve CSU alteration of ksqlDB clusters. Targets the new PATCH `/ksqldbcm/v2/clusters/{id}` endpoint being added in cc-control-plane-ksql PR #313 (KSQL-14845) and gated server-side by the `ksql.self_serve_csu_alteration.enable` LD flag.
What's in the change
Validation behavior
Rolling restart behavior
On a real resize the PATCH returns 202 Accepted immediately; the control plane then performs a rolling restart of the StatefulSet asynchronously (via `expandKsqlCluster` → `syncSpecToPhysicalCluster`). The CLI surfaces this with a pre-flight notice:
```
Resizing ksqlDB cluster "lksqlc-12345" from 4 to 8 CSUs. A rolling restart will be performed
asynchronously; the cluster will continue serving queries during the resize.
```
SDK dependency — actual wire call is gated
The public
ccloud-sdk-go-v2/ksql/v2SDK atv0.2.0(current dep ingo.mod) does not yet exposeClustersKsqldbcmV2Api.UpdateKsqldbcmV2Cluster. That method is generated from the cc-api OpenAPI spec, which is being updated by cc-api PR #2507 (KSQL-14844). The merge of cc-api #2507 is NOT a blocker for review or for non-prod validation — per @sgagniere's direction:Unblock path
For non-prod testing (does NOT require cc-api #2507 to merge):
confluentinc/ccloud-sdk-go-v2-internal/ksql(separate repo from the public SDK; latest tag today isksql/v0.3.0— the regen will cut e.g.ksql/v0.4.0).github.com/confluentinc/ccloud-sdk-go-v2/ksql/v2) for the internal one (github.com/confluentinc/ccloud-sdk-go-v2-internal/ksql/v2at the new tag) inpkg/ccloudv2/ksql.go+go.mod, and replaces the shim body ofClient.UpdateKsqlClusterwith the realUpdateKsqldbcmV2Clustercall. The SDK type/method signatures are identical between public and internal (both generated from the same minispec), so it's just an import-path change.maindoesn't ship a dependency on the internal SDK repo.For final merge (requires cc-api #2507 to ship):
ccloud-sdk-go-v2/ksqlregenerates and a new tag is cut.ccloud-sdk-go-v2/ksqlingo.modto that tag and re-swap the shim for the real call (one-line change inpkg/ccloudv2/ksql.go, documented inline in the shim's doc comment).Hidden: trueon the cobra command, un-draft, final review, merge.Today, in this PR
Client.UpdateKsqlClusterreturns a clear, customer-safe error ("ksqlDB cluster update is not yet available in this CLI build. Please upgrade to a newer version of the Confluent CLI and retry.").Hidden: true) so customers don't discover a permanently-failing command in any released build.DescribeKsqlCluster, rolling-restart notice after the call, table output) is wired and unit-tested.Test plan
ccloud-sdk-go-v2/ksqlrelease ships withUpdateKsqldbcmV2Cluster, and cc-control-plane-ksql ships with the LD flag enabled — does not require cc-api chore: update repo by service bot #2507 to merge)Why draft
Cannot meaningfully run end-to-end against any environment until the SDK is regenerated. Marking ready for review once `ccloud-sdk-go-v2/ksql` ships a release with `UpdateKsqldbcmV2Cluster`.
🤖 Generated with Claude Code