Skip to content
Open
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
72 changes: 46 additions & 26 deletions cmd/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ func NewCmdBundle() *cobra.Command { //nolint:funlen // cobra command builders a
var bundleListInput bundleList

bundleListCmd := &cobra.Command{
Use: "list",
Short: "List bundles in your organization",
Long: helpdocs.MustRender("bundle/list"),
Use: "list",
Aliases: []string{"ls"},
Short: "List bundles in your organization",
Long: helpdocs.MustRender("bundle/list"),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
return runBundleList(&bundleListInput)
Expand Down Expand Up @@ -158,11 +159,13 @@ func NewCmdBundle() *cobra.Command { //nolint:funlen // cobra command builders a
}

bundleTemplateListCmd := &cobra.Command{
Use: "list",
Short: "List bundle templates",
Long: helpdocs.MustRender("bundle/template-list"),
RunE: runBundleTemplateList,
Use: "list",
Aliases: []string{"ls"},
Short: "List bundle templates",
Long: helpdocs.MustRender("bundle/template-list"),
RunE: runBundleTemplateList,
}
bundleTemplateListCmd.Flags().StringP("output", "o", "text", "Output format (text, json)")

bundleCreateCmd := &cobra.Command{
Use: "create <name>",
Expand Down Expand Up @@ -207,19 +210,34 @@ func runBundleCreate(cmd *cobra.Command, args []string) error {
}

func runBundleTemplateList(cmd *cobra.Command, args []string) error {
templateList, err := templates.List()
output, err := cmd.Flags().GetString("output")
if err != nil {
return err
}

if len(templateList) == 0 {
fmt.Println("No templates found.")
return nil
templateList, err := templates.List()
if err != nil {
return err
}

fmt.Println("Available templates:")
for _, tmpl := range templateList {
fmt.Printf(" %s\n", tmpl)
switch output {
case "json":
jsonBytes, marshalErr := json.MarshalIndent(templateList, "", " ")
if marshalErr != nil {
return fmt.Errorf("failed to marshal templates to JSON: %w", marshalErr)
}
fmt.Println(string(jsonBytes))
case "text":
if len(templateList) == 0 {
fmt.Println("No templates found.")
return nil
}
fmt.Println("Available templates:")
for _, tmpl := range templateList {
fmt.Printf(" %s\n", tmpl)
}
default:
return fmt.Errorf("unsupported output format: %s", output)
}
return nil
}
Expand Down Expand Up @@ -522,24 +540,26 @@ func runBundleList(input *bundleList) error {
}
}

repos, err := mdClient.OciRepos.List(ctx, listInput)
if err != nil {
return fmt.Errorf("failed to list bundles: %w", err)
}
seq := mdClient.OciRepos.Iter(ctx, listInput)

switch input.output {
case "json":
jsonBytes, err := json.MarshalIndent(repos, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal bundles to JSON: %w", err)
repos, collectErr := types.Collect(seq)
if collectErr != nil {
return fmt.Errorf("failed to list bundles: %w", collectErr)
}
jsonBytes, marshalErr := json.MarshalIndent(repos, "", " ")
if marshalErr != nil {
return fmt.Errorf("failed to marshal bundles to JSON: %w", marshalErr)
}
fmt.Println(string(jsonBytes))
case "table":
tbl := cli.NewTable("Name", "Latest", "Created At")
for _, repo := range repos {
tbl.AddRow(repo.Name, repo.LatestTag, repo.CreatedAt.Format("2006-01-02 15:04:05"))
}
tbl.Print()
return cli.Paginate(seq, cli.PagerConfig[ocirepos.OciRepo]{
Columns: []string{"Name", "Latest", "Created At"},
Row: func(repo ocirepos.OciRepo) []string {
return []string{repo.Name, repo.LatestTag, repo.CreatedAt.Format("2006-01-02 15:04:05")}
},
})
default:
return fmt.Errorf("unsupported output format: %s", input.output)
}
Expand Down
54 changes: 43 additions & 11 deletions cmd/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ func NewCmdDeployment() *cobra.Command {
RunE: runDeploymentList,
}
deploymentListCmd.Flags().IntP("limit", "n", 10, "Maximum number of deployments to return (max 100)")
deploymentListCmd.Flags().StringP("output", "o", "table", "Output format (table, json)")
deploymentListCmd.Flags().String("status", "", "Filter by status (pending, approved, running, completed, failed, aborted, rejected, proposed)")
deploymentListCmd.Flags().String("action", "", "Filter by action (provision, decommission, plan)")
deploymentListCmd.Flags().String("repo", "", "Filter by OCI repo name")
deploymentListCmd.Flags().String("bundle", "", "Filter by bundle version (name@version) or release channel (name@latest)")

deploymentLogsCmd := &cobra.Command{
Use: "logs <deployment-id>",
Expand Down Expand Up @@ -129,36 +134,63 @@ func runDeploymentList(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
status, _ := cmd.Flags().GetString("status")
action, _ := cmd.Flags().GetString("action")
repo, _ := cmd.Flags().GetString("repo")
bundle, _ := cmd.Flags().GetString("bundle")
output, _ := cmd.Flags().GetString("output")
cmd.SilenceUsage = true

mdClient, err := massdriver.NewClient()
if err != nil {
return fmt.Errorf("error initializing massdriver client: %w", err)
}

// SDK's List auto-paginates without a total cap; we want a total cap, so
// SDK's Iter auto-paginates without a total cap; we want a total cap, so
// drive Iter and stop after `limit` items.
listInput := deployments.ListInput{
InstanceID: instanceID,
SortBy: deployments.SortByCreatedAt,
SortOrder: deployments.SortDesc,
InstanceID: instanceID,
OciRepoName: repo,
BundleID: bundle,
SortBy: deployments.SortByCreatedAt,
SortOrder: deployments.SortDesc,
}
if status != "" {
listInput.Status = deployments.Status(strings.ToUpper(status))
}
if action != "" {
listInput.Action = deployments.Action(strings.ToUpper(action))
}

tbl := cli.NewTable("ID", "Action", "Status", "Version", "Created At", "By", "Message")
count := 0
deps := make([]deployments.Deployment, 0, limit)
for d, iterErr := range mdClient.Deployments.Iter(ctx, listInput) {
if iterErr != nil {
return iterErr
}
if limit > 0 && count >= limit {
if limit > 0 && len(deps) >= limit {
break
}
tbl.AddRow(d.ID, d.Action, d.Status, d.Version, d.CreatedAt, d.DeployedBy, cli.TruncateString(d.Message, 40))
count++
deps = append(deps, d)
}
tbl.Print()

return nil
switch output {
case "json":
jsonBytes, marshalErr := json.MarshalIndent(deps, "", " ")
if marshalErr != nil {
return fmt.Errorf("failed to marshal deployments to JSON: %w", marshalErr)
}
fmt.Println(string(jsonBytes))
return nil
case "table":
tbl := cli.NewTable("ID", "Action", "Status", "Version", "Created At", "By", "Message")
for _, d := range deps {
tbl.AddRow(d.ID, d.Action, d.Status, d.Version, d.CreatedAt, d.DeployedBy, cli.TruncateString(d.Message, 40))
}
tbl.Print()
return nil
default:
return fmt.Errorf("unsupported output format: %s", output)
}
}

func runDeploymentLogs(cmd *cobra.Command, args []string) error {
Expand Down
56 changes: 38 additions & 18 deletions cmd/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ func NewCmdEnvironment() *cobra.Command {
environmentGetCmd.Flags().StringP("output", "o", "text", "Output format (text or json)")

environmentListCmd := &cobra.Command{
Use: "list",
Short: "List environments",
Long: helpdocs.MustRender("environment/list"),
Args: cobra.ExactArgs(1),
RunE: runEnvironmentList,
Use: "list",
Aliases: []string{"ls"},
Short: "List environments",
Long: helpdocs.MustRender("environment/list"),
Args: cobra.ExactArgs(1),
RunE: runEnvironmentList,
}
environmentListCmd.Flags().StringP("output", "o", "table", "Output format (table, json)")
environmentListCmd.Flags().StringSlice("id", nil, "Filter to specific environment IDs (repeatable)")

environmentCreateCmd := &cobra.Command{
Use: "create [ID]",
Expand Down Expand Up @@ -220,21 +223,22 @@ func runEnvironmentList(cmd *cobra.Command, args []string) error {

projectID := args[0]

output, err := cmd.Flags().GetString("output")
if err != nil {
return err
}
ids, _ := cmd.Flags().GetStringSlice("id")

cmd.SilenceUsage = true

mdClient, err := massdriver.NewClient()
if err != nil {
return fmt.Errorf("error initializing massdriver client: %w", err)
}

envs, err := mdClient.Environments.List(ctx, environments.ListInput{ProjectID: projectID})
if err != nil {
return err
}

tbl := cli.NewTable("ID", "Name", "Description", "Monthly $", "Daily $")
seq := mdClient.Environments.Iter(ctx, environments.ListInput{ProjectID: projectID, IDs: ids})

for _, env := range envs {
row := func(env environments.Environment) []string {
monthly := ""
daily := ""
if env.Cost.MonthlyAverage.Amount != nil {
Expand All @@ -243,13 +247,29 @@ func runEnvironmentList(cmd *cobra.Command, args []string) error {
if env.Cost.DailyAverage.Amount != nil {
daily = fmt.Sprintf("%v", *env.Cost.DailyAverage.Amount)
}
description := cli.TruncateString(env.Description, 60)
tbl.AddRow(env.ID, env.Name, description, monthly, daily)
return []string{env.ID, env.Name, cli.TruncateString(env.Description, 60), monthly, daily}
}

tbl.Print()

return nil
switch output {
case "json":
envs, collectErr := types.Collect(seq)
if collectErr != nil {
return collectErr
}
jsonBytes, marshalErr := json.MarshalIndent(envs, "", " ")
if marshalErr != nil {
return fmt.Errorf("failed to marshal environments to JSON: %w", marshalErr)
}
fmt.Println(string(jsonBytes))
return nil
case "table":
return cli.Paginate(seq, cli.PagerConfig[environments.Environment]{
Columns: []string{"ID", "Name", "Description", "Monthly $", "Daily $"},
Row: row,
})
default:
return fmt.Errorf("unsupported output format: %s", output)
}
}

func renderEnvironment(ctx context.Context, mdClient *massdriver.Client, env *environments.Environment) error {
Expand All @@ -265,7 +285,7 @@ func renderEnvironment(ctx context.Context, mdClient *massdriver.Client, env *en

// Instances aren't embedded on the environment record returned by
// Environments.Get; fetch them separately so the template can render them.
insts, err := mdClient.Instances.List(ctx, instances.ListInput{EnvironmentID: env.ID})
insts, err := types.Collect(mdClient.Instances.Iter(ctx, instances.ListInput{EnvironmentID: env.ID}))
if err != nil {
return fmt.Errorf("failed to list instances: %w", err)
}
Expand Down
63 changes: 47 additions & 16 deletions cmd/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@
Args: cobra.ExactArgs(1),
RunE: runInstanceList,
}
instanceListCmd.Flags().StringP("output", "o", "table", "Output format (table, json)")
instanceListCmd.Flags().String("status", "", "Filter by lifecycle status (initialized, provisioned, decommissioned, failed)")
instanceListCmd.Flags().String("repo", "", "Filter by OCI repo name (matches all versions of a bundle)")
instanceListCmd.Flags().String("bundle", "", "Filter by bundle version (name@version) or release channel (name@latest)")

instanceOrphanCmd := &cobra.Command{
Use: `orphan <project>-<env>-<manifest>`,
Expand Down Expand Up @@ -475,33 +479,60 @@

environmentID := args[0]

output, err := cmd.Flags().GetString("output")
if err != nil {
return err
}
status, _ := cmd.Flags().GetString("status")
repo, _ := cmd.Flags().GetString("repo")
bundle, _ := cmd.Flags().GetString("bundle")

cmd.SilenceUsage = true

mdClient, err := massdriver.NewClient()
if err != nil {
return fmt.Errorf("error initializing massdriver client: %w", err)
}

insts, err := mdClient.Instances.List(ctx, instances.ListInput{EnvironmentID: environmentID})
if err != nil {
return err
listInput := instances.ListInput{
EnvironmentID: environmentID,
OciRepoName: repo,
BundleID: bundle,
}
if status != "" {
listInput.Status = instances.Status(strings.ToUpper(status))
}

tbl := cli.NewTable("ID", "Name", "Bundle", "Status")
seq := mdClient.Instances.Iter(ctx, listInput)

for _, inst := range insts {
componentName := ""
if inst.Component != nil {
componentName = inst.Component.Name
switch output {
case "json":
insts, collectErr := types.Collect(seq)
if collectErr != nil {
return collectErr
}
bundleName := ""
if inst.Bundle != nil {
bundleName = inst.Bundle.Name
jsonBytes, marshalErr := json.MarshalIndent(insts, "", " ")
if marshalErr != nil {
return fmt.Errorf("failed to marshal instances to JSON: %w", marshalErr)
}
tbl.AddRow(inst.ID, componentName, bundleName, inst.Status)
fmt.Println(string(jsonBytes))
return nil
case "table":
return cli.Paginate(seq, cli.PagerConfig[instances.Instance]{
Columns: []string{"ID", "Name", "Bundle", "Status"},
Row: func(inst instances.Instance) []string {
componentName := ""
if inst.Component != nil {
componentName = inst.Component.Name
}
bundleName := ""
if inst.Bundle != nil {
bundleName = inst.Bundle.Name
}
return []string{inst.ID, componentName, bundleName, string(inst.Status)}

Check failure on line 532 in cmd/instance.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary conversion (unconvert)
},
})
default:
return fmt.Errorf("unsupported output format: %s", output)
}

tbl.Print()

return nil
}
Loading
Loading