-
-
Notifications
You must be signed in to change notification settings - Fork 112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement: atmos list values #1036
base: main
Are you sure you want to change the base?
Changes from 21 commits
2e1e51d
547f984
917cdd0
72a8e76
b6b19b2
30e14d0
f3db126
54d8ad0
b03b3c2
cc9c8bf
9060a00
79e94f8
cfec6fb
df4c494
872d881
368d21d
6a3e02b
538d6b7
216e6cd
6d87e2c
befa005
f07cb4a
132dfce
52f11fb
ab3bde4
948a3c0
1ce3cf4
571d382
9b72518
f4779cc
7d92050
4e758fc
a2f790c
d0e24c3
53f83ab
e0ec172
a8af871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
e "github.com/cloudposse/atmos/internal/exec" | ||
"github.com/cloudposse/atmos/pkg/config" | ||
list "github.com/cloudposse/atmos/pkg/list" | ||
l "github.com/cloudposse/atmos/pkg/logger" | ||
"github.com/cloudposse/atmos/pkg/schema" | ||
"github.com/cloudposse/atmos/pkg/ui/theme" | ||
u "github.com/cloudposse/atmos/pkg/utils" | ||
) | ||
|
||
// listValuesCmd lists component values across stacks | ||
var listValuesCmd = &cobra.Command{ | ||
Use: "values [component]", | ||
Short: "List component values across stacks", | ||
Long: "List values for a component across all stacks where it is used", | ||
Example: "atmos list values vpc\n" + | ||
"atmos list values vpc --query .vars\n" + | ||
"atmos list values vpc --abstract\n" + | ||
"atmos list values vpc --max-columns 5\n" + | ||
"atmos list values vpc --format json\n" + | ||
"atmos list values vpc --format yaml\n" + | ||
"atmos list values vpc --format csv", | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
// Check Atmos configuration | ||
checkAtmosConfig() | ||
|
||
// Initialize logger from CLI config | ||
configAndStacksInfo := schema.ConfigAndStacksInfo{} | ||
atmosConfig, err := config.InitCliConfig(configAndStacksInfo, true) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error initializing CLI config: %v\n", err) | ||
return | ||
} | ||
osterman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
logger, err := l.NewLoggerFromCliConfig(atmosConfig) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error initializing logger: %v\n", err) | ||
return | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe we need to do this everywhere. And if we did, then we should have a function for it, so we don't duplicate this logic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
however we indeed don't need |
||
flags := cmd.Flags() | ||
|
||
queryFlag, err := flags.GetString("query") | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to get query flag: %v", err)) | ||
return | ||
} | ||
|
||
abstractFlag, err := flags.GetBool("abstract") | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to get abstract flag: %v", err)) | ||
return | ||
} | ||
|
||
maxColumnsFlag, err := flags.GetInt("max-columns") | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to get max-columns flag: %v", err)) | ||
return | ||
} | ||
|
||
formatFlag, err := flags.GetString("format") | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to get format flag: %v", err)) | ||
return | ||
} | ||
|
||
delimiterFlag, err := flags.GetString("delimiter") | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to get delimiter flag: %v", err)) | ||
return | ||
} | ||
|
||
// Set appropriate default delimiter based on format | ||
if formatFlag == list.FormatCSV && delimiterFlag == list.DefaultTSVDelimiter { | ||
delimiterFlag = list.DefaultCSVDelimiter | ||
} | ||
|
||
component := args[0] | ||
|
||
// Get all stacks | ||
stacksMap, err := e.ExecuteDescribeStacks(atmosConfig, "", nil, nil, nil, false, false, false, false, nil) | ||
if err != nil { | ||
logger.Error(fmt.Errorf("failed to describe stacks: %v", err)) | ||
return | ||
} | ||
|
||
output, err := list.FilterAndListValues(stacksMap, component, queryFlag, abstractFlag, maxColumnsFlag, formatFlag, delimiterFlag) | ||
if err != nil { | ||
// Check if this is a 'no values found' error | ||
if list.IsNoValuesFoundError(err) { | ||
logger.Error(err) | ||
} else { | ||
logger.Warning(fmt.Sprintf("Failed to filter and list values: %v", err)) | ||
} | ||
return | ||
} | ||
|
||
logger.Info(output) | ||
}, | ||
} | ||
|
||
// listVarsCmd is an alias for 'list values --query .vars' | ||
var listVarsCmd = &cobra.Command{ | ||
Use: "vars [component]", | ||
Short: "List component vars across stacks (alias for 'list values --query .vars')", | ||
Long: "List vars for a component across all stacks where it is used", | ||
Example: "atmos list vars vpc\n" + | ||
Cerebrovinny marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"atmos list vars vpc --abstract\n" + | ||
"atmos list vars vpc --max-columns 5\n" + | ||
"atmos list vars vpc --format json\n" + | ||
"atmos list vars vpc --format yaml\n" + | ||
"atmos list vars vpc --format csv", | ||
Args: cobra.ExactArgs(1), | ||
Run: func(cmd *cobra.Command, args []string) { | ||
// Set the query flag to .vars | ||
if err := cmd.Flags().Set("query", ".vars"); err != nil { | ||
u.PrintMessageInColor(fmt.Sprintf("Error setting query flag: %v", err), theme.Colors.Error) | ||
return | ||
} | ||
// Run the values command | ||
listValuesCmd.Run(cmd, args) | ||
}, | ||
} | ||
|
||
func init() { | ||
// Flags for both commands | ||
commonFlags := func(cmd *cobra.Command) { | ||
cmd.PersistentFlags().String("query", "", "JMESPath query to filter values") | ||
cmd.PersistentFlags().Bool("abstract", false, "Include abstract components") | ||
cmd.PersistentFlags().Int("max-columns", 10, "Maximum number of columns to display") | ||
cmd.PersistentFlags().String("format", "", "Output format (table, json, yaml, csv, tsv)") | ||
cmd.PersistentFlags().String("delimiter", "\t", "Delimiter for csv/tsv output (default: tab for tsv, comma for csv)") | ||
} | ||
|
||
commonFlags(listValuesCmd) | ||
commonFlags(listVarsCmd) | ||
|
||
listCmd.AddCommand(listValuesCmd) | ||
listCmd.AddCommand(listVarsCmd) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
– List component values across stacks | ||
|
||
``` | ||
$ atmos list values <component> # List all values | ||
$ atmos list values <component> --query .vars # List only variables | ||
$ atmos list values <component> --abstract # Include abstract components | ||
$ atmos list values <component> --format json # Output in JSON format | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
– List component variables across stacks | ||
|
||
``` | ||
$ atmos list vars <component> # List all variables | ||
$ atmos list vars <component> --abstract # Include abstract components | ||
$ atmos list vars <component> --format json # Output in JSON format | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package list | ||
|
||
import "fmt" | ||
|
||
// ErrNoValuesFound is returned when no values are found for a component | ||
type ErrNoValuesFound struct { | ||
Component string | ||
} | ||
|
||
func (e *ErrNoValuesFound) Error() string { | ||
return fmt.Sprintf("no values found for component '%s'", e.Component) | ||
} | ||
|
||
// IsNoValuesFoundError checks if an error is a NoValuesFound error | ||
func IsNoValuesFoundError(err error) bool { | ||
_, ok := err.(*ErrNoValuesFound) | ||
return ok | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to markdown file and embed with properly annotated examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so are we going to stop using it even for cobra cli only?