Skip to content

Commit 602f8f3

Browse files
samtholiyaautofix-ci[bot]coderabbitai[bot]ostermanBenbentwo
authored
add pager for describe component (#1215)
* add pager to describe config command * add model test * [autofix.ci] apply automated fixes * update structure * update with unit test cases * [autofix.ci] apply automated fixes * remove unwanted interface * fix tests * updated describe config * implement status with help * [autofix.ci] apply automated fixes * error view added * Update pkg/pager/model.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix tests * fix lint * fix golangci-lint * updated pager variable * fix tests * fixed test cases * update the pager variable logic * updated the pager logic * updated test case * fix pager bool * add pager for describe component * fix test case * fix test cases * Update the docs * add pager to describe config command * add model test * [autofix.ci] apply automated fixes * update structure * update with unit test cases * remove unwanted interface * [autofix.ci] apply automated fixes * fix tests * updated describe config * implement status with help * error view added * [autofix.ci] apply automated fixes * fix tests * Update pkg/pager/model.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix lint * fix golangci-lint * updated pager variable * fix tests * fixed test cases * update the pager variable logic * updated the pager logic * updated test case * fix pager bool * unit test case for isPagerEnabled * fix error name * fix tests * checking error in runner * fix struct * fix tests * add tests * added tests * added test for cmd * added tests for print as json * revert changes to limit the pr contents * shift common code * fix command * fix test coverage scope * add more test cases * [autofix.ci] apply automated fixes * add more test cases --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]> Co-authored-by: Ben <[email protected]>
1 parent a55467b commit 602f8f3

23 files changed

+439
-103
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ testacc: get
6161

6262
testacc-cover: get
6363
@echo "Running tests with coverage"
64-
go test $(TEST) -v $(TESTARGS) -timeout 20m -coverprofile=coverage.out.tmp
64+
go test $(TEST) -v -coverpkg=./... $(TESTARGS) -timeout 20m -coverprofile=coverage.out.tmp
6565
cat coverage.out.tmp | grep -v "mock_" > coverage.out
6666

6767
# Run acceptance tests with coverage report

cmd/describe.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var describeCmd = &cobra.Command{
1515

1616
func init() {
1717
describeCmd.PersistentFlags().StringP("query", "q", "", "Query the results of an `atmos describe` command using `yq` expressions")
18-
describeCmd.PersistentFlags().String("pager", "true", "Disable the paging user experience")
18+
describeCmd.PersistentFlags().String("pager", "true", "Disable / Enable the paging user experience")
1919

2020
RootCmd.AddCommand(describeCmd)
2121
}

cmd/describe_component.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cmd
22

33
import (
4+
"errors"
5+
46
"github.com/spf13/cobra"
57

68
e "github.com/cloudposse/atmos/internal/exec"
@@ -13,22 +15,59 @@ var describeComponentCmd = &cobra.Command{
1315
Short: "Show configuration details for an Atmos component in a stack",
1416
Long: `Display the configuration details for a specific Atmos component within a designated Atmos stack, including its dependencies, settings, and overrides.`,
1517
FParseErrWhitelist: struct{ UnknownFlags bool }{UnknownFlags: false},
16-
Run: func(cmd *cobra.Command, args []string) {
18+
Args: cobra.ExactArgs(1),
19+
RunE: func(cmd *cobra.Command, args []string) error {
1720
// Check Atmos configuration
1821
checkAtmosConfig()
1922

20-
err := e.ExecuteDescribeComponentCmd(cmd, args)
23+
if len(args) != 1 {
24+
return errors.New("invalid arguments. The command requires one argument `component`")
25+
}
26+
27+
flags := cmd.Flags()
28+
29+
stack, err := flags.GetString("stack")
30+
checkFlagNotPresentError(err)
31+
format, err := flags.GetString("format")
32+
checkFlagNotPresentError(err)
33+
file, err := flags.GetString("file")
34+
checkFlagNotPresentError(err)
35+
processTemplates, err := flags.GetBool("process-templates")
36+
checkFlagNotPresentError(err)
37+
processYamlFunctions, err := flags.GetBool("process-functions")
38+
checkFlagNotPresentError(err)
39+
query, err := flags.GetString("query")
40+
checkFlagNotPresentError(err)
41+
skip, err := flags.GetStringSlice("skip")
42+
checkFlagNotPresentError(err)
43+
pager, err := flags.GetString("pager")
44+
checkFlagNotPresentError(err)
45+
46+
component := args[0]
47+
48+
err = e.NewDescribeComponentExec().ExecuteDescribeComponentCmd(e.DescribeComponentParams{
49+
Component: component,
50+
Stack: stack,
51+
ProcessTemplates: processTemplates,
52+
ProcessYamlFunctions: processYamlFunctions,
53+
Skip: skip,
54+
Query: query,
55+
Pager: pager,
56+
Format: format,
57+
File: file,
58+
})
2159
if err != nil {
2260
u.PrintErrorMarkdownAndExit("", err, "")
2361
}
62+
return nil
2463
},
2564
ValidArgsFunction: ComponentsArgCompletion,
2665
}
2766

2867
func init() {
2968
describeComponentCmd.DisableFlagParsing = false
3069
AddStackCompletion(describeComponentCmd)
31-
describeComponentCmd.PersistentFlags().StringP("format", "f", "yaml", "The output format (`yaml` is default)")
70+
describeComponentCmd.PersistentFlags().StringP("format", "f", "yaml", "The output format")
3271
describeComponentCmd.PersistentFlags().String("file", "", "Write the result to the file")
3372
describeComponentCmd.PersistentFlags().Bool("process-templates", true, "Enable/disable Go template processing in Atmos stack manifests when executing the command")
3473
describeComponentCmd.PersistentFlags().Bool("process-functions", true, "Enable/disable YAML functions processing in Atmos stack manifests when executing the command")
@@ -41,3 +80,11 @@ func init() {
4180

4281
describeCmd.AddCommand(describeComponentCmd)
4382
}
83+
84+
// checkFlagNotPresentError checks if the error is nil.
85+
// we prefer to panic because this is a developer error.
86+
func checkFlagNotPresentError(err error) {
87+
if err != nil {
88+
panic(err)
89+
}
90+
}

internal/exec/atlantis_generate_repo_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ specified in the ` + "`" + `integrations.atlantis.config_templates` + "`" + ` se
525525
return err
526526
}
527527
} else {
528-
err = u.PrintAsYAML(atlantisYaml)
528+
err = u.PrintAsYAML(&atmosConfig, atlantisYaml)
529529
if err != nil {
530530
return err
531531
}

internal/exec/atmos.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func ExecuteAtmosCmd() error {
108108
if err != nil {
109109
return err
110110
}
111-
err = u.PrintAsYAML(data)
111+
err = u.PrintAsYAML(&atmosConfig, data)
112112
if err != nil {
113113
return err
114114
}
@@ -120,7 +120,7 @@ func ExecuteAtmosCmd() error {
120120
if err != nil {
121121
return err
122122
}
123-
err = u.PrintAsYAML(data)
123+
err = u.PrintAsYAML(&atmosConfig, data)
124124
if err != nil {
125125
return err
126126
}

internal/exec/describe_affected.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ func parseDescribeAffectedCliArgs(cmd *cobra.Command, args []string) (DescribeAf
205205

206206
// ExecuteDescribeAffectedCmd executes `describe affected` command
207207
func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error {
208+
info, err := ProcessCommandLineArgs("", cmd, args, nil)
209+
if err != nil {
210+
return err
211+
}
212+
213+
atmosConfig, err := cfg.InitCliConfig(info, true)
214+
if err != nil {
215+
return err
216+
}
217+
208218
a, err := parseDescribeAffectedCliArgs(cmd, args)
209219
if err != nil {
210220
return err
@@ -271,7 +281,7 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error {
271281
if a.Query == "" {
272282
a.Logger.Trace("\nAffected components and stacks: \n")
273283

274-
err = printOrWriteToFile(a.Format, a.OutputFile, affected)
284+
err = printOrWriteToFile(&atmosConfig, a.Format, a.OutputFile, affected)
275285
if err != nil {
276286
return err
277287
}
@@ -314,7 +324,7 @@ func ExecuteDescribeAffectedCmd(cmd *cobra.Command, args []string) error {
314324
return err
315325
}
316326

317-
err = printOrWriteToFile(a.Format, a.OutputFile, res)
327+
err = printOrWriteToFile(&atmosConfig, a.Format, a.OutputFile, res)
318328
if err != nil {
319329
return err
320330
}

internal/exec/describe_component.go

Lines changed: 95 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,71 @@
11
package exec
22

33
import (
4-
"github.com/pkg/errors"
4+
log "github.com/charmbracelet/log"
55
"github.com/samber/lo"
6-
"github.com/spf13/cobra"
76

7+
"github.com/cloudposse/atmos/internal/tui/templates/term"
88
cfg "github.com/cloudposse/atmos/pkg/config"
9+
"github.com/cloudposse/atmos/pkg/pager"
910
"github.com/cloudposse/atmos/pkg/schema"
1011
u "github.com/cloudposse/atmos/pkg/utils"
1112
)
1213

13-
// ExecuteDescribeComponentCmd executes `describe component` command.
14-
func ExecuteDescribeComponentCmd(cmd *cobra.Command, args []string) error {
15-
if len(args) != 1 {
16-
return errors.New("invalid arguments. The command requires one argument `component`")
17-
}
18-
19-
atmosConfig, err := cfg.InitCliConfig(schema.ConfigAndStacksInfo{}, true)
20-
if err != nil {
21-
return err
22-
}
23-
24-
flags := cmd.Flags()
25-
26-
stack, err := flags.GetString("stack")
27-
if err != nil {
28-
return err
29-
}
30-
31-
format, err := flags.GetString("format")
32-
if err != nil {
33-
return err
34-
}
35-
36-
file, err := flags.GetString("file")
37-
if err != nil {
38-
return err
39-
}
40-
41-
processTemplates, err := flags.GetBool("process-templates")
42-
if err != nil {
43-
return err
44-
}
14+
type DescribeComponentParams struct {
15+
Component string
16+
Stack string
17+
ProcessTemplates bool
18+
ProcessYamlFunctions bool
19+
Skip []string
20+
Query string
21+
Pager string
22+
Format string
23+
File string
24+
}
4525

46-
processYamlFunctions, err := flags.GetBool("process-functions")
47-
if err != nil {
48-
return err
49-
}
26+
type DescribeComponentExec struct {
27+
pageCreator pager.PageCreator
28+
printOrWriteToFile func(atmosConfig *schema.AtmosConfiguration, format string, file string, data any) error
29+
IsTTYSupportForStdout func() bool
30+
initCliConfig func(configAndStacksInfo schema.ConfigAndStacksInfo, processStacks bool) (schema.AtmosConfiguration, error)
31+
executeDescribeComponent func(component string, stack string, processTemplates bool, processYamlFunctions bool, skip []string) (map[string]any, error)
32+
evaluateYqExpression func(atmosConfig *schema.AtmosConfiguration, data any, yq string) (any, error)
33+
}
5034

51-
query, err := flags.GetString("query")
52-
if err != nil {
53-
return err
35+
func NewDescribeComponentExec() *DescribeComponentExec {
36+
return &DescribeComponentExec{
37+
printOrWriteToFile: printOrWriteToFile,
38+
IsTTYSupportForStdout: term.IsTTYSupportForStdout,
39+
pageCreator: pager.New(),
40+
initCliConfig: cfg.InitCliConfig,
41+
executeDescribeComponent: ExecuteDescribeComponent,
42+
evaluateYqExpression: u.EvaluateYqExpression,
5443
}
44+
}
5545

56-
skip, err := flags.GetStringSlice("skip")
46+
func (d *DescribeComponentExec) ExecuteDescribeComponentCmd(describeComponentParams DescribeComponentParams) error {
47+
component := describeComponentParams.Component
48+
stack := describeComponentParams.Stack
49+
processTemplates := describeComponentParams.ProcessTemplates
50+
processYamlFunctions := describeComponentParams.ProcessYamlFunctions
51+
skip := describeComponentParams.Skip
52+
query := describeComponentParams.Query
53+
pager := describeComponentParams.Pager
54+
format := describeComponentParams.Format
55+
file := describeComponentParams.File
56+
57+
var err error
58+
var atmosConfig schema.AtmosConfiguration
59+
60+
atmosConfig, err = d.initCliConfig(schema.ConfigAndStacksInfo{
61+
ComponentFromArg: component,
62+
Stack: stack,
63+
}, true)
5764
if err != nil {
5865
return err
5966
}
6067

61-
component := args[0]
62-
63-
componentSection, err := ExecuteDescribeComponent(
68+
componentSection, err := d.executeDescribeComponent(
6469
component,
6570
stack,
6671
processTemplates,
@@ -72,24 +77,67 @@ func ExecuteDescribeComponentCmd(cmd *cobra.Command, args []string) error {
7277
}
7378

7479
var res any
80+
if pager != "" {
81+
atmosConfig.Settings.Terminal.Pager = pager
82+
}
7583

7684
if query != "" {
77-
res, err = u.EvaluateYqExpression(&atmosConfig, componentSection, query)
85+
res, err = d.evaluateYqExpression(&atmosConfig, componentSection, query)
7886
if err != nil {
7987
return err
8088
}
8189
} else {
8290
res = componentSection
8391
}
8492

85-
err = printOrWriteToFile(format, file, res)
93+
if atmosConfig.Settings.Terminal.IsPagerEnabled() {
94+
err = d.viewConfig(&atmosConfig, component, format, res)
95+
switch err.(type) {
96+
case DescribeConfigFormatError:
97+
return err
98+
case nil:
99+
return nil
100+
default:
101+
log.Debug("Failed to use pager")
102+
}
103+
}
104+
105+
err = d.printOrWriteToFile(&atmosConfig, format, file, res)
86106
if err != nil {
87107
return err
88108
}
89109

90110
return nil
91111
}
92112

113+
func (d *DescribeComponentExec) viewConfig(atmosConfig *schema.AtmosConfiguration, displayName string, format string, data any) error {
114+
if !d.IsTTYSupportForStdout() {
115+
return ErrTTYNotSupported
116+
}
117+
var content string
118+
var err error
119+
switch format {
120+
case "yaml":
121+
content, err = u.GetHighlightedYAML(atmosConfig, data)
122+
if err != nil {
123+
return err
124+
}
125+
case "json":
126+
content, err = u.GetHighlightedJSON(atmosConfig, data)
127+
if err != nil {
128+
return err
129+
}
130+
default:
131+
return DescribeConfigFormatError{
132+
format,
133+
}
134+
}
135+
if err := d.pageCreator.Run(displayName, content); err != nil {
136+
return err
137+
}
138+
return nil
139+
}
140+
93141
// ExecuteDescribeComponent describes component config
94142
func ExecuteDescribeComponent(
95143
component string,

0 commit comments

Comments
 (0)