From 5003178782f2634cb57efc6a0d87bd7760f7a515 Mon Sep 17 00:00:00 2001 From: Amelia Dong Date: Mon, 25 May 2026 14:18:25 -0700 Subject: [PATCH 1/2] Add CLI support for SCIM token management --- .cli-generation-checksum | 2 +- cmd/lint/main.go | 1 + go.mod | 4 +- go.sum | 2 - internal/command.go | 2 +- internal/organization/command.go | 5 +- internal/organization/command_scim_token.go | 90 +++++++++++++++++++ .../organization/command_scim_token_create.go | 50 +++++++++++ .../organization/command_scim_token_delete.go | 46 ++++++++++ .../organization/command_scim_token_list.go | 51 +++++++++++ pkg/ccloudv2/org.go | 47 ++++++++++ .../org/scim_token/create_scim_token.json | 16 ++++ .../scim_token/read_created_scim_token.json | 16 ++++ test/fixtures/output/help-onprem.golden | 1 + test/fixtures/output/help.golden | 1 + .../create-expire-duration-mins.golden | 8 ++ .../output/org/scim-token/create.golden | 8 ++ .../org/scim-token/delete-invalid.golden | 2 + .../org/scim-token/delete-multiple.golden | 2 + .../org/scim-token/delete-no-force.golden | 2 + .../output/org/scim-token/delete.golden | 2 + .../output/org/scim-token/list-json.golden | 10 +++ .../output/org/scim-token/list-yaml.golden | 6 ++ .../output/org/scim-token/list.golden | 4 + .../output/organization/describe-help.golden | 1 + test/fixtures/output/organization/help.golden | 2 + .../output/organization/list-help.golden | 1 + .../scim-token/create-help.golden | 15 ++++ .../scim-token/delete-help.golden | 14 +++ .../organization/scim-token/help.golden | 20 +++++ .../organization/scim-token/list-help.golden | 14 +++ .../output/organization/update-help.golden | 1 + test/live/scim_token_live_test.go | 49 ++++++++++ test/scim_token_test.go | 53 +++++++++++ test/test-server/ccloudv2_router.go | 2 + test/test-server/scim_token_handler.go | 66 ++++++++++++++ 36 files changed, 610 insertions(+), 6 deletions(-) create mode 100644 internal/organization/command_scim_token.go create mode 100644 internal/organization/command_scim_token_create.go create mode 100644 internal/organization/command_scim_token_delete.go create mode 100644 internal/organization/command_scim_token_list.go create mode 100644 test/fixtures/input/org/scim_token/create_scim_token.json create mode 100644 test/fixtures/input/org/scim_token/read_created_scim_token.json create mode 100644 test/fixtures/output/org/scim-token/create-expire-duration-mins.golden create mode 100644 test/fixtures/output/org/scim-token/create.golden create mode 100644 test/fixtures/output/org/scim-token/delete-invalid.golden create mode 100644 test/fixtures/output/org/scim-token/delete-multiple.golden create mode 100644 test/fixtures/output/org/scim-token/delete-no-force.golden create mode 100644 test/fixtures/output/org/scim-token/delete.golden create mode 100644 test/fixtures/output/org/scim-token/list-json.golden create mode 100644 test/fixtures/output/org/scim-token/list-yaml.golden create mode 100644 test/fixtures/output/org/scim-token/list.golden create mode 100644 test/fixtures/output/organization/scim-token/create-help.golden create mode 100644 test/fixtures/output/organization/scim-token/delete-help.golden create mode 100644 test/fixtures/output/organization/scim-token/help.golden create mode 100644 test/fixtures/output/organization/scim-token/list-help.golden create mode 100644 test/live/scim_token_live_test.go create mode 100644 test/scim_token_test.go create mode 100644 test/test-server/scim_token_handler.go diff --git a/.cli-generation-checksum b/.cli-generation-checksum index 57f994b270..74aeaafce4 100644 --- a/.cli-generation-checksum +++ b/.cli-generation-checksum @@ -1 +1 @@ -4b4b331c9a9a8e2a28db070b9537b1b55c480d15a4a64543b296ed127f147123 +eec151074517277c2cbfcb933b73a1f36c0b4553f7ff30e93ea126d143554d22 diff --git a/cmd/lint/main.go b/cmd/lint/main.go index 5f9f21d5fc..1e03e20945 100644 --- a/cmd/lint/main.go +++ b/cmd/lint/main.go @@ -189,6 +189,7 @@ var properNouns = []string{ "ksqlDB Server", "ksqlDB", "Node.js", + "Organization", "Prometheus", "Python", "Real Time Context Engine", diff --git a/go.mod b/go.mod index 8dfd89ed11..88f173e120 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/confluentinc/ccloud-sdk-go-v2/networking-gateway v0.7.0 github.com/confluentinc/ccloud-sdk-go-v2/networking-ip v0.2.0 github.com/confluentinc/ccloud-sdk-go-v2/networking-privatelink v0.3.0 - github.com/confluentinc/ccloud-sdk-go-v2/org v0.10.0 + github.com/confluentinc/ccloud-sdk-go-v2/org v0.12.0 github.com/confluentinc/ccloud-sdk-go-v2/provider-integration v0.2.0 github.com/confluentinc/ccloud-sdk-go-v2/rtce v0.1.0 github.com/confluentinc/ccloud-sdk-go-v2/service-quota v0.2.0 @@ -296,3 +296,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +replace github.com/confluentinc/ccloud-sdk-go-v2/org => /Users/ameliadong/git/go/src/github.com/confluentinc/cli-terraform-generator/test-suites/specs/org diff --git a/go.sum b/go.sum index 77fce0d503..16beeb400e 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,6 @@ github.com/confluentinc/ccloud-sdk-go-v2/networking-ip v0.2.0 h1:ZHNF2DeqVlNPuKG github.com/confluentinc/ccloud-sdk-go-v2/networking-ip v0.2.0/go.mod h1:KTShFBZA7WG8LcxlWjJpoZFdWkJ+uOw3dDuwAHs5eKU= github.com/confluentinc/ccloud-sdk-go-v2/networking-privatelink v0.3.0 h1:mC0E1nKUt57AxMM4Lpdfd+KA/YZwJVwro9ER+dCUFi8= github.com/confluentinc/ccloud-sdk-go-v2/networking-privatelink v0.3.0/go.mod h1:GIHF2cYOUKx+6ycYokr4i8E4cuNBC22xqvO/IhqZ31U= -github.com/confluentinc/ccloud-sdk-go-v2/org v0.10.0 h1:UN/SU52OApJxMt/zkuxmTGjhAzy1nALcsZbnBP+jfaE= -github.com/confluentinc/ccloud-sdk-go-v2/org v0.10.0/go.mod h1:K5kVqnlOPD35riIm1VR89uulVwsKlmCbKDWxXSKTFVI= github.com/confluentinc/ccloud-sdk-go-v2/provider-integration v0.2.0 h1:UN2a+aqYhk95ro+wVLkeB/8W7n+UV2KsE3jNFbbDCSw= github.com/confluentinc/ccloud-sdk-go-v2/provider-integration v0.2.0/go.mod h1:TzompS9F0G6awN5xMC+nguNG8ULElN5UqX2XOBOIPuM= github.com/confluentinc/ccloud-sdk-go-v2/rtce v0.1.0 h1:OBa2vm09bOG1oojOP1vNj8V7+M2AfUkYP1sRQ+xlRm4= diff --git a/internal/command.go b/internal/command.go index d9b7f05690..c5fcad48d5 100644 --- a/internal/command.go +++ b/internal/command.go @@ -126,7 +126,7 @@ func NewConfluentCommand(cfg *config.Config) *cobra.Command { cmd.AddCommand(login.New(cfg, prerunner, ccloudClientFactory, mdsClientManager, loginCredentialsManager, loginOrganizationManager, authTokenHandler)) cmd.AddCommand(logout.New(cfg, prerunner, authTokenHandler)) cmd.AddCommand(network.New(cfg, prerunner)) - cmd.AddCommand(organization.New(prerunner)) + cmd.AddCommand(organization.New(cfg, prerunner)) cmd.AddCommand(plugin.New(cfg, prerunner)) cmd.AddCommand(prompt.New(cfg)) cmd.AddCommand(providerintegration.New(prerunner)) diff --git a/internal/organization/command.go b/internal/organization/command.go index 557a924eb7..b9d78aa706 100644 --- a/internal/organization/command.go +++ b/internal/organization/command.go @@ -4,13 +4,14 @@ import ( "github.com/spf13/cobra" pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/config" ) type command struct { *pcmd.AuthenticatedCLICommand } -func New(prerunner pcmd.PreRunner) *cobra.Command { +func New(cfg *config.Config, prerunner pcmd.PreRunner) *cobra.Command { cmd := &cobra.Command{ Use: "organization", Aliases: []string{"org"}, @@ -23,6 +24,8 @@ func New(prerunner pcmd.PreRunner) *cobra.Command { cmd.AddCommand(c.newDescribeCommand()) cmd.AddCommand(c.newListCommand()) cmd.AddCommand(c.newUpdateCommand()) + cmd.AddCommand(newScimTokenCommand(cfg, prerunner)) + // cli-tfgen:cli-subcommands return cmd } diff --git a/internal/organization/command_scim_token.go b/internal/organization/command_scim_token.go new file mode 100644 index 0000000000..4d12dd8326 --- /dev/null +++ b/internal/organization/command_scim_token.go @@ -0,0 +1,90 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package organization + +import ( + "time" + + "github.com/spf13/cobra" + + orgv2 "github.com/confluentinc/ccloud-sdk-go-v2/org/v2" + + pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/config" + "github.com/confluentinc/cli/v4/pkg/output" +) + +type scimTokenCommand struct { + *pcmd.AuthenticatedCLICommand +} + +type scimTokenOut struct { + ID string `human:"ID" serialized:"id"` + ConnectionName string `human:"Connection Name" serialized:"connection_name"` + Token string `human:"Token" serialized:"token"` + CreatedAt string `human:"Created At" serialized:"created_at"` + ExpiresAt string `human:"Expires At" serialized:"expires_at"` +} + +func newScimTokenCommand(cfg *config.Config, prerunner pcmd.PreRunner) *cobra.Command { //nolint:unparam + cmd := &cobra.Command{ + Use: "scim-token", + Aliases: []string{"st"}, + Short: "Manage organization scim tokens.", + Annotations: map[string]string{pcmd.RunRequirement: pcmd.RequireNonAPIKeyCloudLogin}, + } + + c := &scimTokenCommand{ + AuthenticatedCLICommand: pcmd.NewAuthenticatedCLICommand(cmd, prerunner), + } + + cmd.AddCommand( + c.newCreateCommand(), + c.newDeleteCommand(), + c.newListCommand(), + ) + + return cmd +} + +func printScimToken(cmd *cobra.Command, scimToken orgv2.OrgV2ScimToken) error { + table := output.NewTable(cmd) + out := &scimTokenOut{ + ID: scimToken.GetId(), + ConnectionName: scimToken.GetConnectionName(), + Token: scimToken.GetToken(), + CreatedAt: scimToken.GetCreatedAt().Format(time.RFC3339), + ExpiresAt: scimToken.GetExpiresAt().Format(time.RFC3339), + } + table.Add(out) + return table.Print() +} + +func (c *scimTokenCommand) validArgs(cmd *cobra.Command, args []string) []string { + if len(args) > 0 { + return nil + } + + return c.validArgsMultiple(cmd, args) +} + +func (c *scimTokenCommand) validArgsMultiple(cmd *cobra.Command, args []string) []string { + if err := c.PersistentPreRunE(cmd, args); err != nil { + return nil + } + + return c.autocompleteScimTokens() +} + +func (c *scimTokenCommand) autocompleteScimTokens() []string { + scimTokens, err := c.V2Client.ListOrganizationScimTokens() + if err != nil { + return nil + } + + suggestions := make([]string, len(scimTokens)) + for i, scimToken := range scimTokens { + suggestions[i] = scimToken.GetId() + } + return suggestions +} diff --git a/internal/organization/command_scim_token_create.go b/internal/organization/command_scim_token_create.go new file mode 100644 index 0000000000..6c5b67f52f --- /dev/null +++ b/internal/organization/command_scim_token_create.go @@ -0,0 +1,50 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package organization + +import ( + "github.com/spf13/cobra" + + orgv2 "github.com/confluentinc/ccloud-sdk-go-v2/org/v2" + + pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/errors" +) + +func (c *scimTokenCommand) newCreateCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Create an organization scim token.", + Args: cobra.NoArgs, + RunE: c.create, + } + + // Required flags + + // Optional flags + cmd.Flags().Int32("expire-duration-mins", 0, "The duration in minutes after which the token expires. Defaults to 6 months (259200 minutes) if not specified. Minimum: 1 month (43200 minutes). Maximum: 2 years (1051200 minutes).") + + pcmd.AddContextFlag(cmd, c.CLICommand) + pcmd.AddOutputFlag(cmd) + + return cmd +} + +func (c *scimTokenCommand) create(cmd *cobra.Command, args []string) error { + createReq := orgv2.InlineObject{} + + expireDurationMins, err := cmd.Flags().GetInt32("expire-duration-mins") + if err != nil { + return err + } + if expireDurationMins != 0 { + createReq.ExpireDurationMins = orgv2.PtrInt32(expireDurationMins) + } + + scimToken, httpResp, err := c.V2Client.CreateOrganizationScimToken(createReq) + if err != nil { + return errors.CatchCCloudV2Error(err, httpResp) + } + + return printScimToken(cmd, scimToken) +} diff --git a/internal/organization/command_scim_token_delete.go b/internal/organization/command_scim_token_delete.go new file mode 100644 index 0000000000..473701bf24 --- /dev/null +++ b/internal/organization/command_scim_token_delete.go @@ -0,0 +1,46 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package organization + +import ( + "github.com/spf13/cobra" + + pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/deletion" +) + +func (c *scimTokenCommand) newDeleteCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "delete [id-2] ... [id-n]", + Short: "Delete one or more organization scim tokens.", + Args: cobra.MinimumNArgs(1), + ValidArgsFunction: pcmd.NewValidArgsFunction(c.validArgsMultiple), + RunE: c.delete, + } + + // Required flags + + // Optional flags + + pcmd.AddContextFlag(cmd, c.CLICommand) + pcmd.AddForceFlag(cmd) + + return cmd +} + +func (c *scimTokenCommand) delete(cmd *cobra.Command, args []string) error { + existenceFunc := func(primaryId string) bool { + return true + } + + if err := deletion.ValidateAndConfirm(cmd, args, existenceFunc, "organization scim token"); err != nil { + return err + } + + deleteFunc := func(primaryId string) error { + return c.V2Client.DeleteOrganizationScimToken(primaryId) + } + + _, err := deletion.Delete(cmd, args, deleteFunc, "organization scim token") + return err +} diff --git a/internal/organization/command_scim_token_list.go b/internal/organization/command_scim_token_list.go new file mode 100644 index 0000000000..57bc277750 --- /dev/null +++ b/internal/organization/command_scim_token_list.go @@ -0,0 +1,51 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package organization + +import ( + "time" + + "github.com/spf13/cobra" + + pcmd "github.com/confluentinc/cli/v4/pkg/cmd" + "github.com/confluentinc/cli/v4/pkg/output" +) + +func (c *scimTokenCommand) newListCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List organization scim tokens.", + Args: cobra.NoArgs, + RunE: c.list, + } + + // Required flags + + // Optional flags + + pcmd.AddContextFlag(cmd, c.CLICommand) + pcmd.AddOutputFlag(cmd) + + return cmd +} + +func (c *scimTokenCommand) list(cmd *cobra.Command, _ []string) error { + + scimTokens, err := c.V2Client.ListOrganizationScimTokens() + if err != nil { + return err + } + + list := output.NewList(cmd) + for _, scimToken := range scimTokens { + out := &scimTokenOut{ + ID: scimToken.GetId(), + ConnectionName: scimToken.GetConnectionName(), + Token: scimToken.GetToken(), + CreatedAt: scimToken.GetCreatedAt().Format(time.RFC3339), + ExpiresAt: scimToken.GetExpiresAt().Format(time.RFC3339), + } + list.Add(out) + } + return list.Print() +} diff --git a/pkg/ccloudv2/org.go b/pkg/ccloudv2/org.go index 835c9d0568..bb8d516180 100644 --- a/pkg/ccloudv2/org.go +++ b/pkg/ccloudv2/org.go @@ -106,3 +106,50 @@ func (c *Client) executeListOrganizations(pageToken string) (orgv2.OrgV2Organiza } return req.Execute() } + +// ===== organization scim tokens API calls ===== + +func (c *Client) CreateOrganizationScimToken(req orgv2.InlineObject) (orgv2.OrgV2ScimToken, *http.Response, error) { + createReq := c.OrgClient.ScimTokensOrgV2Api. + CreateOrgV2ScimToken(c.orgApiContext()). + InlineObject(req) + return createReq.Execute() +} + +func (c *Client) DeleteOrganizationScimToken(id string) error { + deleteReq := c.OrgClient.ScimTokensOrgV2Api. + DeleteOrgV2ScimToken(c.orgApiContext(), id) + httpResp, err := deleteReq.Execute() + return errors.CatchCCloudV2Error(err, httpResp) +} + +func (c *Client) ListOrganizationScimTokens() ([]orgv2.OrgV2ScimToken, error) { + var list []orgv2.OrgV2ScimToken + + done := false + pageToken := "" + for !done { + page, httpResp, err := c.executeListScimTokens(pageToken) + if err != nil { + return nil, errors.CatchCCloudV2Error(err, httpResp) + } + list = append(list, page.GetData()...) + + pageToken, done, err = extractNextPageToken(page.GetMetadata().Next) + if err != nil { + return nil, err + } + } + + return list, nil +} + +func (c *Client) executeListScimTokens(pageToken string) (orgv2.OrgV2ScimTokenList, *http.Response, error) { + req := c.OrgClient.ScimTokensOrgV2Api. + ListOrgV2ScimTokens(c.orgApiContext()). + PageSize(ccloudV2ListPageSize) + if pageToken != "" { + req = req.PageToken(pageToken) + } + return req.Execute() +} diff --git a/test/fixtures/input/org/scim_token/create_scim_token.json b/test/fixtures/input/org/scim_token/create_scim_token.json new file mode 100644 index 0000000000..09ac05bfb8 --- /dev/null +++ b/test/fixtures/input/org/scim_token/create_scim_token.json @@ -0,0 +1,16 @@ +{ + "api_version": "org/v2", + "connection_name": "test-connection", + "created_at": "2026-04-16T10:00:00Z", + "expires_at": "2026-10-16T10:00:00Z", + "id": "dlz-f3a90de", + "kind": "ScimToken", + "metadata": { + "created_at": "2006-01-02T15:04:05-07:00", + "deleted_at": "2006-01-02T15:04:05-07:00", + "resource_name": "crn://confluent.cloud/organization=9bb441c4-edef-46ac-8a41-c49e44a3fd9a/scim-token=st-12345", + "self": "https://api.confluent.cloud/org/v2/scim-tokens/st-12345", + "updated_at": "2006-01-02T15:04:05-07:00" + }, + "token": "cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} diff --git a/test/fixtures/input/org/scim_token/read_created_scim_token.json b/test/fixtures/input/org/scim_token/read_created_scim_token.json new file mode 100644 index 0000000000..09ac05bfb8 --- /dev/null +++ b/test/fixtures/input/org/scim_token/read_created_scim_token.json @@ -0,0 +1,16 @@ +{ + "api_version": "org/v2", + "connection_name": "test-connection", + "created_at": "2026-04-16T10:00:00Z", + "expires_at": "2026-10-16T10:00:00Z", + "id": "dlz-f3a90de", + "kind": "ScimToken", + "metadata": { + "created_at": "2006-01-02T15:04:05-07:00", + "deleted_at": "2006-01-02T15:04:05-07:00", + "resource_name": "crn://confluent.cloud/organization=9bb441c4-edef-46ac-8a41-c49e44a3fd9a/scim-token=st-12345", + "self": "https://api.confluent.cloud/org/v2/scim-tokens/st-12345", + "updated_at": "2006-01-02T15:04:05-07:00" + }, + "token": "cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." +} diff --git a/test/fixtures/output/help-onprem.golden b/test/fixtures/output/help-onprem.golden index ec45c3d741..a91f84c849 100644 --- a/test/fixtures/output/help-onprem.golden +++ b/test/fixtures/output/help-onprem.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted Manage your Confluent Platform. Usage: diff --git a/test/fixtures/output/help.golden b/test/fixtures/output/help.golden index 1c620fd16b..b3ec956d43 100644 --- a/test/fixtures/output/help.golden +++ b/test/fixtures/output/help.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted Manage your Confluent Cloud. Usage: diff --git a/test/fixtures/output/org/scim-token/create-expire-duration-mins.golden b/test/fixtures/output/org/scim-token/create-expire-duration-mins.golden new file mode 100644 index 0000000000..84b2b7ab5c --- /dev/null +++ b/test/fixtures/output/org/scim-token/create-expire-duration-mins.golden @@ -0,0 +1,8 @@ +warning: GOCOVERDIR not set, no coverage data emitted ++-----------------+---------------------------------------------------+ +| ID | dlz-f3a90de | +| Connection Name | test-connection | +| Token | cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... | +| Created At | 2026-04-16T10:00:00Z | +| Expires At | 2026-10-16T10:00:00Z | ++-----------------+---------------------------------------------------+ diff --git a/test/fixtures/output/org/scim-token/create.golden b/test/fixtures/output/org/scim-token/create.golden new file mode 100644 index 0000000000..84b2b7ab5c --- /dev/null +++ b/test/fixtures/output/org/scim-token/create.golden @@ -0,0 +1,8 @@ +warning: GOCOVERDIR not set, no coverage data emitted ++-----------------+---------------------------------------------------+ +| ID | dlz-f3a90de | +| Connection Name | test-connection | +| Token | cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... | +| Created At | 2026-04-16T10:00:00Z | +| Expires At | 2026-10-16T10:00:00Z | ++-----------------+---------------------------------------------------+ diff --git a/test/fixtures/output/org/scim-token/delete-invalid.golden b/test/fixtures/output/org/scim-token/delete-invalid.golden new file mode 100644 index 0000000000..fe4d8c3a74 --- /dev/null +++ b/test/fixtures/output/org/scim-token/delete-invalid.golden @@ -0,0 +1,2 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Are you sure you want to delete organization scim token "invalid"? (y/n): Error: failed to read input diff --git a/test/fixtures/output/org/scim-token/delete-multiple.golden b/test/fixtures/output/org/scim-token/delete-multiple.golden new file mode 100644 index 0000000000..525b63f0db --- /dev/null +++ b/test/fixtures/output/org/scim-token/delete-multiple.golden @@ -0,0 +1,2 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Are you sure you want to delete organization scim tokens "id-1" and "id-2"? (y/n): Deleted organization scim tokens "id-1" and "id-2". diff --git a/test/fixtures/output/org/scim-token/delete-no-force.golden b/test/fixtures/output/org/scim-token/delete-no-force.golden new file mode 100644 index 0000000000..fe90ecb1e2 --- /dev/null +++ b/test/fixtures/output/org/scim-token/delete-no-force.golden @@ -0,0 +1,2 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Are you sure you want to delete organization scim token "id-1"? (y/n): Deleted organization scim token "id-1". diff --git a/test/fixtures/output/org/scim-token/delete.golden b/test/fixtures/output/org/scim-token/delete.golden new file mode 100644 index 0000000000..fb857f940b --- /dev/null +++ b/test/fixtures/output/org/scim-token/delete.golden @@ -0,0 +1,2 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Deleted organization scim token "id-1". diff --git a/test/fixtures/output/org/scim-token/list-json.golden b/test/fixtures/output/org/scim-token/list-json.golden new file mode 100644 index 0000000000..3ea051bfd5 --- /dev/null +++ b/test/fixtures/output/org/scim-token/list-json.golden @@ -0,0 +1,10 @@ +warning: GOCOVERDIR not set, no coverage data emitted +[ + { + "id": "dlz-f3a90de", + "connection_name": "test-connection", + "token": "cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "created_at": "2026-04-16T10:00:00Z", + "expires_at": "2026-10-16T10:00:00Z" + } +] diff --git a/test/fixtures/output/org/scim-token/list-yaml.golden b/test/fixtures/output/org/scim-token/list-yaml.golden new file mode 100644 index 0000000000..0a0a0a3e5a --- /dev/null +++ b/test/fixtures/output/org/scim-token/list-yaml.golden @@ -0,0 +1,6 @@ +warning: GOCOVERDIR not set, no coverage data emitted +- id: dlz-f3a90de + connection_name: test-connection + token: cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + created_at: "2026-04-16T10:00:00Z" + expires_at: "2026-10-16T10:00:00Z" diff --git a/test/fixtures/output/org/scim-token/list.golden b/test/fixtures/output/org/scim-token/list.golden new file mode 100644 index 0000000000..25fe361238 --- /dev/null +++ b/test/fixtures/output/org/scim-token/list.golden @@ -0,0 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted + ID | Connection Name | Token | Created At | Expires At +--------------+-----------------+---------------------------------------------------+----------------------+----------------------- + dlz-f3a90de | test-connection | cflt-scim_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... | 2026-04-16T10:00:00Z | 2026-10-16T10:00:00Z diff --git a/test/fixtures/output/organization/describe-help.golden b/test/fixtures/output/organization/describe-help.golden index ca17a3d721..783d20ae78 100644 --- a/test/fixtures/output/organization/describe-help.golden +++ b/test/fixtures/output/organization/describe-help.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted Describe the current Confluent Cloud organization. Usage: diff --git a/test/fixtures/output/organization/help.golden b/test/fixtures/output/organization/help.golden index f11f9c852d..a877d45880 100644 --- a/test/fixtures/output/organization/help.golden +++ b/test/fixtures/output/organization/help.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted Manage your Confluent Cloud organizations. Usage: @@ -9,6 +10,7 @@ Aliases: Available Commands: describe Describe the current Confluent Cloud organization. list List Confluent Cloud organizations. + scim-token Manage organization scim tokens. update Update the current Confluent Cloud organization. Global Flags: diff --git a/test/fixtures/output/organization/list-help.golden b/test/fixtures/output/organization/list-help.golden index 9bf301db75..1dec799534 100644 --- a/test/fixtures/output/organization/list-help.golden +++ b/test/fixtures/output/organization/list-help.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted List Confluent Cloud organizations. Usage: diff --git a/test/fixtures/output/organization/scim-token/create-help.golden b/test/fixtures/output/organization/scim-token/create-help.golden new file mode 100644 index 0000000000..8014bd0643 --- /dev/null +++ b/test/fixtures/output/organization/scim-token/create-help.golden @@ -0,0 +1,15 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Create an organization scim token. + +Usage: + confluent organization scim-token create [flags] + +Flags: + --expire-duration-mins int32 The duration in minutes after which the token expires. Defaults to 6 months (259200 minutes) if not specified. Minimum: 1 month (43200 minutes). Maximum: 2 years (1051200 minutes). + --context string CLI context name. + -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") + +Global Flags: + -h, --help Show help for this command. + --unsafe-trace Equivalent to -vvvv, but also log HTTP requests and responses which might contain plaintext secrets. + -v, --verbose count Increase verbosity (-v for warn, -vv for info, -vvv for debug, -vvvv for trace). diff --git a/test/fixtures/output/organization/scim-token/delete-help.golden b/test/fixtures/output/organization/scim-token/delete-help.golden new file mode 100644 index 0000000000..f4092857f3 --- /dev/null +++ b/test/fixtures/output/organization/scim-token/delete-help.golden @@ -0,0 +1,14 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Delete one or more organization scim tokens. + +Usage: + confluent organization scim-token delete [id-2] ... [id-n] [flags] + +Flags: + --context string CLI context name. + --force Skip the deletion confirmation prompt. + +Global Flags: + -h, --help Show help for this command. + --unsafe-trace Equivalent to -vvvv, but also log HTTP requests and responses which might contain plaintext secrets. + -v, --verbose count Increase verbosity (-v for warn, -vv for info, -vvv for debug, -vvvv for trace). diff --git a/test/fixtures/output/organization/scim-token/help.golden b/test/fixtures/output/organization/scim-token/help.golden new file mode 100644 index 0000000000..97eee817eb --- /dev/null +++ b/test/fixtures/output/organization/scim-token/help.golden @@ -0,0 +1,20 @@ +warning: GOCOVERDIR not set, no coverage data emitted +Manage organization scim tokens. + +Usage: + confluent organization scim-token [command] + +Aliases: + scim-token, st + +Available Commands: + create Create an organization scim token. + delete Delete one or more organization scim tokens. + list List organization scim tokens. + +Global Flags: + -h, --help Show help for this command. + --unsafe-trace Equivalent to -vvvv, but also log HTTP requests and responses which might contain plaintext secrets. + -v, --verbose count Increase verbosity (-v for warn, -vv for info, -vvv for debug, -vvvv for trace). + +Use "confluent organization scim-token [command] --help" for more information about a command. diff --git a/test/fixtures/output/organization/scim-token/list-help.golden b/test/fixtures/output/organization/scim-token/list-help.golden new file mode 100644 index 0000000000..6966665a4b --- /dev/null +++ b/test/fixtures/output/organization/scim-token/list-help.golden @@ -0,0 +1,14 @@ +warning: GOCOVERDIR not set, no coverage data emitted +List organization scim tokens. + +Usage: + confluent organization scim-token list [flags] + +Flags: + --context string CLI context name. + -o, --output string Specify the output format as "human", "json", or "yaml". (default "human") + +Global Flags: + -h, --help Show help for this command. + --unsafe-trace Equivalent to -vvvv, but also log HTTP requests and responses which might contain plaintext secrets. + -v, --verbose count Increase verbosity (-v for warn, -vv for info, -vvv for debug, -vvvv for trace). diff --git a/test/fixtures/output/organization/update-help.golden b/test/fixtures/output/organization/update-help.golden index 5d91b0aa6b..4c8d6a549d 100644 --- a/test/fixtures/output/organization/update-help.golden +++ b/test/fixtures/output/organization/update-help.golden @@ -1,3 +1,4 @@ +warning: GOCOVERDIR not set, no coverage data emitted Update the current Confluent Cloud organization. Usage: diff --git a/test/live/scim_token_live_test.go b/test/live/scim_token_live_test.go new file mode 100644 index 0000000000..4986b236f8 --- /dev/null +++ b/test/live/scim_token_live_test.go @@ -0,0 +1,49 @@ +//go:build live_test && (all || core) + +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package live + +import ( + "testing" +) + +func (s *CLILiveTestSuite) TestScimTokenCRUDLive() { + t := s.T() + t.Parallel() + state := s.setupTestContext(t) + + // Variables + + // Cleanup (LIFO) + s.registerCleanup(t, "org scim-token delete {{.scim_token_id}} --force", state) + + steps := []CLILiveTest{ + { + Name: "Create organization scim token", + Args: "org scim-token create -o json", + ExitCode: 0, + JSONFields: map[string]string{}, + JSONFieldsExist: []string{"id"}, + CaptureID: "scim_token_id", + }, + { + Name: "List organization scim tokens", + Args: "org scim-token list", + UseStateVars: true, + ExitCode: 0, + }, + { + Name: "Delete organization scim token", + Args: "org scim-token delete {{.scim_token_id}} --force", + UseStateVars: true, + ExitCode: 0, + }, + } + + for _, step := range steps { + t.Run(step.Name, func(t *testing.T) { + s.runLiveCommand(t, step, state) + }) + } +} diff --git a/test/scim_token_test.go b/test/scim_token_test.go new file mode 100644 index 0000000000..49a0562634 --- /dev/null +++ b/test/scim_token_test.go @@ -0,0 +1,53 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package test + +func (s *CLITestSuite) TestOrgScimTokenCreate() { + tests := []CLITest{ + {args: "org scim-token create", fixture: "org/scim-token/create.golden"}, + {args: "org scim-token create --expire-duration-mins 259200", fixture: "org/scim-token/create-expire-duration-mins.golden"}, + } + + for _, test := range tests { + test.login = "cloud" + s.runIntegrationTest(test) + } +} + +func (s *CLITestSuite) TestOrgScimTokenDelete() { + tests := []CLITest{ + {args: "org scim-token delete id-1 --force", fixture: "org/scim-token/delete.golden"}, + {args: "org scim-token delete id-1", input: "y\n", fixture: "org/scim-token/delete-no-force.golden"}, + {args: "org scim-token delete id-1 id-2", input: "y\n", fixture: "org/scim-token/delete-multiple.golden"}, + {args: "org scim-token delete invalid", fixture: "org/scim-token/delete-invalid.golden", exitCode: 1}, + } + + for _, test := range tests { + test.login = "cloud" + s.runIntegrationTest(test) + } +} + +func (s *CLITestSuite) TestOrgScimTokenList() { + tests := []CLITest{ + {args: "org scim-token list", fixture: "org/scim-token/list.golden"}, + {args: "org scim-token list -o json", fixture: "org/scim-token/list-json.golden"}, + {args: "org scim-token list -o yaml", fixture: "org/scim-token/list-yaml.golden"}, + } + + for _, test := range tests { + test.login = "cloud" + s.runIntegrationTest(test) + } +} + +func (s *CLITestSuite) TestOrgScimToken_Autocomplete() { + tests := []CLITest{ + {args: "__complete org scim-token delete \"\"", fixture: "org/scim-token/delete-autocomplete.golden"}, + } + + for _, test := range tests { + test.login = "cloud" + s.runIntegrationTest(test) + } +} diff --git a/test/test-server/ccloudv2_router.go b/test/test-server/ccloudv2_router.go index a5aa9ed980..d12ef209ea 100644 --- a/test/test-server/ccloudv2_router.go +++ b/test/test-server/ccloudv2_router.go @@ -116,6 +116,8 @@ var ccloudV2Routes = []route{ {"/org/v2/environments/{id}", handleOrgEnvironment}, {"/org/v2/organizations", handleOrgOrganizations}, {"/org/v2/organizations/{id}", handleOrgOrganization}, + {"/org/v2/scim-tokens", handleOrgV2ScimTokens}, + {"/org/v2/scim-tokens/{id}", handleOrgV2ScimTokensId}, {"/pim/v1/integrations", handleProviderIntegrations}, {"/pim/v1/integrations/{id}", handleProviderIntegration}, {"/pim/v2/integrations", handleProviderIntegrationsV2}, diff --git a/test/test-server/scim_token_handler.go b/test/test-server/scim_token_handler.go new file mode 100644 index 0000000000..8d6b76bb03 --- /dev/null +++ b/test/test-server/scim_token_handler.go @@ -0,0 +1,66 @@ +// Code generated by cli-terraform-generator; DO NOT EDIT. + +package testserver + +import ( + "encoding/json" + "net/http" + "os" + "path/filepath" + "testing" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/require" + + orgv2 "github.com/confluentinc/ccloud-sdk-go-v2/org/v2" +) + +// Handler for "/org/v2/scim-tokens" +func handleOrgV2ScimTokens(t *testing.T) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + scimToken := readOrgV2ScimTokenFile(t, "read_created_scim_token.json") + + scimTokenList := &orgv2.OrgV2ScimTokenList{ + Data: []orgv2.OrgV2ScimToken{scimToken}, + } + + err := json.NewEncoder(w).Encode(scimTokenList) + require.NoError(t, err) + case http.MethodPost: + scimToken := readOrgV2ScimTokenFile(t, "create_scim_token.json") + + err := json.NewEncoder(w).Encode(scimToken) + require.NoError(t, err) + } + } +} + +// Handler for "/org/v2/scim-tokens/{id}" +func handleOrgV2ScimTokensId(t *testing.T) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + id := mux.Vars(r)["id"] + switch r.Method { + case http.MethodDelete: + switch id { + case "invalid": + w.WriteHeader(http.StatusNotFound) + default: + w.WriteHeader(http.StatusNoContent) + } + } + } +} + +func readOrgV2ScimTokenFile(t *testing.T, filename string) orgv2.OrgV2ScimToken { + jsonPath := filepath.Join("test", "fixtures", "input", "org", "scim_token", filename) + jsonData, err := os.ReadFile(jsonPath) + require.NoError(t, err) + + scimToken := orgv2.OrgV2ScimToken{} + err = json.Unmarshal(jsonData, &scimToken) + require.NoError(t, err) + + return scimToken +} From 7968fcedf7ab4927bc3b5c900a32cab993f635c0 Mon Sep 17 00:00:00 2001 From: Amelia Dong Date: Tue, 26 May 2026 14:13:55 -0700 Subject: [PATCH 2/2] Replace with ccloud-sdk-go-v2-internal --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 88f173e120..f76d92099d 100644 --- a/go.mod +++ b/go.mod @@ -297,4 +297,4 @@ require ( sigs.k8s.io/yaml v1.3.0 // indirect ) -replace github.com/confluentinc/ccloud-sdk-go-v2/org => /Users/ameliadong/git/go/src/github.com/confluentinc/cli-terraform-generator/test-suites/specs/org +replace github.com/confluentinc/ccloud-sdk-go-v2/org => github.com/confluentinc/ccloud-sdk-go-v2-internal/org v0.2.0 diff --git a/go.sum b/go.sum index 16beeb400e..4690b473cc 100644 --- a/go.sum +++ b/go.sum @@ -190,6 +190,8 @@ github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/confluentinc/ccloud-sdk-go-v1-public v0.0.0-20250521223017-0e8f6f971b52 h1:19qEGhkbZa5fopKCe0VPIV+Sasby4Pv10z9ZaktwWso= github.com/confluentinc/ccloud-sdk-go-v1-public v0.0.0-20250521223017-0e8f6f971b52/go.mod h1:62EMf+5uFEt1BJ2q8WMrUoI9VUSxAbDnmZCGRt/MbA0= +github.com/confluentinc/ccloud-sdk-go-v2-internal/org v0.2.0 h1:M2CN2vnXsgsi+mxS9Mbq8NQdi/dfRE0ooYVFrZ81R3s= +github.com/confluentinc/ccloud-sdk-go-v2-internal/org v0.2.0/go.mod h1:G9+rxKPBSPWLEbeYBGLlvt4DzPjifsYBRkDog8sCcRk= github.com/confluentinc/ccloud-sdk-go-v2/ai v0.1.0 h1:zSF4OQUJXWH2JeAo9rsq13ibk+JFdzITGR8S7cFMpzw= github.com/confluentinc/ccloud-sdk-go-v2/ai v0.1.0/go.mod h1:DoxqzzF3JzvJr3fWkvCiOHFlE0GoYpozWxFZ1Ud9ntA= github.com/confluentinc/ccloud-sdk-go-v2/apikeys v0.4.0 h1:8fWyLwMuy8ec0MVF5Avd54UvbIxhDFhZzanHBVwgxdw=