Skip to content

Commit

Permalink
feat: create atmos list command for listing stacks and components (#…
Browse files Browse the repository at this point in the history
…797)

* feat: add atmos list stacks and components command

* feat: list commands, update docs

* feat: create listing helper functions

* feat: create listing helper functions

* feat: add spacing

* refactor: remove duplicate code, enhance error handling, and update
inline docs

* feat: add tests

* Update pkg/list/list_stacks_test.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update pkg/list/list_components_test.go tests

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: remove list custom command

remove custom list command

* feat: update tests

update tests to include more assertions

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
RoseSecurity and coderabbitai[bot] authored Nov 26, 2024
1 parent 4b30800 commit 3f1cad7
Show file tree
Hide file tree
Showing 25 changed files with 789 additions and 379 deletions.
53 changes: 0 additions & 53 deletions atmos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -191,59 +191,6 @@ commands:
- 'echo Dependencies: "{{ .ComponentConfig.deps }}"'
- 'echo settings.config.is_prod: "{{ .ComponentConfig.settings.config.is_prod }}"'
- 'echo ATMOS_IS_PROD: "$ATMOS_IS_PROD"'
- name: list
description: Execute 'atmos list' commands
# subcommands
commands:
- name: stacks
description: |
List all Atmos stacks.
steps:
- >
atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
- name: components
description: |
List all Atmos components in all stacks or in a single stack.
Example usage:
atmos list components
atmos list components -s plat-ue2-dev
atmos list components --stack plat-uw2-prod
atmos list components -s plat-ue2-dev --type abstract
atmos list components -s plat-ue2-dev -t enabled
atmos list components -s plat-ue2-dev -t disabled
flags:
- name: stack
shorthand: s
description: Name of the stack
required: false
- name: type
shorthand: t
description: Component types - abstract, enabled, or disabled
required: false
steps:
- >
{{ if .Flags.stack }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r .key
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r .key
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r .key
{{ else }}
atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ else }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else }}
atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ end }}

# Integrations
integrations:
Expand Down
17 changes: 17 additions & 0 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"github.com/spf13/cobra"
)

// listCmd commands list stacks and components
var listCmd = &cobra.Command{
Use: "list",
Short: "Execute 'list' commands",
Long: `This command lists stacks and components`,
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
}

func init() {
RootCmd.AddCommand(listCmd)
}
54 changes: 54 additions & 0 deletions cmd/list_components.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package cmd

import (
"fmt"

e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/config"
l "github.com/cloudposse/atmos/pkg/list"
"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

// listComponentsCmd lists atmos components
var listComponentsCmd = &cobra.Command{
Use: "components",
Short: "Execute 'list components' command",
Long: `This command lists all Atmos components or filters components by stacks.`,
Example: "atmos list components\n" +
"atmos list components -s <stack>",
Run: func(cmd *cobra.Command, args []string) {
// Check Atmos configuration
checkAtmosConfig()

stackFlag, _ := cmd.Flags().GetString("stack")

configAndStacksInfo := schema.ConfigAndStacksInfo{}
cliConfig, err := config.InitCliConfig(configAndStacksInfo, true)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error initializing CLI config: %v", err), color.New(color.FgRed))
return
}

stacksMap, err := e.ExecuteDescribeStacks(cliConfig, "", nil, nil, nil, false, false, false)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error describing stacks: %v", err), color.New(color.FgRed))
return
}

output, err := l.FilterAndListComponents(stackFlag, stacksMap)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error: %v"+"\n", err), color.New(color.FgYellow))
return
}

u.PrintMessageInColor(output, color.New(color.FgGreen))
},
}

func init() {
listComponentsCmd.PersistentFlags().StringP("stack", "s", "", "Filter components by stack (e.g., atmos list components -s stack1)")
listCmd.AddCommand(listComponentsCmd)
}
55 changes: 55 additions & 0 deletions cmd/list_stacks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"fmt"

e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/config"
l "github.com/cloudposse/atmos/pkg/list"
"github.com/cloudposse/atmos/pkg/schema"
u "github.com/cloudposse/atmos/pkg/utils"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

// listStacksCmd lists atmos stacks
var listStacksCmd = &cobra.Command{
Use: "stacks",
Short: "Execute 'list stacks' command",
Long: `This command lists all Atmos stacks or all stacks for the specified component: atmos list stacks -c <component>`,
Example: "atmos list stacks\n" +
"atmos list stacks -c <component>",
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
Run: func(cmd *cobra.Command, args []string) {
// Check Atmos configuration
checkAtmosConfig()

componentFlag, _ := cmd.Flags().GetString("component")

configAndStacksInfo := schema.ConfigAndStacksInfo{}
cliConfig, err := config.InitCliConfig(configAndStacksInfo, true)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error initializing CLI config: %v", err), color.New(color.FgRed))
return
}

stacksMap, err := e.ExecuteDescribeStacks(cliConfig, "", nil, nil, nil, false, false, false)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error describing stacks: %v", err), color.New(color.FgRed))
return
}

output, err := l.FilterAndListStacks(stacksMap, componentFlag)
if err != nil {
u.PrintMessageInColor(fmt.Sprintf("Error filtering stacks: %v", err), color.New(color.FgRed))
return
}
u.PrintMessageInColor(output, color.New(color.FgGreen))
},
}

func init() {
listStacksCmd.DisableFlagParsing = false
listStacksCmd.PersistentFlags().StringP("component", "c", "", "atmos list stacks -c <component>")
listCmd.AddCommand(listStacksCmd)
}
53 changes: 0 additions & 53 deletions examples/quick-start-advanced/atmos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -176,59 +176,6 @@ commands:
- 'echo Environment: "{{ .ComponentConfig.vars.environment }}"'
- 'echo Stage: "{{ .ComponentConfig.vars.stage }}"'
- 'echo Dependencies: "{{ .ComponentConfig.deps }}"'
- name: list
description: Execute 'atmos list' commands
# subcommands
commands:
- name: stacks
description: |
List all Atmos stacks.
steps:
- >
atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
- name: components
description: |
List all Atmos components in all stacks or in a single stack.
Example usage:
atmos list components
atmos list components -s plat-ue2-dev
atmos list components --stack plat-uw2-prod
atmos list components -s plat-ue2-dev --type abstract
atmos list components -s plat-ue2-dev -t enabled
atmos list components -s plat-ue2-dev -t disabled
flags:
- name: stack
shorthand: s
description: Name of the stack
required: false
- name: type
shorthand: t
description: Component types - abstract, enabled, or disabled
required: false
steps:
- >
{{ if .Flags.stack }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r .key
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r .key
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r .key
{{ else }}
atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ else }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else }}
atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ end }}

# Validation schemas (for validating atmos stacks and components)
schemas:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,60 +176,6 @@ commands:
- 'echo Environment: "{{ .ComponentConfig.vars.environment }}"'
- 'echo Stage: "{{ .ComponentConfig.vars.stage }}"'
- 'echo Dependencies: "{{ .ComponentConfig.deps }}"'
- name: list
description: Execute 'atmos list' commands
# subcommands
commands:
- name: stacks
description: |
List all Atmos stacks.
steps:
- >
atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
- name: components
description: |
List all Atmos components in all stacks or in a single stack.
Example usage:
atmos list components
atmos list components -s plat-ue2-dev
atmos list components --stack plat-uw2-prod
atmos list components -s plat-ue2-dev --type abstract
atmos list components -s plat-ue2-dev -t enabled
atmos list components -s plat-ue2-dev -t disabled
flags:
- name: stack
shorthand: s
description: Name of the stack
required: false
- name: type
shorthand: t
description: Component types - abstract, enabled, or disabled
required: false
steps:
- >
{{ if .Flags.stack }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r .key
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r .key
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --stack {{ .Flags.stack }} --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r .key
{{ else }}
atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ else }}
{{ if eq .Flags.type "enabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == true)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "disabled" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.vars.enabled == false)' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else if eq .Flags.type "abstract" }}
atmos describe stacks --format json | jq '.[].components.terraform | to_entries[] | select(.value.metadata.type == "abstract")' | jq -r '[.key]' | jq -s 'add' | jq 'unique | sort' | jq -r "values[]"
{{ else }}
atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
{{ end }}

# Validation schemas (for validating atmos stacks and components)
schemas:
Expand Down
31 changes: 0 additions & 31 deletions examples/tests/atmos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,37 +189,6 @@ commands:
- 'echo settings.config.is_prod: "{{ .ComponentConfig.settings.config.is_prod }}"'
- 'echo ATMOS_IS_PROD: "$ATMOS_IS_PROD"'

- name: list
description: Execute 'atmos list' commands
# subcommands
commands:
- name: stacks
description: |
List all Atmos stacks.
steps:
- >
atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
- name: components
description: |
List all Atmos components in all stacks or in a single stack.
Example usage:
atmos list components
atmos list components -s tenant1-ue1-dev
atmos list components --stack tenant2-uw2-prod
flags:
- name: stack
shorthand: s
description: Name of the stack
required: false
steps:
- >
{{ if .Flags.stack }}
atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ else }}
atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
- name: set-eks-cluster
description: |
Download 'kubeconfig' and set EKS cluster.
Expand Down
31 changes: 0 additions & 31 deletions examples/tests/rootfs/usr/local/etc/atmos/atmos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,37 +184,6 @@ commands:
- 'echo settings.config.is_prod: "{{ .ComponentConfig.settings.config.is_prod }}"'
- 'echo ATMOS_IS_PROD: "$ATMOS_IS_PROD"'

- name: list
description: Execute 'atmos list' commands
# subcommands
commands:
- name: stacks
description: |
List all Atmos stacks.
steps:
- >
atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
- name: components
description: |
List all Atmos components in all stacks or in a single stack.
Example usage:
atmos list components
atmos list components -s tenant1-ue1-dev
atmos list components --stack tenant2-uw2-prod
flags:
- name: stack
shorthand: s
description: Name of the stack
required: false
steps:
- >
{{ if .Flags.stack }}
atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ else }}
atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
{{ end }}
- name: set-eks-cluster
description: |
Download 'kubeconfig' and set EKS cluster.
Expand Down
Loading

0 comments on commit 3f1cad7

Please sign in to comment.