Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/ctrlc/root/api/create/create.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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())
Expand Down
131 changes: 131 additions & 0 deletions cmd/ctrlc/root/api/create/deploymentversion/deployment-version.go
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 6 additions & 0 deletions cmd/ctrlc/root/api/create/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}}'
`),
Expand All @@ -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)

Expand All @@ -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 <channelid>")
cmd.Flags().StringSliceVarP(&deploymentVersionChannels, "deployment-version-channel", "d", []string{}, "Deployment version channel in format <channelid>")
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)")

Expand Down
2 changes: 1 addition & 1 deletion cmd/ctrlc/root/api/create/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
3 changes: 2 additions & 1 deletion cmd/ctrlc/root/api/delete/delete.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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
}
Original file line number Diff line number Diff line change
@@ -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
}
Loading