From 22e0180e091687f04ca447224be0a47e91216c54 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Wed, 2 Apr 2025 18:45:12 -0700 Subject: [PATCH 1/2] fix: Gen cli for release refactor --- cmd/ctrlc/root/api/create/create.go | 4 + .../deploymentversion/deployment-version.go | 131 +++ .../deployment-version-channel.go | 69 ++ .../api/create/environment/environment.go | 6 + cmd/ctrlc/root/api/create/release/release.go | 2 +- cmd/ctrlc/root/api/delete/delete.go | 3 +- .../deployment-version-channel.go | 48 ++ .../deploymentversion/deployment-version.go | 112 +++ cmd/ctrlc/root/api/update/update.go | 2 + .../deploymentversion/deployment-version.go | 127 +++ cmd/ctrlc/root/api/upsert/release/release.go | 2 +- cmd/ctrlc/root/api/upsert/upsert.go | 2 + internal/api/client.gen.go | 751 +++++++++++++++++- test/backwards_compatibility_test.go | 256 ++++++ 14 files changed, 1504 insertions(+), 11 deletions(-) create mode 100644 cmd/ctrlc/root/api/create/deploymentversion/deployment-version.go create mode 100644 cmd/ctrlc/root/api/create/deploymentversionchannel/deployment-version-channel.go create mode 100644 cmd/ctrlc/root/api/delete/deploymentversionchannel/deployment-version-channel.go create mode 100644 cmd/ctrlc/root/api/update/deploymentversion/deployment-version.go create mode 100644 cmd/ctrlc/root/api/upsert/deploymentversion/deployment-version.go create mode 100644 test/backwards_compatibility_test.go diff --git a/cmd/ctrlc/root/api/create/create.go b/cmd/ctrlc/root/api/create/create.go index 60aee0b..8368680 100644 --- a/cmd/ctrlc/root/api/create/create.go +++ b/cmd/ctrlc/root/api/create/create.go @@ -1,6 +1,8 @@ package create import ( + "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/create/deploymentversion" + "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/create/deploymentversionchannel" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/create/environment" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/create/relationship" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/create/release" @@ -20,6 +22,8 @@ func NewCreateCmd() *cobra.Command { } cmd.AddCommand(releasechannel.NewCreateReleaseChannelCmd()) + cmd.AddCommand(deploymentversionchannel.NewCreateDeploymentVersionChannelCmd()) + cmd.AddCommand(deploymentversion.NewCreateDeploymentVersionCmd()) cmd.AddCommand(environment.NewCreateEnvironmentCmd()) cmd.AddCommand(relationship.NewRelationshipCmd()) cmd.AddCommand(release.NewCreateReleaseCmd()) diff --git a/cmd/ctrlc/root/api/create/deploymentversion/deployment-version.go b/cmd/ctrlc/root/api/create/deploymentversion/deployment-version.go new file mode 100644 index 0000000..03abfe0 --- /dev/null +++ b/cmd/ctrlc/root/api/create/deploymentversion/deployment-version.go @@ -0,0 +1,131 @@ +package deploymentversion + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/ctrlplanedev/cli/internal/api" + "github.com/ctrlplanedev/cli/internal/cliutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func safeConvertToDeploymentVersionStatus(status string) (*api.UpsertDeploymentVersionJSONBodyStatus, error) { + statusLower := strings.ToLower(status) + if statusLower == "ready" || statusLower == "" { + s := api.UpsertDeploymentVersionJSONBodyStatusReady + return &s, nil + } + if statusLower == "building" { + s := api.UpsertDeploymentVersionJSONBodyStatusBuilding + return &s, nil + } + if statusLower == "failed" { + s := api.UpsertDeploymentVersionJSONBodyStatusFailed + return &s, nil + } + return nil, fmt.Errorf("invalid deployment version status: %s", status) +} + +func NewCreateDeploymentVersionCmd() *cobra.Command { + var tag string + var deploymentID []string + var metadata map[string]string + var configArray map[string]string + var jobAgentConfigArray map[string]string + var links map[string]string + var createdAt string + var name string + var status string + var message string + + cmd := &cobra.Command{ + Use: "deployment-version [flags]", + Short: "Create a deployment version", + Long: `Create a deployment version with the specified tag and configuration.`, + Example: heredoc.Doc(` + # Create a deployment version + $ ctrlc create deployment-version --tag v1.0.0 --deployment 1234567890 + + # Create a deployment version using Go template syntax + $ ctrlc create deployment-version --tag v1.0.0 --deployment 1234567890 --template='{{.status.phase}}' + + # Create a deployment version for multiple deployments + $ ctrlc create deployment-version --tag v1.0.0 --deployment 1234567890 --deployment 0987654321 + `), + RunE: func(cmd *cobra.Command, args []string) error { + apiURL := viper.GetString("url") + apiKey := viper.GetString("api-key") + client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) + if err != nil { + return fmt.Errorf("failed to create API client: %w", err) + } + + var parsedTime *time.Time + if createdAt != "" { + t, err := time.Parse(time.RFC3339, createdAt) + if err != nil { + return fmt.Errorf("failed to parse created_at time: %w", err) + } + parsedTime = &t + } + + if len(links) > 0 { + linksJSON, err := json.Marshal(links) + if err != nil { + return fmt.Errorf("failed to marshal links: %w", err) + } + metadata["ctrlplane/links"] = string(linksJSON) + } + + stat, err := safeConvertToDeploymentVersionStatus(status) + if err != nil { + return fmt.Errorf("failed to convert deployment version status: %w", err) + } + + config := cliutil.ConvertConfigArrayToNestedMap(configArray) + jobAgentConfig := cliutil.ConvertConfigArrayToNestedMap(jobAgentConfigArray) + var response *http.Response + for _, id := range deploymentID { + resp, err := client.UpsertDeploymentVersion(cmd.Context(), api.UpsertDeploymentVersionJSONRequestBody{ + Tag: tag, + DeploymentId: id, + Metadata: cliutil.StringMapPtr(metadata), + CreatedAt: parsedTime, + Config: cliutil.MapPtr(config), + JobAgentConfig: cliutil.MapPtr(jobAgentConfig), + Name: cliutil.StringPtr(name), + Status: stat, + Message: cliutil.StringPtr(message), + }) + if err != nil { + return fmt.Errorf("failed to create deployment version: %w", err) + } + response = resp + } + + return cliutil.HandleResponseOutput(cmd, response) + }, + } + + // Add flags + cmd.Flags().StringVarP(&tag, "tag", "t", "", "Tag of the deployment version (required)") + cmd.Flags().StringArrayVarP(&deploymentID, "deployment", "d", []string{}, "IDs of the deployments (required, supports multiple)") + cmd.Flags().StringToStringVarP(&metadata, "metadata", "m", make(map[string]string), "Metadata key-value pairs (e.g. --metadata key=value)") + cmd.Flags().StringToStringVarP(&configArray, "config", "c", make(map[string]string), "Config key-value pairs with nested values (can be specified multiple times)") + cmd.Flags().StringToStringVarP(&jobAgentConfigArray, "job-agent-config", "j", make(map[string]string), "Job agent config key-value pairs (can be specified multiple times)") + cmd.Flags().StringToStringVarP(&links, "link", "l", make(map[string]string), "Links key-value pairs (can be specified multiple times)") + cmd.Flags().StringVarP(&createdAt, "created-at", "r", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the deployment version") + cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the deployment version") + cmd.Flags().StringVarP(&status, "status", "s", string(api.UpsertDeploymentVersionJSONBodyStatusReady), "Status of the deployment version (one of: ready, building, failed)") + cmd.Flags().StringVar(&message, "message", "", "Message of the deployment version") + + cmd.MarkFlagRequired("tag") + cmd.MarkFlagRequired("deployment") + + return cmd +} diff --git a/cmd/ctrlc/root/api/create/deploymentversionchannel/deployment-version-channel.go b/cmd/ctrlc/root/api/create/deploymentversionchannel/deployment-version-channel.go new file mode 100644 index 0000000..1ae5fca --- /dev/null +++ b/cmd/ctrlc/root/api/create/deploymentversionchannel/deployment-version-channel.go @@ -0,0 +1,69 @@ +package deploymentversionchannel + +import ( + "encoding/json" + "fmt" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/ctrlplanedev/cli/internal/api" + "github.com/ctrlplanedev/cli/internal/cliutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func NewCreateDeploymentVersionChannelCmd() *cobra.Command { + var name string + var deploymentID string + var description string + var selector string + + cmd := &cobra.Command{ + Use: "deployment-version-channel [flags]", + Short: "Create a new deployment version channel", + Long: `Create a new deployment version channel with the specified name and configuration.`, + Example: heredoc.Doc(` + # Create a new deployment version channel + $ ctrlc create deployment-version-channel --name my-version-channel --deployment 1234567890 + + # Create a new deployment version channel with selector + $ ctrlc create deployment-version-channel --name my-version-channel --deployment 1234567890 --selector '{"type":"tag","operator":"equals","value":"v1.0.0"}' + `), + RunE: func(cmd *cobra.Command, args []string) error { + apiURL := viper.GetString("url") + apiKey := viper.GetString("api-key") + client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) + if err != nil { + return fmt.Errorf("failed to create API client: %w", err) + } + + versionSelector := make(map[string]interface{}) + if selector != "" { + if err := json.Unmarshal([]byte(selector), &versionSelector); err != nil { + return fmt.Errorf("failed to parse version selector JSON: %w", err) + } + } + + resp, err := client.CreateDeploymentVersionChannel(cmd.Context(), api.CreateDeploymentVersionChannelJSONRequestBody{ + Name: name, + DeploymentId: deploymentID, + Description: &description, + VersionSelector: versionSelector, + }) + if err != nil { + return fmt.Errorf("failed to create deployment version channel: %w", err) + } + + return cliutil.HandleResponseOutput(cmd, resp) + }, + } + + // Add flags + cmd.Flags().StringVar(&name, "name", "", "Name of the deployment version channel (required)") + cmd.Flags().StringVar(&deploymentID, "deployment", "", "ID of the deployment (required)") + cmd.Flags().StringVar(&selector, "selector", "", "JSON string containing version selector criteria") + cmd.Flags().StringVar(&description, "description", "", "Description of the deployment version channel") + cmd.MarkFlagRequired("name") + cmd.MarkFlagRequired("deployment") + + return cmd +} diff --git a/cmd/ctrlc/root/api/create/environment/environment.go b/cmd/ctrlc/root/api/create/environment/environment.go index 1944e27..5fcc1fa 100644 --- a/cmd/ctrlc/root/api/create/environment/environment.go +++ b/cmd/ctrlc/root/api/create/environment/environment.go @@ -14,6 +14,7 @@ import ( func NewCreateEnvironmentCmd() *cobra.Command { var nameFlag string var releaseChannels []string + var deploymentVersionChannels []string var system string var resourceSelector string var metadata map[string]string @@ -25,6 +26,9 @@ func NewCreateEnvironmentCmd() *cobra.Command { # Create a new environment $ ctrlc create environment --name my-environment --system 00000000-0000-0000-0000-000000000000 + # Create a new environment with both release channels and deployment version channels + $ ctrlc create environment --name my-environment --system 00000000-0000-0000-0000-000000000000 --release-channel 00000000-0000-0000-0000-000000000001 --deployment-version-channel 00000000-0000-0000-0000-000000000002 + # Create a new environment using Go template syntax $ ctrlc create environment --name my-environment --system 00000000-0000-0000-0000-000000000000 --template='{{.id}}' `), @@ -39,6 +43,7 @@ func NewCreateEnvironmentCmd() *cobra.Command { body := api.CreateEnvironmentJSONRequestBody{} body.Name = nameFlag body.ReleaseChannels = &releaseChannels + body.DeploymentVersionChannels = &deploymentVersionChannels body.SystemId = system body.Metadata = cliutil.StringMapPtr(metadata) @@ -62,6 +67,7 @@ func NewCreateEnvironmentCmd() *cobra.Command { cmd.Flags().StringVarP(&nameFlag, "name", "n", "", "Name of the environment (required)") cmd.Flags().StringVarP(&system, "system", "s", "", "ID of the system (required)") cmd.Flags().StringSliceVarP(&releaseChannels, "release-channel", "r", []string{}, "Release channel in format ") + cmd.Flags().StringSliceVarP(&deploymentVersionChannels, "deployment-version-channel", "d", []string{}, "Deployment version channel in format ") cmd.Flags().StringVarP(&resourceSelector, "resource-selector", "f", "", "Resource selector as JSON string") cmd.Flags().StringToStringVarP(&metadata, "metadata", "m", make(map[string]string), "Metadata key-value pairs (e.g. --metadata key=value)") diff --git a/cmd/ctrlc/root/api/create/release/release.go b/cmd/ctrlc/root/api/create/release/release.go index 30f5069..c03efe5 100644 --- a/cmd/ctrlc/root/api/create/release/release.go +++ b/cmd/ctrlc/root/api/create/release/release.go @@ -119,7 +119,7 @@ func NewCreateReleaseCmd() *cobra.Command { cmd.Flags().StringToStringVarP(&configArray, "config", "c", make(map[string]string), "Config key-value pairs with nested values (can be specified multiple times)") cmd.Flags().StringToStringVarP(&jobAgentConfigArray, "job-agent-config", "j", make(map[string]string), "Job agent config key-value pairs (can be specified multiple times)") cmd.Flags().StringToStringVarP(&links, "link", "l", make(map[string]string), "Links key-value pairs (can be specified multiple times)") - cmd.Flags().StringVarP(&createdAt, "created-at", "t", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the release channel") + cmd.Flags().StringVarP(&createdAt, "created-at", "r", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the release channel") cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the release channel") cmd.Flags().StringVarP(&status, "status", "s", string(api.UpsertReleaseJSONBodyStatusReady), "Status of the release channel (one of: ready, building, failed)") cmd.Flags().StringVar(&message, "message", "", "Message of the release channel") diff --git a/cmd/ctrlc/root/api/delete/delete.go b/cmd/ctrlc/root/api/delete/delete.go index 5267671..64a477e 100644 --- a/cmd/ctrlc/root/api/delete/delete.go +++ b/cmd/ctrlc/root/api/delete/delete.go @@ -1,6 +1,7 @@ package delete import ( + "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/delete/deploymentversionchannel" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/delete/environment" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/delete/releasechannel" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/delete/resource" @@ -20,6 +21,6 @@ func NewDeleteCmd() *cobra.Command { cmd.AddCommand(resource.NewDeleteResourceCmd()) cmd.AddCommand(environment.NewDeleteEnvironmentCmd()) cmd.AddCommand(releasechannel.NewDeleteReleaseChannelCmd()) - + cmd.AddCommand(deploymentversionchannel.NewDeleteDeploymentVersionChannelCmd()) return cmd } diff --git a/cmd/ctrlc/root/api/delete/deploymentversionchannel/deployment-version-channel.go b/cmd/ctrlc/root/api/delete/deploymentversionchannel/deployment-version-channel.go new file mode 100644 index 0000000..12b317c --- /dev/null +++ b/cmd/ctrlc/root/api/delete/deploymentversionchannel/deployment-version-channel.go @@ -0,0 +1,48 @@ +package deploymentversionchannel + +import ( + "fmt" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/ctrlplanedev/cli/internal/api" + "github.com/ctrlplanedev/cli/internal/cliutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func NewDeleteDeploymentVersionChannelCmd() *cobra.Command { + var deploymentID string + var name string + + cmd := &cobra.Command{ + Use: "deployment-version-channel [flags]", + Short: "Delete a deployment version channel", + Long: `Delete a deployment version channel by specifying a deployment ID and a name.`, + Example: heredoc.Doc(` + $ ctrlc delete deployment-version-channel --deployment 123e4567-e89b-12d3-a456-426614174000 --name mychannel + `), + RunE: func(cmd *cobra.Command, args []string) error { + if deploymentID == "" || name == "" { + return fmt.Errorf("deployment and name are required") + } + + apiURL := viper.GetString("url") + apiKey := viper.GetString("api-key") + client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) + if err != nil { + return fmt.Errorf("failed to create API client: %w", err) + } + resp, err := client.DeleteDeploymentVersionChannel(cmd.Context(), deploymentID, name) + if err != nil { + return fmt.Errorf("failed to delete deployment version channel: %w", err) + } + + return cliutil.HandleResponseOutput(cmd, resp) + }, + } + + cmd.Flags().StringVar(&deploymentID, "deployment", "", "Deployment ID") + cmd.Flags().StringVar(&name, "name", "", "Deployment version channel name") + + return cmd +} diff --git a/cmd/ctrlc/root/api/update/deploymentversion/deployment-version.go b/cmd/ctrlc/root/api/update/deploymentversion/deployment-version.go new file mode 100644 index 0000000..9aa4010 --- /dev/null +++ b/cmd/ctrlc/root/api/update/deploymentversion/deployment-version.go @@ -0,0 +1,112 @@ +package deploymentversion + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/ctrlplanedev/cli/internal/api" + "github.com/ctrlplanedev/cli/internal/cliutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func safeConvertToDeploymentVersionStatus(stat string) (*api.UpdateDeploymentVersionJSONBodyStatus, error) { + if stat == "" { + return nil, nil + } + status := stat + statusLower := strings.ToLower(status) + if statusLower == "ready" || statusLower == "" { + s := api.UpdateDeploymentVersionJSONBodyStatusReady + return &s, nil + } + if statusLower == "building" { + s := api.UpdateDeploymentVersionJSONBodyStatusBuilding + return &s, nil + } + if statusLower == "failed" { + s := api.UpdateDeploymentVersionJSONBodyStatusFailed + return &s, nil + } + return nil, fmt.Errorf("invalid deployment version status: %s", status) +} + +func NewUpdateDeploymentVersionCmd() *cobra.Command { + var deploymentVersionID string + var tag string + var metadata map[string]string + var configArray map[string]string + var jobAgentConfigArray map[string]string + var links map[string]string + var name string + var status string + var message string + + cmd := &cobra.Command{ + Use: "deployment-version [flags]", + Short: "Update a deployment version", + Long: `Update a deployment version with the specified tag and configuration.`, + Example: heredoc.Doc(` + # Update a deployment version + $ ctrlc update deployment-version --deployment-version-id 1234567890 --tag v1.0.0 --status ready + `), + RunE: func(cmd *cobra.Command, args []string) error { + if deploymentVersionID == "" { + return fmt.Errorf("deployment version ID is required") + } + + apiURL := viper.GetString("url") + apiKey := viper.GetString("api-key") + client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) + if err != nil { + return fmt.Errorf("failed to create API client: %w", err) + } + + stat, err := safeConvertToDeploymentVersionStatus(status) + if err != nil { + return fmt.Errorf("failed to convert deployment version status: %w", err) + } + + if len(links) > 0 { + linksJSON, err := json.Marshal(links) + if err != nil { + return fmt.Errorf("failed to marshal links: %w", err) + } + metadata["ctrlplane/links"] = string(linksJSON) + } + + config := cliutil.ConvertConfigArrayToNestedMap(configArray) + jobAgentConfig := cliutil.ConvertConfigArrayToNestedMap(jobAgentConfigArray) + resp, err := client.UpdateDeploymentVersion(cmd.Context(), deploymentVersionID, api.UpdateDeploymentVersionJSONRequestBody{ + Tag: cliutil.StringPtr(tag), + Metadata: cliutil.StringMapPtr(metadata), + Config: cliutil.MapPtr(config), + JobAgentConfig: cliutil.MapPtr(jobAgentConfig), + Name: cliutil.StringPtr(name), + Status: stat, + Message: cliutil.StringPtr(message), + }) + if err != nil { + return fmt.Errorf("failed to update deployment version: %w", err) + } + + return cliutil.HandleResponseOutput(cmd, resp) + }, + } + + cmd.Flags().StringVarP(&deploymentVersionID, "deployment-version-id", "r", "", "ID of the deployment version to update (required)") + cmd.Flags().StringVarP(&tag, "tag", "t", "", "Tag of the deployment version") + cmd.Flags().StringToStringVarP(&metadata, "metadata", "m", make(map[string]string), "Metadata key-value pairs (e.g. --metadata key=value)") + cmd.Flags().StringToStringVarP(&configArray, "config", "c", make(map[string]string), "Config key-value pairs with nested values (can be specified multiple times)") + cmd.Flags().StringToStringVarP(&jobAgentConfigArray, "job-agent-config", "j", make(map[string]string), "Job agent config key-value pairs (can be specified multiple times)") + cmd.Flags().StringToStringVarP(&links, "link", "l", make(map[string]string), "Links key-value pairs (can be specified multiple times)") + cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the deployment version") + cmd.Flags().StringVarP(&status, "status", "s", "", "Status of the deployment version") + cmd.Flags().StringVar(&message, "message", "", "Message of the deployment version") + + cmd.MarkFlagRequired("deployment-version-id") + + return cmd +} diff --git a/cmd/ctrlc/root/api/update/update.go b/cmd/ctrlc/root/api/update/update.go index 9c751c1..cb69cf3 100644 --- a/cmd/ctrlc/root/api/update/update.go +++ b/cmd/ctrlc/root/api/update/update.go @@ -1,6 +1,7 @@ package update import ( + "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/update/deploymentversion" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/update/release" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/update/system" "github.com/spf13/cobra" @@ -17,6 +18,7 @@ func NewUpdateCmd() *cobra.Command { } cmd.AddCommand(release.NewUpdateReleaseCmd()) + cmd.AddCommand(deploymentversion.NewUpdateDeploymentVersionCmd()) cmd.AddCommand(system.NewUpdateSystemCmd()) return cmd diff --git a/cmd/ctrlc/root/api/upsert/deploymentversion/deployment-version.go b/cmd/ctrlc/root/api/upsert/deploymentversion/deployment-version.go new file mode 100644 index 0000000..f734802 --- /dev/null +++ b/cmd/ctrlc/root/api/upsert/deploymentversion/deployment-version.go @@ -0,0 +1,127 @@ +package deploymentversion + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/ctrlplanedev/cli/internal/api" + "github.com/ctrlplanedev/cli/internal/cliutil" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func safeConvertToDeploymentVersionStatus(status string) (*api.UpsertDeploymentVersionJSONBodyStatus, error) { + statusLower := strings.ToLower(status) + if statusLower == "ready" || statusLower == "" { + s := api.UpsertDeploymentVersionJSONBodyStatusReady + return &s, nil + } + if statusLower == "building" { + s := api.UpsertDeploymentVersionJSONBodyStatusBuilding + return &s, nil + } + if statusLower == "failed" { + s := api.UpsertDeploymentVersionJSONBodyStatusFailed + return &s, nil + } + return nil, fmt.Errorf("invalid deployment version status: %s", status) +} + +func NewUpsertDeploymentVersionCmd() *cobra.Command { + var tag string + var deploymentID []string + var metadata map[string]string + var configArray map[string]string + var links map[string]string + var createdAt string + var name string + var status string + var message string + + cmd := &cobra.Command{ + Use: "deployment-version [flags]", + Short: "Upsert a deployment version", + Long: `Upsert a deployment version with the specified tag and configuration.`, + Example: heredoc.Doc(` + # Upsert a deployment version + $ ctrlc upsert deployment-version --tag v1.0.0 --deployment 1234567890 + + # Upsert a deployment version using Go template syntax + $ ctrlc upsert deployment-version --tag v1.0.0 --deployment 1234567890 --template='{{.status.phase}}' + + # Upsert a new deployment version for multiple deployments + $ ctrlc upsert deployment-version --tag v1.0.0 --deployment 1234567890 --deployment 0987654321 + `), + RunE: func(cmd *cobra.Command, args []string) error { + apiURL := viper.GetString("url") + apiKey := viper.GetString("api-key") + client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) + if err != nil { + return fmt.Errorf("failed to create API client: %w", err) + } + + var parsedTime *time.Time + if createdAt != "" { + t, err := time.Parse(time.RFC3339, createdAt) + if err != nil { + return fmt.Errorf("failed to parse created_at time: %w", err) + } + parsedTime = &t + } + + if len(links) > 0 { + linksJSON, err := json.Marshal(links) + if err != nil { + return fmt.Errorf("failed to marshal links: %w", err) + } + metadata["ctrlplane/links"] = string(linksJSON) + } + + stat, err := safeConvertToDeploymentVersionStatus(status) + if err != nil { + return fmt.Errorf("failed to convert deployment version status: %w", err) + } + + config := cliutil.ConvertConfigArrayToNestedMap(configArray) + var response *http.Response + for _, id := range deploymentID { + resp, err := client.UpsertDeploymentVersion(cmd.Context(), api.UpsertDeploymentVersionJSONRequestBody{ + Tag: tag, + DeploymentId: id, + Metadata: &metadata, + CreatedAt: parsedTime, + Config: &config, + Name: &name, + Status: stat, + Message: &message, + }) + if err != nil { + return fmt.Errorf("failed to create deployment version: %w", err) + } + response = resp + } + + return cliutil.HandleResponseOutput(cmd, response) + }, + } + + // Add flags + cmd.Flags().StringVarP(&tag, "tag", "t", "", "Tag of the deployment version (required)") + cmd.Flags().StringArrayVarP(&deploymentID, "deployment", "d", []string{}, "IDs of the deployments (required, supports multiple)") + cmd.Flags().StringToStringVarP(&metadata, "metadata", "m", make(map[string]string), "Metadata key-value pairs (e.g. --metadata key=value)") + cmd.Flags().StringToStringVarP(&configArray, "config", "c", make(map[string]string), "Config key-value pairs with nested values (can be specified multiple times)") + cmd.Flags().StringToStringVarP(&links, "link", "l", make(map[string]string), "Links key-value pairs (can be specified multiple times)") + cmd.Flags().StringVarP(&createdAt, "created-at", "r", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the deployment version") + cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the deployment version") + cmd.Flags().StringVarP(&status, "status", "s", string(api.UpsertDeploymentVersionJSONBodyStatusReady), "Status of the deployment version (one of: ready, building, failed)") + cmd.Flags().StringVar(&message, "message", "", "Message of the deployment version") + + cmd.MarkFlagRequired("tag") + cmd.MarkFlagRequired("deployment") + + return cmd +} diff --git a/cmd/ctrlc/root/api/upsert/release/release.go b/cmd/ctrlc/root/api/upsert/release/release.go index f9fdfc3..f90d41c 100644 --- a/cmd/ctrlc/root/api/upsert/release/release.go +++ b/cmd/ctrlc/root/api/upsert/release/release.go @@ -115,7 +115,7 @@ func NewUpsertReleaseCmd() *cobra.Command { cmd.Flags().StringToStringVarP(&metadata, "metadata", "m", make(map[string]string), "Metadata key-value pairs (e.g. --metadata key=value)") cmd.Flags().StringToStringVarP(&configArray, "config", "c", make(map[string]string), "Config key-value pairs with nested values (can be specified multiple times)") cmd.Flags().StringToStringVarP(&links, "link", "l", make(map[string]string), "Links key-value pairs (can be specified multiple times)") - cmd.Flags().StringVarP(&createdAt, "created-at", "t", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the release channel") + cmd.Flags().StringVarP(&createdAt, "created-at", "r", "", "Created at timestamp (e.g. --created-at 2024-01-01T00:00:00Z) for the release channel") cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the release channel") cmd.Flags().StringVarP(&status, "status", "s", string(api.UpsertReleaseJSONBodyStatusReady), "Status of the release channel (one of: ready, building, failed)") cmd.Flags().StringVar(&message, "message", "", "Message of the release channel") diff --git a/cmd/ctrlc/root/api/upsert/upsert.go b/cmd/ctrlc/root/api/upsert/upsert.go index 66ddf2a..fa4789a 100644 --- a/cmd/ctrlc/root/api/upsert/upsert.go +++ b/cmd/ctrlc/root/api/upsert/upsert.go @@ -1,6 +1,7 @@ package upsert import ( + "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/upsert/deploymentversion" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/upsert/release" "github.com/ctrlplanedev/cli/cmd/ctrlc/root/api/upsert/resource" "github.com/spf13/cobra" @@ -18,6 +19,7 @@ func NewUpsertCmd() *cobra.Command { cmd.AddCommand(resource.NewUpsertResourceCmd()) cmd.AddCommand(release.NewUpsertReleaseCmd()) + cmd.AddCommand(deploymentversion.NewUpsertDeploymentVersionCmd()) return cmd } diff --git a/internal/api/client.gen.go b/internal/api/client.gen.go index 0ce42a9..78edd08 100644 --- a/internal/api/client.gen.go +++ b/internal/api/client.gen.go @@ -69,6 +69,20 @@ const ( Gcp GetCloudProviderRegionsParamsProvider = "gcp" ) +// Defines values for UpsertDeploymentVersionJSONBodyStatus. +const ( + UpsertDeploymentVersionJSONBodyStatusBuilding UpsertDeploymentVersionJSONBodyStatus = "building" + UpsertDeploymentVersionJSONBodyStatusFailed UpsertDeploymentVersionJSONBodyStatus = "failed" + UpsertDeploymentVersionJSONBodyStatusReady UpsertDeploymentVersionJSONBodyStatus = "ready" +) + +// Defines values for UpdateDeploymentVersionJSONBodyStatus. +const ( + UpdateDeploymentVersionJSONBodyStatusBuilding UpdateDeploymentVersionJSONBodyStatus = "building" + UpdateDeploymentVersionJSONBodyStatusFailed UpdateDeploymentVersionJSONBodyStatus = "failed" + UpdateDeploymentVersionJSONBodyStatusReady UpdateDeploymentVersionJSONBodyStatus = "ready" +) + // Defines values for UpsertReleaseJSONBodyStatus. const ( UpsertReleaseJSONBodyStatusBuilding UpsertReleaseJSONBodyStatus = "building" @@ -108,6 +122,18 @@ type Deployment struct { Timeout *int `json:"timeout"` } +// DeploymentVersion defines model for DeploymentVersion. +type DeploymentVersion struct { + Config map[string]interface{} `json:"config"` + CreatedAt time.Time `json:"createdAt"` + DeploymentId openapi_types.UUID `json:"deploymentId"` + Id openapi_types.UUID `json:"id"` + JobAgentConfig map[string]interface{} `json:"jobAgentConfig"` + Metadata *map[string]interface{} `json:"metadata,omitempty"` + Name string `json:"name"` + Tag string `json:"tag"` +} + // Environment defines model for Environment. type Environment struct { CreatedAt time.Time `json:"createdAt"` @@ -157,10 +183,11 @@ type JobWithTrigger struct { Id string `json:"id"` Status JobWithTriggerApprovalStatus `json:"status"` } `json:"approval"` - CompletedAt *time.Time `json:"completedAt"` - CreatedAt time.Time `json:"createdAt"` - Deployment *Deployment `json:"deployment,omitempty"` - Environment *Environment `json:"environment,omitempty"` + CompletedAt *time.Time `json:"completedAt"` + CreatedAt time.Time `json:"createdAt"` + Deployment *Deployment `json:"deployment,omitempty"` + DeploymentVersion *DeploymentVersion `json:"deploymentVersion,omitempty"` + Environment *Environment `json:"environment,omitempty"` // ExternalId External job identifier (e.g. GitHub workflow run ID) ExternalId *string `json:"externalId"` @@ -336,6 +363,46 @@ type Workspace struct { // GetCloudProviderRegionsParamsProvider defines parameters for GetCloudProviderRegions. type GetCloudProviderRegionsParamsProvider string +// CreateDeploymentVersionChannelJSONBody defines parameters for CreateDeploymentVersionChannel. +type CreateDeploymentVersionChannelJSONBody struct { + DeploymentId string `json:"deploymentId"` + Description *string `json:"description"` + Name string `json:"name"` + VersionSelector map[string]interface{} `json:"versionSelector"` +} + +// UpsertDeploymentVersionJSONBody defines parameters for UpsertDeploymentVersion. +type UpsertDeploymentVersionJSONBody struct { + Config *map[string]interface{} `json:"config,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + DeploymentId string `json:"deploymentId"` + JobAgentConfig *map[string]interface{} `json:"jobAgentConfig,omitempty"` + Message *string `json:"message,omitempty"` + Metadata *map[string]string `json:"metadata,omitempty"` + Name *string `json:"name,omitempty"` + Status *UpsertDeploymentVersionJSONBodyStatus `json:"status,omitempty"` + Tag string `json:"tag"` +} + +// UpsertDeploymentVersionJSONBodyStatus defines parameters for UpsertDeploymentVersion. +type UpsertDeploymentVersionJSONBodyStatus string + +// UpdateDeploymentVersionJSONBody defines parameters for UpdateDeploymentVersion. +type UpdateDeploymentVersionJSONBody struct { + Config *map[string]interface{} `json:"config,omitempty"` + CreatedAt *time.Time `json:"createdAt,omitempty"` + DeploymentId *string `json:"deploymentId,omitempty"` + JobAgentConfig *map[string]interface{} `json:"jobAgentConfig,omitempty"` + Message *string `json:"message,omitempty"` + Metadata *map[string]string `json:"metadata,omitempty"` + Name *string `json:"name,omitempty"` + Status *UpdateDeploymentVersionJSONBodyStatus `json:"status,omitempty"` + Tag *string `json:"tag,omitempty"` +} + +// UpdateDeploymentVersionJSONBodyStatus defines parameters for UpdateDeploymentVersion. +type UpdateDeploymentVersionJSONBodyStatus string + // CreateDeploymentJSONBody defines parameters for CreateDeployment. type CreateDeploymentJSONBody struct { // Description The description of the deployment @@ -368,7 +435,8 @@ type CreateDeploymentJSONBody struct { // CreateEnvironmentJSONBody defines parameters for CreateEnvironment. type CreateEnvironmentJSONBody struct { - Description *string `json:"description,omitempty"` + DeploymentVersionChannels *[]string `json:"deploymentVersionChannels,omitempty"` + Description *string `json:"description,omitempty"` // Directory The directory path of the environment Directory *string `json:"directory,omitempty"` @@ -525,6 +593,15 @@ type UpdateSystemJSONBody struct { WorkspaceId *openapi_types.UUID `json:"workspaceId,omitempty"` } +// CreateDeploymentVersionChannelJSONRequestBody defines body for CreateDeploymentVersionChannel for application/json ContentType. +type CreateDeploymentVersionChannelJSONRequestBody CreateDeploymentVersionChannelJSONBody + +// UpsertDeploymentVersionJSONRequestBody defines body for UpsertDeploymentVersion for application/json ContentType. +type UpsertDeploymentVersionJSONRequestBody UpsertDeploymentVersionJSONBody + +// UpdateDeploymentVersionJSONRequestBody defines body for UpdateDeploymentVersion for application/json ContentType. +type UpdateDeploymentVersionJSONRequestBody UpdateDeploymentVersionJSONBody + // CreateDeploymentJSONRequestBody defines body for CreateDeployment for application/json ContentType. type CreateDeploymentJSONRequestBody CreateDeploymentJSONBody @@ -910,6 +987,21 @@ type ClientInterface interface { // GetCloudProviderRegions request GetCloudProviderRegions(ctx context.Context, provider GetCloudProviderRegionsParamsProvider, reqEditors ...RequestEditorFn) (*http.Response, error) + // CreateDeploymentVersionChannelWithBody request with any body + CreateDeploymentVersionChannelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateDeploymentVersionChannel(ctx context.Context, body CreateDeploymentVersionChannelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpsertDeploymentVersionWithBody request with any body + UpsertDeploymentVersionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpsertDeploymentVersion(ctx context.Context, body UpsertDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpdateDeploymentVersionWithBody request with any body + UpdateDeploymentVersionWithBody(ctx context.Context, deploymentVersionId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpdateDeploymentVersion(ctx context.Context, deploymentVersionId string, body UpdateDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // CreateDeploymentWithBody request with any body CreateDeploymentWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -926,6 +1018,9 @@ type ClientInterface interface { UpdateDeployment(ctx context.Context, deploymentId openapi_types.UUID, body UpdateDeploymentJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteDeploymentVersionChannel request + DeleteDeploymentVersionChannel(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteReleaseChannel request DeleteReleaseChannel(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -1073,6 +1168,78 @@ func (c *Client) GetCloudProviderRegions(ctx context.Context, provider GetCloudP return c.Client.Do(req) } +func (c *Client) CreateDeploymentVersionChannelWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateDeploymentVersionChannelRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateDeploymentVersionChannel(ctx context.Context, body CreateDeploymentVersionChannelJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateDeploymentVersionChannelRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpsertDeploymentVersionWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertDeploymentVersionRequestWithBody(c.Server, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpsertDeploymentVersion(ctx context.Context, body UpsertDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpsertDeploymentVersionRequest(c.Server, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateDeploymentVersionWithBody(ctx context.Context, deploymentVersionId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateDeploymentVersionRequestWithBody(c.Server, deploymentVersionId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateDeploymentVersion(ctx context.Context, deploymentVersionId string, body UpdateDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateDeploymentVersionRequest(c.Server, deploymentVersionId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) CreateDeploymentWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewCreateDeploymentRequestWithBody(c.Server, contentType, body) if err != nil { @@ -1145,6 +1312,18 @@ func (c *Client) UpdateDeployment(ctx context.Context, deploymentId openapi_type return c.Client.Do(req) } +func (c *Client) DeleteDeploymentVersionChannel(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteDeploymentVersionChannelRequest(c.Server, deploymentId, name) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) DeleteReleaseChannel(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeleteReleaseChannelRequest(c.Server, deploymentId, name) if err != nil { @@ -1767,6 +1946,133 @@ func NewGetCloudProviderRegionsRequest(server string, provider GetCloudProviderR return req, nil } +// NewCreateDeploymentVersionChannelRequest calls the generic CreateDeploymentVersionChannel builder with application/json body +func NewCreateDeploymentVersionChannelRequest(server string, body CreateDeploymentVersionChannelJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewCreateDeploymentVersionChannelRequestWithBody(server, "application/json", bodyReader) +} + +// NewCreateDeploymentVersionChannelRequestWithBody generates requests for CreateDeploymentVersionChannel with any type of body +func NewCreateDeploymentVersionChannelRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/deployment-version-channels") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewUpsertDeploymentVersionRequest calls the generic UpsertDeploymentVersion builder with application/json body +func NewUpsertDeploymentVersionRequest(server string, body UpsertDeploymentVersionJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpsertDeploymentVersionRequestWithBody(server, "application/json", bodyReader) +} + +// NewUpsertDeploymentVersionRequestWithBody generates requests for UpsertDeploymentVersion with any type of body +func NewUpsertDeploymentVersionRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/deployment-versions") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewUpdateDeploymentVersionRequest calls the generic UpdateDeploymentVersion builder with application/json body +func NewUpdateDeploymentVersionRequest(server string, deploymentVersionId string, body UpdateDeploymentVersionJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpdateDeploymentVersionRequestWithBody(server, deploymentVersionId, "application/json", bodyReader) +} + +// NewUpdateDeploymentVersionRequestWithBody generates requests for UpdateDeploymentVersion with any type of body +func NewUpdateDeploymentVersionRequestWithBody(server string, deploymentVersionId string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "deploymentVersionId", runtime.ParamLocationPath, deploymentVersionId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/deployment-versions/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PATCH", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + // NewCreateDeploymentRequest calls the generic CreateDeployment builder with application/json body func NewCreateDeploymentRequest(server string, body CreateDeploymentJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -1922,6 +2228,47 @@ func NewUpdateDeploymentRequestWithBody(server string, deploymentId openapi_type return req, nil } +// NewDeleteDeploymentVersionChannelRequest generates requests for DeleteDeploymentVersionChannel +func NewDeleteDeploymentVersionChannelRequest(server string, deploymentId string, name string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "deploymentId", runtime.ParamLocationPath, deploymentId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "name", runtime.ParamLocationPath, name) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/deployments/%s/deployment-version-channels/name/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewDeleteReleaseChannelRequest generates requests for DeleteReleaseChannel func NewDeleteReleaseChannelRequest(server string, deploymentId string, name string) (*http.Request, error) { var err error @@ -3347,10 +3694,25 @@ type ClientWithResponsesInterface interface { // GetCloudProviderRegionsWithResponse request GetCloudProviderRegionsWithResponse(ctx context.Context, provider GetCloudProviderRegionsParamsProvider, reqEditors ...RequestEditorFn) (*GetCloudProviderRegionsResponse, error) - // CreateDeploymentWithBodyWithResponse request with any body - CreateDeploymentWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDeploymentResponse, error) + // CreateDeploymentVersionChannelWithBodyWithResponse request with any body + CreateDeploymentVersionChannelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDeploymentVersionChannelResponse, error) - CreateDeploymentWithResponse(ctx context.Context, body CreateDeploymentJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDeploymentResponse, error) + CreateDeploymentVersionChannelWithResponse(ctx context.Context, body CreateDeploymentVersionChannelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDeploymentVersionChannelResponse, error) + + // UpsertDeploymentVersionWithBodyWithResponse request with any body + UpsertDeploymentVersionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertDeploymentVersionResponse, error) + + UpsertDeploymentVersionWithResponse(ctx context.Context, body UpsertDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertDeploymentVersionResponse, error) + + // UpdateDeploymentVersionWithBodyWithResponse request with any body + UpdateDeploymentVersionWithBodyWithResponse(ctx context.Context, deploymentVersionId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDeploymentVersionResponse, error) + + UpdateDeploymentVersionWithResponse(ctx context.Context, deploymentVersionId string, body UpdateDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDeploymentVersionResponse, error) + + // CreateDeploymentWithBodyWithResponse request with any body + CreateDeploymentWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDeploymentResponse, error) + + CreateDeploymentWithResponse(ctx context.Context, body CreateDeploymentJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDeploymentResponse, error) // DeleteDeploymentWithResponse request DeleteDeploymentWithResponse(ctx context.Context, deploymentId openapi_types.UUID, reqEditors ...RequestEditorFn) (*DeleteDeploymentResponse, error) @@ -3363,6 +3725,9 @@ type ClientWithResponsesInterface interface { UpdateDeploymentWithResponse(ctx context.Context, deploymentId openapi_types.UUID, body UpdateDeploymentJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDeploymentResponse, error) + // DeleteDeploymentVersionChannelWithResponse request + DeleteDeploymentVersionChannelWithResponse(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*DeleteDeploymentVersionChannelResponse, error) + // DeleteReleaseChannelWithResponse request DeleteReleaseChannelWithResponse(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*DeleteReleaseChannelResponse, error) @@ -3523,6 +3888,96 @@ func (r GetCloudProviderRegionsResponse) StatusCode() int { return 0 } +type CreateDeploymentVersionChannelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + CreatedAt time.Time `json:"createdAt"` + DeploymentId string `json:"deploymentId"` + Description *string `json:"description"` + Id string `json:"id"` + Name string `json:"name"` + VersionSelector *map[string]interface{} `json:"versionSelector,omitempty"` + } + JSON401 *struct { + Error string `json:"error"` + } + JSON403 *struct { + Error string `json:"error"` + } + JSON409 *struct { + Error string `json:"error"` + Id string `json:"id"` + } + JSON500 *struct { + Error string `json:"error"` + } +} + +// Status returns HTTPResponse.Status +func (r CreateDeploymentVersionChannelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreateDeploymentVersionChannelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpsertDeploymentVersionResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *DeploymentVersion + JSON409 *struct { + Error *string `json:"error,omitempty"` + Id *string `json:"id,omitempty"` + } +} + +// Status returns HTTPResponse.Status +func (r UpsertDeploymentVersionResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpsertDeploymentVersionResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpdateDeploymentVersionResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *DeploymentVersion +} + +// Status returns HTTPResponse.Status +func (r UpdateDeploymentVersionResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpdateDeploymentVersionResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type CreateDeploymentResponse struct { Body []byte HTTPResponse *http.Response @@ -3633,6 +4088,39 @@ func (r UpdateDeploymentResponse) StatusCode() int { return 0 } +type DeleteDeploymentVersionChannelResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Message string `json:"message"` + } + JSON403 *struct { + Error string `json:"error"` + } + JSON404 *struct { + Error string `json:"error"` + } + JSON500 *struct { + Error string `json:"error"` + } +} + +// Status returns HTTPResponse.Status +func (r DeleteDeploymentVersionChannelResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteDeploymentVersionChannelResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DeleteReleaseChannelResponse struct { Body []byte HTTPResponse *http.Response @@ -4665,6 +5153,57 @@ func (c *ClientWithResponses) GetCloudProviderRegionsWithResponse(ctx context.Co return ParseGetCloudProviderRegionsResponse(rsp) } +// CreateDeploymentVersionChannelWithBodyWithResponse request with arbitrary body returning *CreateDeploymentVersionChannelResponse +func (c *ClientWithResponses) CreateDeploymentVersionChannelWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDeploymentVersionChannelResponse, error) { + rsp, err := c.CreateDeploymentVersionChannelWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateDeploymentVersionChannelResponse(rsp) +} + +func (c *ClientWithResponses) CreateDeploymentVersionChannelWithResponse(ctx context.Context, body CreateDeploymentVersionChannelJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateDeploymentVersionChannelResponse, error) { + rsp, err := c.CreateDeploymentVersionChannel(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateDeploymentVersionChannelResponse(rsp) +} + +// UpsertDeploymentVersionWithBodyWithResponse request with arbitrary body returning *UpsertDeploymentVersionResponse +func (c *ClientWithResponses) UpsertDeploymentVersionWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpsertDeploymentVersionResponse, error) { + rsp, err := c.UpsertDeploymentVersionWithBody(ctx, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpsertDeploymentVersionResponse(rsp) +} + +func (c *ClientWithResponses) UpsertDeploymentVersionWithResponse(ctx context.Context, body UpsertDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpsertDeploymentVersionResponse, error) { + rsp, err := c.UpsertDeploymentVersion(ctx, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpsertDeploymentVersionResponse(rsp) +} + +// UpdateDeploymentVersionWithBodyWithResponse request with arbitrary body returning *UpdateDeploymentVersionResponse +func (c *ClientWithResponses) UpdateDeploymentVersionWithBodyWithResponse(ctx context.Context, deploymentVersionId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateDeploymentVersionResponse, error) { + rsp, err := c.UpdateDeploymentVersionWithBody(ctx, deploymentVersionId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateDeploymentVersionResponse(rsp) +} + +func (c *ClientWithResponses) UpdateDeploymentVersionWithResponse(ctx context.Context, deploymentVersionId string, body UpdateDeploymentVersionJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateDeploymentVersionResponse, error) { + rsp, err := c.UpdateDeploymentVersion(ctx, deploymentVersionId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateDeploymentVersionResponse(rsp) +} + // CreateDeploymentWithBodyWithResponse request with arbitrary body returning *CreateDeploymentResponse func (c *ClientWithResponses) CreateDeploymentWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateDeploymentResponse, error) { rsp, err := c.CreateDeploymentWithBody(ctx, contentType, body, reqEditors...) @@ -4717,6 +5256,15 @@ func (c *ClientWithResponses) UpdateDeploymentWithResponse(ctx context.Context, return ParseUpdateDeploymentResponse(rsp) } +// DeleteDeploymentVersionChannelWithResponse request returning *DeleteDeploymentVersionChannelResponse +func (c *ClientWithResponses) DeleteDeploymentVersionChannelWithResponse(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*DeleteDeploymentVersionChannelResponse, error) { + rsp, err := c.DeleteDeploymentVersionChannel(ctx, deploymentId, name, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteDeploymentVersionChannelResponse(rsp) +} + // DeleteReleaseChannelWithResponse request returning *DeleteReleaseChannelResponse func (c *ClientWithResponses) DeleteReleaseChannelWithResponse(ctx context.Context, deploymentId string, name string, reqEditors ...RequestEditorFn) (*DeleteReleaseChannelResponse, error) { rsp, err := c.DeleteReleaseChannel(ctx, deploymentId, name, reqEditors...) @@ -5180,6 +5728,138 @@ func ParseGetCloudProviderRegionsResponse(rsp *http.Response) (*GetCloudProvider return response, nil } +// ParseCreateDeploymentVersionChannelResponse parses an HTTP response from a CreateDeploymentVersionChannelWithResponse call +func ParseCreateDeploymentVersionChannelResponse(rsp *http.Response) (*CreateDeploymentVersionChannelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreateDeploymentVersionChannelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + CreatedAt time.Time `json:"createdAt"` + DeploymentId string `json:"deploymentId"` + Description *string `json:"description"` + Id string `json:"id"` + Name string `json:"name"` + VersionSelector *map[string]interface{} `json:"versionSelector,omitempty"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest struct { + Error string `json:"error"` + Id string `json:"id"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + +// ParseUpsertDeploymentVersionResponse parses an HTTP response from a UpsertDeploymentVersionWithResponse call +func ParseUpsertDeploymentVersionResponse(rsp *http.Response) (*UpsertDeploymentVersionResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpsertDeploymentVersionResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest DeploymentVersion + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 409: + var dest struct { + Error *string `json:"error,omitempty"` + Id *string `json:"id,omitempty"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON409 = &dest + + } + + return response, nil +} + +// ParseUpdateDeploymentVersionResponse parses an HTTP response from a UpdateDeploymentVersionWithResponse call +func ParseUpdateDeploymentVersionResponse(rsp *http.Response) (*UpdateDeploymentVersionResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpdateDeploymentVersionResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest DeploymentVersion + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseCreateDeploymentResponse parses an HTTP response from a CreateDeploymentWithResponse call func ParseCreateDeploymentResponse(rsp *http.Response) (*CreateDeploymentResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -5348,6 +6028,61 @@ func ParseUpdateDeploymentResponse(rsp *http.Response) (*UpdateDeploymentRespons return response, nil } +// ParseDeleteDeploymentVersionChannelResponse parses an HTTP response from a DeleteDeploymentVersionChannelWithResponse call +func ParseDeleteDeploymentVersionChannelResponse(rsp *http.Response) (*DeleteDeploymentVersionChannelResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteDeploymentVersionChannelResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Message string `json:"message"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest struct { + Error string `json:"error"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseDeleteReleaseChannelResponse parses an HTTP response from a DeleteReleaseChannelWithResponse call func ParseDeleteReleaseChannelResponse(rsp *http.Response) (*DeleteReleaseChannelResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/test/backwards_compatibility_test.go b/test/backwards_compatibility_test.go new file mode 100644 index 0000000..d4e7d8b --- /dev/null +++ b/test/backwards_compatibility_test.go @@ -0,0 +1,256 @@ +package test + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +const ( + WORKSPACE_ID = "5316df47-1f1c-4a5e-85e6-645e6b821616" + SYSTEM_ID = "55469883-36ae-450a-bc2b-60f6637ed3f4" + DEPLOYMENT_ID = "c585065c-4132-4b91-a479-cf45830b1576" + API_KEY = "f89b6f6172b99919.a02ec78ed6bb0729f860ca7bee5e44495b39eb543ed5c9d8dea7b05e55aa40bf" + API_URL = "http://localhost:3000/api" +) + +func runCommand(args ...string) (string, error) { + // Get the current working directory + cmdDir, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("failed to get working directory: %v", err) + } + + // If we're in the test directory, go up one level to the cli directory + if filepath.Base(cmdDir) == "test" { + cmdDir = filepath.Dir(cmdDir) + } + + // Prepend 'api' to the command args + args = append([]string{"api"}, args...) + + cmd := exec.Command("go", append([]string{"run", "cmd/ctrlc/ctrlc.go"}, args...)...) + cmd.Dir = cmdDir + cmd.Env = append(os.Environ(), + fmt.Sprintf("CTRLPLANE_API_KEY=%s", API_KEY), + fmt.Sprintf("CTRLPLANE_URL=%s", API_URL), + ) + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("command failed: %v\nOutput: %s", err, string(output)) + } + return string(output), nil +} + +func extractID(output string) string { + lines := strings.Split(output, "\n") + for _, line := range lines { + if strings.Contains(line, "\"id\":") { + // Find the last occurrence of ":" to handle cases where the ID might contain colons + lastColon := strings.LastIndex(line, ":") + if lastColon != -1 { + // Get everything after the last colon + id := line[lastColon+1:] + // Remove any quotes, commas, and whitespace + id = strings.TrimSpace(id) + id = strings.Trim(id, ",") + id = strings.Trim(id, `"`) + id = strings.TrimSpace(id) + fmt.Println("ID:", id) + return id + } + } + } + return "" +} + +func TestReleaseBackwardsCompatibility(t *testing.T) { + fmt.Println("\n=== Testing Release Endpoints ===") + + // Test old release endpoint (create) + fmt.Println("\nTesting old release endpoint (create release)") + oldReleaseOutput, err := runCommand("create", "release", + "--version", "v1.0.0", + "--deployment", DEPLOYMENT_ID, + "--name", "Test Release", + "--config", "test=config", + "--job-agent-config", "test=job_config", + ) + if err != nil { + t.Fatalf("Failed to create old release: %v", err) + } + fmt.Println("Old release output:", oldReleaseOutput) + + // Extract release ID from output + releaseID := extractID(oldReleaseOutput) + fmt.Println("Release ID:", releaseID) + if releaseID == "" { + t.Fatal("Failed to extract release ID from output") + } + + // Test old release update endpoint + fmt.Println("\nTesting old release update endpoint (update release)") + oldUpdateOutput, err := runCommand("update", "release", + "--release-id", releaseID, + "--version", "v1.0.1", + ) + if err != nil { + t.Fatalf("Failed to update old release: %v", err) + } + fmt.Println("Old release update output:", oldUpdateOutput) + + // Test new deployment version endpoint (create) + fmt.Println("\nTesting new deployment version endpoint (create deployment-version)") + newVersionOutput, err := runCommand("create", "deployment-version", + "--tag", "v1.1.0", + "--deployment", DEPLOYMENT_ID, + "--name", "Test Deployment Version", + "--config", "test=config", + "--job-agent-config", "test=job_config", + ) + if err != nil { + t.Fatalf("Failed to create new deployment version: %v", err) + } + fmt.Println("New deployment version output:", newVersionOutput) + + // Extract version ID from output + versionID := extractID(newVersionOutput) + if versionID == "" { + t.Fatal("Failed to extract version ID from output") + } + + // Test new deployment version update endpoint + fmt.Println("\nTesting new deployment version update endpoint (update deployment-version)") + newUpdateOutput, err := runCommand("update", "deployment-version", + "--deployment-version-id", versionID, + "--tag", "v1.1.1", + ) + if err != nil { + t.Fatalf("Failed to update new deployment version: %v", err) + } + fmt.Println("New deployment version update output:", newUpdateOutput) +} + +func TestReleaseChannelBackwardsCompatibility(t *testing.T) { + fmt.Println("\n=== Testing Release Channel Endpoints ===") + + // Test old release channel endpoint (create) + fmt.Println("\nTesting old release channel endpoint (create release-channel)") + oldChannelOutput, err := runCommand("create", "release-channel", + "--deployment", DEPLOYMENT_ID, + "--name", "test-channel", + "--description", "Test channel", + "--selector", `{"type":"version","operator":"equals","value":"v1.0.0"}`, + ) + if err != nil { + t.Fatalf("Failed to create old release channel: %v", err) + } + fmt.Println("Old release channel output:", oldChannelOutput) + + // Test old release channel deletion + fmt.Println("\nTesting old release channel deletion (delete release-channel)") + oldDeleteOutput, err := runCommand("delete", "release-channel", + "--deployment", DEPLOYMENT_ID, + "--name", "test-channel", + ) + if err != nil { + t.Fatalf("Failed to delete old release channel: %v", err) + } + fmt.Println("Old release channel deletion output:", oldDeleteOutput) + + // Test new deployment version channel endpoint (create) + fmt.Println("\nTesting new deployment version channel endpoint (create deployment-version-channel)") + newChannelOutput, err := runCommand("create", "deployment-version-channel", + "--deployment", DEPLOYMENT_ID, + "--name", "test-version-channel", + "--description", "Test version channel", + "--selector", `{"type":"tag","operator":"equals","value":"v1.1.0"}`, + ) + if err != nil { + t.Fatalf("Failed to create new deployment version channel: %v", err) + } + fmt.Println("New deployment version channel output:", newChannelOutput) + + // Skip deployment version channel deletion since endpoint doesn't exist yet + runCommand("delete", "deployment-version-channel", "--deployment", DEPLOYMENT_ID, "--name", "test-version-channel") + + // Extract release channel ID + releaseChannelID := extractID(oldChannelOutput) + fmt.Println("Release channel ID:", releaseChannelID) + if releaseChannelID == "" { + t.Fatal("Failed to extract release channel ID") + } +} + +func TestEnvironmentWithMixedChannels(t *testing.T) { + fmt.Println("\n=== Testing Environment with Mixed Channels ===") + + // Create a release channel + fmt.Println("\nCreating release channel for mixed environment") + releaseChannelOutput, err := runCommand("create", "release-channel", + "--deployment", DEPLOYMENT_ID, + "--name", "mixed-test-release-channel", + "--description", "Test release channel for mixed environment", + "--selector", `{"type":"version","operator":"equals","value":"v1.0.0"}`, + ) + if err != nil { + t.Fatalf("Failed to create release channel: %v", err) + } + fmt.Println("Release channel output:", releaseChannelOutput) + + // Extract release channel ID + releaseChannelID := extractID(releaseChannelOutput) + fmt.Println("Release channel ID:", releaseChannelID) + if releaseChannelID == "" { + t.Fatal("Failed to extract release channel ID") + } + + // Create a deployment version channel + fmt.Println("\nCreating deployment version channel for mixed environment") + versionChannelOutput, err := runCommand("create", "deployment-version-channel", + "--deployment", DEPLOYMENT_ID, + "--name", "mixed-test-version-channel", + "--description", "Test version channel for mixed environment", + "--selector", `{"type":"tag","operator":"equals","value":"v1.1.0"}`, + ) + if err != nil { + t.Fatalf("Failed to create deployment version channel: %v", err) + } + fmt.Println("Deployment version channel output:", versionChannelOutput) + + // Extract version channel ID + versionChannelID := extractID(versionChannelOutput) + fmt.Println("Version channel ID:", versionChannelID) + if versionChannelID == "" { + t.Fatal("Failed to extract version channel ID") + } + + // Create environment with both channels + fmt.Println("\nCreating environment with mixed channels") + environmentOutput, err := runCommand("create", "environment", + "--system", SYSTEM_ID, + "--name", "mixed-test-environment", + "--release-channel", releaseChannelID, + "--deployment-version-channel", versionChannelID, + "--metadata", "test=mixed environment", + ) + if err != nil { + t.Fatalf("Failed to create environment: %v", err) + } + fmt.Println("Environment output:", environmentOutput) + + // Extract environment ID + environmentID := extractID(environmentOutput) + if environmentID == "" { + t.Fatal("Failed to extract environment ID") + } + + // Clean up + fmt.Println("\nCleaning up...") + runCommand("delete", "environment", "--environment", environmentID) + runCommand("delete", "release-channel", "--deployment", DEPLOYMENT_ID, "--name", "mixed-test-release-channel") + runCommand("delete", "deployment-version-channel", "--deployment", DEPLOYMENT_ID, "--name", "mixed-test-version-channel") +} From 4ced9a4c4f2ae88ce0027c351a73fc8b1df77640 Mon Sep 17 00:00:00 2001 From: Aditya Choudhari Date: Wed, 2 Apr 2025 19:13:48 -0700 Subject: [PATCH 2/2] remove test --- test/backwards_compatibility_test.go | 256 --------------------------- 1 file changed, 256 deletions(-) delete mode 100644 test/backwards_compatibility_test.go diff --git a/test/backwards_compatibility_test.go b/test/backwards_compatibility_test.go deleted file mode 100644 index d4e7d8b..0000000 --- a/test/backwards_compatibility_test.go +++ /dev/null @@ -1,256 +0,0 @@ -package test - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" -) - -const ( - WORKSPACE_ID = "5316df47-1f1c-4a5e-85e6-645e6b821616" - SYSTEM_ID = "55469883-36ae-450a-bc2b-60f6637ed3f4" - DEPLOYMENT_ID = "c585065c-4132-4b91-a479-cf45830b1576" - API_KEY = "f89b6f6172b99919.a02ec78ed6bb0729f860ca7bee5e44495b39eb543ed5c9d8dea7b05e55aa40bf" - API_URL = "http://localhost:3000/api" -) - -func runCommand(args ...string) (string, error) { - // Get the current working directory - cmdDir, err := os.Getwd() - if err != nil { - return "", fmt.Errorf("failed to get working directory: %v", err) - } - - // If we're in the test directory, go up one level to the cli directory - if filepath.Base(cmdDir) == "test" { - cmdDir = filepath.Dir(cmdDir) - } - - // Prepend 'api' to the command args - args = append([]string{"api"}, args...) - - cmd := exec.Command("go", append([]string{"run", "cmd/ctrlc/ctrlc.go"}, args...)...) - cmd.Dir = cmdDir - cmd.Env = append(os.Environ(), - fmt.Sprintf("CTRLPLANE_API_KEY=%s", API_KEY), - fmt.Sprintf("CTRLPLANE_URL=%s", API_URL), - ) - output, err := cmd.CombinedOutput() - if err != nil { - return "", fmt.Errorf("command failed: %v\nOutput: %s", err, string(output)) - } - return string(output), nil -} - -func extractID(output string) string { - lines := strings.Split(output, "\n") - for _, line := range lines { - if strings.Contains(line, "\"id\":") { - // Find the last occurrence of ":" to handle cases where the ID might contain colons - lastColon := strings.LastIndex(line, ":") - if lastColon != -1 { - // Get everything after the last colon - id := line[lastColon+1:] - // Remove any quotes, commas, and whitespace - id = strings.TrimSpace(id) - id = strings.Trim(id, ",") - id = strings.Trim(id, `"`) - id = strings.TrimSpace(id) - fmt.Println("ID:", id) - return id - } - } - } - return "" -} - -func TestReleaseBackwardsCompatibility(t *testing.T) { - fmt.Println("\n=== Testing Release Endpoints ===") - - // Test old release endpoint (create) - fmt.Println("\nTesting old release endpoint (create release)") - oldReleaseOutput, err := runCommand("create", "release", - "--version", "v1.0.0", - "--deployment", DEPLOYMENT_ID, - "--name", "Test Release", - "--config", "test=config", - "--job-agent-config", "test=job_config", - ) - if err != nil { - t.Fatalf("Failed to create old release: %v", err) - } - fmt.Println("Old release output:", oldReleaseOutput) - - // Extract release ID from output - releaseID := extractID(oldReleaseOutput) - fmt.Println("Release ID:", releaseID) - if releaseID == "" { - t.Fatal("Failed to extract release ID from output") - } - - // Test old release update endpoint - fmt.Println("\nTesting old release update endpoint (update release)") - oldUpdateOutput, err := runCommand("update", "release", - "--release-id", releaseID, - "--version", "v1.0.1", - ) - if err != nil { - t.Fatalf("Failed to update old release: %v", err) - } - fmt.Println("Old release update output:", oldUpdateOutput) - - // Test new deployment version endpoint (create) - fmt.Println("\nTesting new deployment version endpoint (create deployment-version)") - newVersionOutput, err := runCommand("create", "deployment-version", - "--tag", "v1.1.0", - "--deployment", DEPLOYMENT_ID, - "--name", "Test Deployment Version", - "--config", "test=config", - "--job-agent-config", "test=job_config", - ) - if err != nil { - t.Fatalf("Failed to create new deployment version: %v", err) - } - fmt.Println("New deployment version output:", newVersionOutput) - - // Extract version ID from output - versionID := extractID(newVersionOutput) - if versionID == "" { - t.Fatal("Failed to extract version ID from output") - } - - // Test new deployment version update endpoint - fmt.Println("\nTesting new deployment version update endpoint (update deployment-version)") - newUpdateOutput, err := runCommand("update", "deployment-version", - "--deployment-version-id", versionID, - "--tag", "v1.1.1", - ) - if err != nil { - t.Fatalf("Failed to update new deployment version: %v", err) - } - fmt.Println("New deployment version update output:", newUpdateOutput) -} - -func TestReleaseChannelBackwardsCompatibility(t *testing.T) { - fmt.Println("\n=== Testing Release Channel Endpoints ===") - - // Test old release channel endpoint (create) - fmt.Println("\nTesting old release channel endpoint (create release-channel)") - oldChannelOutput, err := runCommand("create", "release-channel", - "--deployment", DEPLOYMENT_ID, - "--name", "test-channel", - "--description", "Test channel", - "--selector", `{"type":"version","operator":"equals","value":"v1.0.0"}`, - ) - if err != nil { - t.Fatalf("Failed to create old release channel: %v", err) - } - fmt.Println("Old release channel output:", oldChannelOutput) - - // Test old release channel deletion - fmt.Println("\nTesting old release channel deletion (delete release-channel)") - oldDeleteOutput, err := runCommand("delete", "release-channel", - "--deployment", DEPLOYMENT_ID, - "--name", "test-channel", - ) - if err != nil { - t.Fatalf("Failed to delete old release channel: %v", err) - } - fmt.Println("Old release channel deletion output:", oldDeleteOutput) - - // Test new deployment version channel endpoint (create) - fmt.Println("\nTesting new deployment version channel endpoint (create deployment-version-channel)") - newChannelOutput, err := runCommand("create", "deployment-version-channel", - "--deployment", DEPLOYMENT_ID, - "--name", "test-version-channel", - "--description", "Test version channel", - "--selector", `{"type":"tag","operator":"equals","value":"v1.1.0"}`, - ) - if err != nil { - t.Fatalf("Failed to create new deployment version channel: %v", err) - } - fmt.Println("New deployment version channel output:", newChannelOutput) - - // Skip deployment version channel deletion since endpoint doesn't exist yet - runCommand("delete", "deployment-version-channel", "--deployment", DEPLOYMENT_ID, "--name", "test-version-channel") - - // Extract release channel ID - releaseChannelID := extractID(oldChannelOutput) - fmt.Println("Release channel ID:", releaseChannelID) - if releaseChannelID == "" { - t.Fatal("Failed to extract release channel ID") - } -} - -func TestEnvironmentWithMixedChannels(t *testing.T) { - fmt.Println("\n=== Testing Environment with Mixed Channels ===") - - // Create a release channel - fmt.Println("\nCreating release channel for mixed environment") - releaseChannelOutput, err := runCommand("create", "release-channel", - "--deployment", DEPLOYMENT_ID, - "--name", "mixed-test-release-channel", - "--description", "Test release channel for mixed environment", - "--selector", `{"type":"version","operator":"equals","value":"v1.0.0"}`, - ) - if err != nil { - t.Fatalf("Failed to create release channel: %v", err) - } - fmt.Println("Release channel output:", releaseChannelOutput) - - // Extract release channel ID - releaseChannelID := extractID(releaseChannelOutput) - fmt.Println("Release channel ID:", releaseChannelID) - if releaseChannelID == "" { - t.Fatal("Failed to extract release channel ID") - } - - // Create a deployment version channel - fmt.Println("\nCreating deployment version channel for mixed environment") - versionChannelOutput, err := runCommand("create", "deployment-version-channel", - "--deployment", DEPLOYMENT_ID, - "--name", "mixed-test-version-channel", - "--description", "Test version channel for mixed environment", - "--selector", `{"type":"tag","operator":"equals","value":"v1.1.0"}`, - ) - if err != nil { - t.Fatalf("Failed to create deployment version channel: %v", err) - } - fmt.Println("Deployment version channel output:", versionChannelOutput) - - // Extract version channel ID - versionChannelID := extractID(versionChannelOutput) - fmt.Println("Version channel ID:", versionChannelID) - if versionChannelID == "" { - t.Fatal("Failed to extract version channel ID") - } - - // Create environment with both channels - fmt.Println("\nCreating environment with mixed channels") - environmentOutput, err := runCommand("create", "environment", - "--system", SYSTEM_ID, - "--name", "mixed-test-environment", - "--release-channel", releaseChannelID, - "--deployment-version-channel", versionChannelID, - "--metadata", "test=mixed environment", - ) - if err != nil { - t.Fatalf("Failed to create environment: %v", err) - } - fmt.Println("Environment output:", environmentOutput) - - // Extract environment ID - environmentID := extractID(environmentOutput) - if environmentID == "" { - t.Fatal("Failed to extract environment ID") - } - - // Clean up - fmt.Println("\nCleaning up...") - runCommand("delete", "environment", "--environment", environmentID) - runCommand("delete", "release-channel", "--deployment", DEPLOYMENT_ID, "--name", "mixed-test-release-channel") - runCommand("delete", "deployment-version-channel", "--deployment", DEPLOYMENT_ID, "--name", "mixed-test-version-channel") -}