-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(influxd): add
print-config
subcommand to support automation
- Loading branch information
Showing
3 changed files
with
225 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package launcher | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
|
||
"github.com/influxdata/influxdb/v2/kit/cli" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
func NewInfluxdPrintConfigCommand(v *viper.Viper, influxdOpts []cli.Opt) *cobra.Command { | ||
|
||
var keyToPrint string | ||
printOpts := make([]cli.Opt, len(influxdOpts)+1) | ||
|
||
printOpts[0] = cli.Opt{ | ||
DestP: &keyToPrint, | ||
Flag: "key-name", | ||
Desc: "config key name; if set, only the resolved value of that key will be printed", | ||
} | ||
for i, opt := range influxdOpts { | ||
printOpts[i+1] = cli.Opt{ | ||
DestP: opt.DestP, | ||
Flag: opt.Flag, | ||
Hidden: true, | ||
} | ||
} | ||
|
||
cmd := &cobra.Command{ | ||
Use: "print-config", | ||
Short: "Print the full influxd config resolved from the current environment", | ||
Long: ` | ||
Print config (in YAML) that the influxd server would use if run with the current flags/env vars/config file. | ||
The order of precedence for config options are as follows (1 highest, 3 lowest): | ||
1. flags | ||
2. env vars | ||
3. config file | ||
A config file can be provided via the INFLUXD_CONFIG_PATH env var. If a file is | ||
not provided via an env var, influxd will look in the current directory for a | ||
config.{json|toml|yaml|yml} file. If one does not exist, then it will continue unchanged. | ||
See 'influxd -h' for the full list of config options supported by the server. | ||
`, | ||
RunE: func(cmd *cobra.Command, _ []string) error { | ||
var err error | ||
if keyToPrint == "" { | ||
err = printAllConfigRunE(printOpts, cmd.OutOrStdout()) | ||
} else { | ||
err = printOneConfigRunE(printOpts, keyToPrint, cmd.OutOrStdout()) | ||
} | ||
|
||
if err != nil { | ||
return fmt.Errorf("failed to print config: %w", err) | ||
} | ||
|
||
return nil | ||
}, | ||
Args: cobra.NoArgs, | ||
} | ||
cli.BindOptions(v, cmd, printOpts) | ||
|
||
return cmd | ||
} | ||
|
||
func printAllConfigRunE(configOpts []cli.Opt, out io.Writer) error { | ||
configMap := make(map[string]interface{}, len(configOpts)) | ||
|
||
for _, o := range configOpts { | ||
configMap[o.Flag] = o.DestP | ||
} | ||
|
||
return yaml.NewEncoder(out).Encode(configMap) | ||
} | ||
|
||
func printOneConfigRunE(configOpts []cli.Opt, key string, out io.Writer) error { | ||
for _, o := range configOpts { | ||
if o.Flag != key { | ||
continue | ||
} | ||
return yaml.NewEncoder(out).Encode(o.DestP) | ||
} | ||
|
||
return fmt.Errorf("key %q not found in config", key) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package launcher | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
|
||
"github.com/influxdata/influxdb/v2" | ||
"github.com/influxdata/influxdb/v2/kit/cli" | ||
"github.com/stretchr/testify/require" | ||
"go.uber.org/zap/zapcore" | ||
) | ||
|
||
// Pretend we've already used cobra/viper to write | ||
// values into these vars. | ||
var stringVar = "string-value" | ||
var intVar = 12344 | ||
var boolVar = false | ||
var floatVar = 987.654 | ||
var sliceVar = []string{"hello", "world"} | ||
var mapVar = map[string]string{"foo": "bar", "baz": "qux"} | ||
var levelVar = zapcore.InfoLevel | ||
var idVar, _ = influxdb.IDFromString("020f755c3c082000") | ||
|
||
var opts = []cli.Opt{ | ||
{ | ||
DestP: &stringVar, | ||
Flag: "string-var", | ||
}, | ||
{ | ||
DestP: &intVar, | ||
Flag: "int-var", | ||
}, | ||
{ | ||
DestP: &boolVar, | ||
Flag: "bool-var", | ||
}, | ||
{ | ||
DestP: &floatVar, | ||
Flag: "float-var", | ||
}, | ||
{ | ||
DestP: &sliceVar, | ||
Flag: "slice-var", | ||
}, | ||
{ | ||
DestP: &mapVar, | ||
Flag: "map-var", | ||
}, | ||
{ | ||
DestP: &levelVar, | ||
Flag: "level-var", | ||
}, | ||
{ | ||
DestP: &idVar, | ||
Flag: "id-var", | ||
}, | ||
} | ||
|
||
func Test_printAllConfig(t *testing.T) { | ||
var out bytes.Buffer | ||
require.NoError(t, printAllConfigRunE(opts, &out)) | ||
|
||
expected := `bool-var: false | ||
float-var: 987.654 | ||
id-var: 020f755c3c082000 | ||
int-var: 12344 | ||
level-var: info | ||
map-var: | ||
baz: qux | ||
foo: bar | ||
slice-var: | ||
- hello | ||
- world | ||
string-var: string-value | ||
` | ||
|
||
require.Equal(t, expected, out.String()) | ||
} | ||
|
||
func Test_printOneConfig(t *testing.T) { | ||
testCases := []struct { | ||
key string | ||
expected string | ||
}{ | ||
{ | ||
key: "bool-var", | ||
expected: "false", | ||
}, | ||
{ | ||
key: "float-var", | ||
expected: "987.654", | ||
}, | ||
{ | ||
key: "id-var", | ||
expected: "020f755c3c082000", | ||
}, | ||
{ | ||
key: "level-var", | ||
expected: "info", | ||
}, | ||
{ | ||
key: "map-var", | ||
expected: `baz: qux | ||
foo: bar`, | ||
}, | ||
{ | ||
key: "slice-var", | ||
expected: `- hello | ||
- world`, | ||
}, | ||
{ | ||
key: "string-var", | ||
expected: "string-value", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.key, func(t *testing.T) { | ||
var out bytes.Buffer | ||
require.NoError(t, printOneConfigRunE(opts, tc.key, &out)) | ||
require.Equal(t, tc.expected+"\n", out.String()) | ||
}) | ||
} | ||
|
||
t.Run("bad-key", func(t *testing.T) { | ||
var out bytes.Buffer | ||
require.Error(t, printOneConfigRunE(opts, "bad-key", &out)) | ||
require.Empty(t, out.String()) | ||
}) | ||
} |