Skip to content

Commit

Permalink
Add sources flag to CLI get command (#20785)
Browse files Browse the repository at this point in the history
* Add sources flag to CLI get command
  • Loading branch information
julesmcrt authored Nov 22, 2023
1 parent 7a05bb2 commit 7c02303
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 3 deletions.
24 changes: 22 additions & 2 deletions pkg/cli/subcommands/config/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
type cliParams struct {
GlobalParams

// source enables detailed information about each source and its value
source bool

// args are the positional command line args
args []string
}
Expand Down Expand Up @@ -91,6 +94,7 @@ func MakeCommand(globalParamsGetter func() GlobalParams) *cobra.Command {
RunE: oneShotRunE(getConfigValue),
}
cmd.AddCommand(getCmd)
getCmd.Flags().BoolVarP(&cliParams.source, "source", "s", false, "print every source and its value")

return cmd
}
Expand Down Expand Up @@ -186,12 +190,28 @@ func getConfigValue(log log.Component, config config.Component, cliParams *cliPa
return err
}

value, err := c.Get(cliParams.args[0])
resp, err := c.GetWithSources(cliParams.args[0])
if err != nil {
return err
}

fmt.Printf("%s is set to: %v\n", cliParams.args[0], value)
fmt.Printf("%s is set to: %v\n", cliParams.args[0], resp["value"])

if cliParams.source {
sourcesVal, ok := resp["sources_value"].([]interface{})
if !ok {
return fmt.Errorf("failed to cast sources_value to []map[interface{}]interface{}")
}

fmt.Printf("sources and their value:\n")
for _, sourceVal := range sourcesVal {
sourceVal, ok := sourceVal.(map[string]interface{})
if !ok {
return fmt.Errorf("failed to cast sourceVal to map[string]interface{}")
}
fmt.Printf(" %s: %v\n", sourceVal["Source"], sourceVal["Value"])
}
}

return nil
}
1 change: 1 addition & 0 deletions pkg/config/model/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Reader interface {
GetProxies() *Proxy

GetSource(key string) Source
GetAllSources(key string) []ValueWithSource

ConfigFileUsed() string

Expand Down
18 changes: 18 additions & 0 deletions pkg/config/model/viper.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const (
// sources list the known sources, following the order of hierarchy between them
var sources = []Source{SourceDefault, SourceUnknown, SourceFile, SourceEnvVar, SourceAgentRuntime, SourceRC, SourceCLI}

// ValueWithSource is a tuple for a source and a value, not necessarily the applied value in the main config
type ValueWithSource struct {
Source Source
Value interface{}
}

// String casts Source into a string
func (s Source) String() string {
// Safeguard: if we don't know the Source, we assume SourceDefault
Expand Down Expand Up @@ -211,6 +217,18 @@ func (c *safeConfig) Get(key string) interface{} {
return val
}

// GetAllSources returns the value of a key for each source
func (c *safeConfig) GetAllSources(key string) []ValueWithSource {
vals := make([]ValueWithSource, len(sources))
for i, source := range sources {
vals[i] = ValueWithSource{
Source: source,
Value: c.configSources[source].Get(key),
}
}
return vals
}

// GetString wraps Viper for concurrent access
func (c *safeConfig) GetString(key string) string {
c.RLock()
Expand Down
1 change: 1 addition & 0 deletions pkg/config/settings/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "github.com/spf13/cobra"
// Client is the interface for interacting with the runtime settings API
type Client interface {
Get(key string) (interface{}, error)
GetWithSources(key string) (map[string]interface{}, error)
Set(key string, value string) (bool, error)
List() (map[string]RuntimeSettingResponse, error)
FullConfig() (string, error)
Expand Down
29 changes: 29 additions & 0 deletions pkg/config/settings/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,35 @@ func (rc *runtimeSettingsHTTPClient) Get(key string) (interface{}, error) {
return nil, fmt.Errorf("unable to get value for this setting: %v", key)
}

func (rc *runtimeSettingsHTTPClient) GetWithSources(key string) (map[string]interface{}, error) {
r, err := util.DoGet(rc.c, fmt.Sprintf("%s/%s?sources=true", rc.baseURL, key), util.LeaveConnectionOpen)
if err != nil {
var errMap = make(map[string]string)
_ = json.Unmarshal(r, &errMap)
// If the error has been marshalled into a json object, check it and return it properly
if e, found := errMap["error"]; found {
return nil, fmt.Errorf("%s", e)
}
return nil, err
}

var setting = make(map[string]interface{})
err = json.Unmarshal(r, &setting)
if err != nil {
return nil, err
}

if _, found := setting["value"]; !found {
return nil, fmt.Errorf("unable to get value for this setting: %v", key)
}

if _, found := setting["sources_value"]; !found {
return nil, fmt.Errorf("unable to get sources value for this setting: %v", key)
}

return setting, nil
}

func (rc *runtimeSettingsHTTPClient) Set(key string, value string) (bool, error) {
settingsList, err := rc.List()
if err != nil {
Expand Down
10 changes: 9 additions & 1 deletion pkg/config/settings/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/gorilla/mux"
"gopkg.in/yaml.v2"

"github.com/DataDog/datadog-agent/pkg/config"
ddconfig "github.com/DataDog/datadog-agent/pkg/config"
"github.com/DataDog/datadog-agent/pkg/config/model"
"github.com/DataDog/datadog-agent/pkg/config/settings"
Expand All @@ -25,6 +26,7 @@ var Server = struct {
GetFullDatadogConfig func(...string) http.HandlerFunc
GetFullSystemProbeConfig func(...string) http.HandlerFunc
GetValue http.HandlerFunc
GetValueWithSources http.HandlerFunc
SetValue http.HandlerFunc
ListConfigurable http.HandlerFunc
}{
Expand Down Expand Up @@ -129,7 +131,13 @@ func getConfigValue(w http.ResponseWriter, r *http.Request) {
}
return
}
body, err := json.Marshal(map[string]interface{}{"value": val})

resp := map[string]interface{}{"value": val}
if r.URL.Query().Get("sources") == "true" {
resp["sources_value"] = config.Datadog.GetAllSources(setting)
}

body, err := json.Marshal(resp)
if err != nil {
log.Errorf("Unable to marshal runtime setting value response: %s", err)
body, _ := json.Marshal(map[string]string{"error": err.Error()})
Expand Down

0 comments on commit 7c02303

Please sign in to comment.