diff --git a/cmd/grr/config.go b/cmd/grr/config.go index a1a9cf24..1d254c19 100644 --- a/cmd/grr/config.go +++ b/cmd/grr/config.go @@ -6,8 +6,24 @@ import ( "github.com/go-clix/cli" "github.com/grafana/grizzly/pkg/config" "github.com/grafana/grizzly/pkg/grizzly" + "github.com/spf13/viper" ) +func configPathCmd() *cli.Command { + cmd := &cli.Command{ + Use: "path", + Short: "Print the path to the configuration file", + Args: cli.ArgsExact(0), + } + var opts grizzly.LoggingOpts + + cmd.Run = func(cmd *cli.Command, args []string) error { + fmt.Println(viper.ConfigFileUsed()) + return nil + } + return initialiseLogging(cmd, &opts) +} + func configImportCmd() *cli.Command { cmd := &cli.Command{ Use: "import configuration", @@ -69,6 +85,31 @@ func getContextsCmd() *cli.Command { return initialiseLogging(cmd, &opts) } +func getConfigCmd() *cli.Command { + cmd := &cli.Command{ + Use: "get [path]", + Short: "get the whole configuration for a context or a specific attribute of the configuration", + Args: cli.ArgsRange(0, 1), + } + var opts grizzly.LoggingOpts + var output string + cmd.Flags().StringVarP(&output, "output", "o", "yaml", "Output format") + + cmd.Run = func(cmd *cli.Command, args []string) error { + path := "" + if len(args) > 0 { + path = args[0] + } + val, err := config.Get(path, output) + if err != nil { + return err + } + fmt.Println(val) + return nil + } + return initialiseLogging(cmd, &opts) +} + func setCmd() *cli.Command { cmd := &cli.Command{ Use: "set configuration value", diff --git a/cmd/grr/workflow.go b/cmd/grr/workflow.go index e7d220e5..f6b7696a 100644 --- a/cmd/grr/workflow.go +++ b/cmd/grr/workflow.go @@ -272,10 +272,12 @@ func configCmd() *cli.Command { Short: "Show, select or configure configuration", Args: cli.ArgsExact(0), } + cmd.AddCommand(configPathCmd()) cmd.AddCommand(currentContextCmd()) cmd.AddCommand(useContextCmd()) cmd.AddCommand(getContextsCmd()) cmd.AddCommand(configImportCmd()) + cmd.AddCommand(getConfigCmd()) cmd.AddCommand(setCmd()) cmd.AddCommand(createContextCmd()) return cmd diff --git a/integration/context_test.go b/integration/context_test.go index a4fa6267..1c27d648 100644 --- a/integration/context_test.go +++ b/integration/context_test.go @@ -1,15 +1,19 @@ package integration_test import ( + "path/filepath" "testing" + + "github.com/stretchr/testify/require" ) func TestContexts(t *testing.T) { - setupContexts(t, "testdata/contexts") + dir := "testdata/contexts" + setupContexts(t, dir) t.Run("Get contexts - success", func(t *testing.T) { runTest(t, GrizzlyTest{ - TestDir: "testdata/contexts", + TestDir: dir, Commands: []Command{ { Command: "config get-contexts", @@ -19,4 +23,41 @@ func TestContexts(t *testing.T) { }, }) }) + + absConfigPath, err := filepath.Abs("testdata/contexts/settings.yaml") + require.NoError(t, err) + t.Run("Find config path", func(t *testing.T) { + runTest(t, GrizzlyTest{ + TestDir: dir, + Commands: []Command{ + { + Command: "config path", + ExpectedOutput: absConfigPath, + }, + }, + }) + }) + + t.Run("Get context config", func(t *testing.T) { + runTest(t, GrizzlyTest{ + TestDir: dir, + Commands: []Command{ + // Whole config + { + Command: "config get", + ExpectedOutputFile: "get-context-val.yml", + }, + // Whole config JSON + { + Command: "config get -o json", + ExpectedOutputFile: "get-context-val.json", + }, + // Specific key + { + Command: "config get grafana.url", + ExpectedOutput: "http://localhost:3001", + }, + }, + }) + }) } diff --git a/integration/testdata/contexts/get-context-val.json b/integration/testdata/contexts/get-context-val.json new file mode 100644 index 00000000..8896f587 --- /dev/null +++ b/integration/testdata/contexts/get-context-val.json @@ -0,0 +1,6 @@ +{ + "grafana": { + "url": "http://localhost:3001" + }, + "name": "default" +} diff --git a/integration/testdata/contexts/get-context-val.yml b/integration/testdata/contexts/get-context-val.yml new file mode 100644 index 00000000..c51b664a --- /dev/null +++ b/integration/testdata/contexts/get-context-val.yml @@ -0,0 +1,3 @@ +grafana: + url: http://localhost:3001 +name: default diff --git a/integration/utils_test.go b/integration/utils_test.go index 4016e5d7..d058bb87 100644 --- a/integration/utils_test.go +++ b/integration/utils_test.go @@ -54,7 +54,7 @@ func runTest(t *testing.T, test GrizzlyTest) { command.ExpectedOutput = string(bytes) } if command.ExpectedOutput != "" { - require.Equal(t, command.ExpectedOutput, stdout) + require.Equal(t, strings.TrimSpace(command.ExpectedOutput), strings.TrimSpace(stdout)) } if command.ExpectedOutputContains != "" { require.Contains(t, stdout, command.ExpectedOutputContains) diff --git a/pkg/config/config.go b/pkg/config/config.go index 7ec070ba..838f4340 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,14 +1,15 @@ package config import ( + "encoding/json" "fmt" "os" - "path/filepath" "sort" "strings" "github.com/kirsle/configdir" "github.com/spf13/viper" + "gopkg.in/yaml.v3" ) const ( @@ -83,17 +84,6 @@ func Import() error { return err } -func configPath() (string, error) { - configPath := configdir.LocalConfig("grizzly") - err := configdir.MakePath(configPath) - if err != nil { - return "", err - } - - configFile := filepath.Join(configPath, "settings.yaml") - return configFile, nil -} - func NewConfig() { viper.Set("apiVersion", "v1alpha1") viper.Set(CURRENT_CONTEXT, "default") @@ -165,6 +155,27 @@ var acceptableKeys = map[string]string{ "only-spec": "bool", } +func Get(path, outputFormat string) (string, error) { + ctx := viper.GetString(CURRENT_CONTEXT) + fullPath := fmt.Sprintf("contexts.%s", ctx) + if path != "" { + fullPath = fmt.Sprintf("%s.%s", fullPath, path) + } + val := viper.Get(fullPath) + if val == nil { + return "", fmt.Errorf("key not found: %s", path) + } + switch outputFormat { + case "yaml": + res, err := yaml.Marshal(val) + return string(res), err + case "json": + res, err := json.MarshalIndent(val, "", " ") + return string(res), err + } + return "", fmt.Errorf("unknown output format: %s", outputFormat) +} + func Set(path string, value string) error { for key, typ := range acceptableKeys { if path == key { @@ -198,10 +209,7 @@ func Write() error { err := viper.WriteConfig() if err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { - configpath, err := configPath() - if err != nil { - return err - } + configpath := viper.ConfigFileUsed() return viper.WriteConfigAs(configpath) } }