Skip to content

Commit efd901a

Browse files
Allow users use a env vars or a config file instead of cli flags
1 parent 128781e commit efd901a

File tree

7 files changed

+511
-22
lines changed

7 files changed

+511
-22
lines changed

go.mod

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/openshift/client-go v0.0.0-20230120202327-72f107311084
1111
github.com/sirupsen/logrus v1.9.0
1212
github.com/spf13/cobra v1.6.0
13+
github.com/spf13/viper v1.15.0
1314
golang.org/x/mod v0.8.0
1415
k8s.io/api v0.26.1
1516
k8s.io/apimachinery v0.26.1
@@ -22,6 +23,7 @@ require (
2223
github.com/davecgh/go-spew v1.1.1 // indirect
2324
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
2425
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
26+
github.com/fsnotify/fsnotify v1.6.0 // indirect
2527
github.com/go-logr/logr v1.2.3 // indirect
2628
github.com/go-openapi/jsonpointer v0.19.6 // indirect
2729
github.com/go-openapi/jsonreference v0.20.2 // indirect
@@ -33,20 +35,27 @@ require (
3335
github.com/google/go-cmp v0.5.9 // indirect
3436
github.com/google/gofuzz v1.2.0 // indirect
3537
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
38+
github.com/hashicorp/hcl v1.0.0 // indirect
3639
github.com/imdario/mergo v0.3.13 // indirect
3740
github.com/inconshreveable/mousetrap v1.0.1 // indirect
3841
github.com/josharian/intern v1.0.0 // indirect
3942
github.com/json-iterator/go v1.1.12 // indirect
40-
github.com/kr/pretty v0.3.0 // indirect
43+
github.com/magiconair/properties v1.8.7 // indirect
4144
github.com/mailru/easyjson v0.7.7 // indirect
45+
github.com/mitchellh/mapstructure v1.5.0 // indirect
4246
github.com/moby/spdystream v0.2.0 // indirect
4347
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4448
github.com/modern-go/reflect2 v1.0.2 // indirect
4549
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
4650
github.com/openshift/api v0.0.0-20230120195050-6ba31fa438f2 // indirect
51+
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
4752
github.com/pkg/errors v0.9.1 // indirect
4853
github.com/rogpeppe/go-internal v1.8.0 // indirect
54+
github.com/spf13/afero v1.9.3 // indirect
55+
github.com/spf13/cast v1.5.0 // indirect
56+
github.com/spf13/jwalterweatherman v1.1.0 // indirect
4957
github.com/spf13/pflag v1.0.5 // indirect
58+
github.com/subosito/gotenv v1.4.2 // indirect
5059
golang.org/x/net v0.8.0 // indirect
5160
golang.org/x/oauth2 v0.5.0 // indirect
5261
golang.org/x/sys v0.6.0 // indirect
@@ -57,6 +66,7 @@ require (
5766
google.golang.org/appengine v1.6.7 // indirect
5867
google.golang.org/protobuf v1.28.1 // indirect
5968
gopkg.in/inf.v0 v0.9.1 // indirect
69+
gopkg.in/ini.v1 v1.67.0 // indirect
6070
gopkg.in/yaml.v2 v2.4.0 // indirect
6171
gopkg.in/yaml.v3 v3.0.1 // indirect
6272
k8s.io/klog/v2 v2.90.0 // indirect

go.sum

+331-2
Large diffs are not rendered by default.

pkg/cmd/collect.go

+72-13
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
log "github.com/sirupsen/logrus"
1515
"github.com/spf13/cobra"
16+
"github.com/spf13/viper"
1617

1718
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/collectors"
1819
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/runner"
@@ -40,19 +41,50 @@ var (
4041
keepDebugFiles bool
4142
)
4243

44+
type CollectionParams struct {
45+
KubeConfig string `mapstructure:"kubeconfig"`
46+
PTPInterface string `mapstructure:"ptp_interface"`
47+
OutputFile string `mapstructure:"output_file"`
48+
Duration string `mapstructure:"duration"`
49+
CollectorNames []string `mapstructure:"collectors"`
50+
PollInterval int `mapstructure:"poll_interval"`
51+
DevInfoAnnouceInterval int `mapstructure:"announce_interval"`
52+
UseAnalyserJSON bool `mapstructure:"use_analyser_format"`
53+
LogsOutputFile string `mapstructure:"logs_output"`
54+
IncludeLogTimestamps bool `mapstructure:"log_timestamps"`
55+
TempDir string `mapstructure:"tempdir"`
56+
KeepDebugFiles bool `mapstructure:"keep_debug_files"`
57+
}
58+
59+
func (p *CollectionParams) CheckForRequiredFields() error {
60+
missing := make([]string, 0)
61+
if p.KubeConfig == "" {
62+
missing = append(missing, "kubeconfig")
63+
}
64+
if p.PTPInterface == "" {
65+
missing = append(missing, "interface")
66+
}
67+
if len(missing) > 0 {
68+
return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missing, `", "`))
69+
}
70+
return nil
71+
}
72+
4373
// collectCmd represents the collect command
4474
var collectCmd = &cobra.Command{
4575
Use: "collect",
4676
Short: "Run the collector tool",
4777
Long: `Run the collector tool to gather data from your target cluster`,
4878
Run: func(cmd *cobra.Command, args []string) {
49-
collectionRunner := runner.NewCollectorRunner(collectorNames)
79+
runtimeConfig := &CollectionParams{}
80+
err := populateParams(cmd, runtimeConfig)
81+
utils.IfErrorExitOrPanic(err)
5082

51-
requestedDuration, err := time.ParseDuration(requestedDurationStr)
83+
requestedDuration, err := time.ParseDuration(runtimeConfig.Duration)
84+
utils.IfErrorExitOrPanic(err)
5285
if requestedDuration.Nanoseconds() < 0 {
5386
log.Panicf("Requested duration must be positive")
5487
}
55-
utils.IfErrorExitOrPanic(err)
5688

5789
for _, c := range collectorNames {
5890
if c == collectors.LogsCollectorName && logsOutputFile == "" {
@@ -78,18 +110,19 @@ var collectCmd = &cobra.Command{
78110
log.Fatal(err)
79111
}
80112

113+
collectionRunner := runner.NewCollectorRunner(runtimeConfig.CollectorNames)
81114
collectionRunner.Run(
82-
kubeConfig,
83-
outputFile,
115+
runtimeConfig.KubeConfig,
116+
runtimeConfig.OutputFile,
84117
requestedDuration,
85-
pollInterval,
86-
devInfoAnnouceInterval,
87-
ptpInterface,
88-
useAnalyserJSON,
89-
logsOutputFile,
90-
includeLogTimestamps,
91-
tempDir,
92-
keepDebugFiles,
118+
runtimeConfig.PollInterval,
119+
runtimeConfig.DevInfoAnnouceInterval,
120+
runtimeConfig.PTPInterface,
121+
runtimeConfig.UseAnalyserJSON,
122+
runtimeConfig.LogsOutputFile,
123+
runtimeConfig.IncludeLogTimestamps,
124+
runtimeConfig.TempDir,
125+
runtimeConfig.KeepDebugFiles,
93126
)
94127
},
95128
}
@@ -110,6 +143,9 @@ func init() { //nolint:funlen // Allow this to get a little long
110143
"A positive duration string sequence of decimal numbers and a unit suffix, such as \"300ms\", \"1.5h\" or \"2h45m\"."+
111144
" Valid time units are \"s\", \"m\", \"h\".",
112145
)
146+
err := viper.BindPFlag("duration", collectCmd.Flags().Lookup("duration"))
147+
utils.IfErrorExitOrPanic(err)
148+
113149
collectCmd.Flags().IntVarP(
114150
&pollInterval,
115151
"rate",
@@ -118,13 +154,23 @@ func init() { //nolint:funlen // Allow this to get a little long
118154
"Poll interval for querying the cluster. The value will be polled once every interval. "+
119155
"Using --rate 10 will cause the value to be polled once every 10 seconds",
120156
)
157+
err = viper.BindPFlag("poll_interval", collectCmd.Flags().Lookup("rate"))
158+
utils.IfErrorExitOrPanic(err)
159+
viper.RegisterAlias("poll_rate", "poll_interval")
160+
viper.RegisterAlias("rate", "poll_interval")
161+
121162
collectCmd.Flags().IntVarP(
122163
&devInfoAnnouceInterval,
123164
"announce",
124165
"a",
125166
defaultDevInfoInterval,
126167
"interval at which to emit the device info summary to the targeted output.",
127168
)
169+
err = viper.BindPFlag("announce_interval", collectCmd.Flags().Lookup("announce"))
170+
utils.IfErrorExitOrPanic(err)
171+
viper.RegisterAlias("announce_rate", "announce_interval")
172+
viper.RegisterAlias("announce", "announce_interval")
173+
128174
defaultCollectorNames := make([]string, 0)
129175
defaultCollectorNames = append(defaultCollectorNames, runner.All)
130176
collectCmd.Flags().StringSliceVarP(
@@ -140,19 +186,32 @@ func init() { //nolint:funlen // Allow this to get a little long
140186
strings.Join(runner.OptionalCollectorNames, ", "),
141187
),
142188
)
189+
err = viper.BindPFlag("collectors", collectCmd.Flags().Lookup("collector"))
190+
utils.IfErrorExitOrPanic(err)
191+
viper.RegisterAlias("collector", "collectors")
143192

144193
collectCmd.Flags().StringVarP(
145194
&logsOutputFile,
146195
"logs-output", "l", "",
147196
"Path to the logs output file. This is required when using the logs collector",
148197
)
198+
err = viper.BindPFlag("logs_output", collectCmd.Flags().Lookup("logs-output"))
199+
utils.IfErrorExitOrPanic(err)
200+
149201
collectCmd.Flags().BoolVar(
150202
&includeLogTimestamps,
151203
"log-timestamps", defaultIncludeLogTimestamps,
152204
"Specifies if collected logs should include timestamps or not. (default is false)",
153205
)
206+
err = viper.BindPFlag("log_timestamps", collectCmd.Flags().Lookup("log-timestamps"))
207+
utils.IfErrorExitOrPanic(err)
154208

155209
collectCmd.Flags().StringVarP(&tempDir, "tempdir", "t", defaultTempDir,
156210
"Directory for storing temp/debug files. Must exist.")
211+
err = viper.BindPFlag("tempdir", collectCmd.Flags().Lookup("tempdir"))
212+
utils.IfErrorExitOrPanic(err)
213+
157214
collectCmd.Flags().BoolVar(&keepDebugFiles, "keep", defaultKeepDebugFiles, "Keep debug files")
215+
err = viper.BindPFlag("keep_debug_files", collectCmd.Flags().Lookup("keep"))
216+
utils.IfErrorExitOrPanic(err)
158217
}

pkg/cmd/common.go

+30-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
package cmd
44

55
import (
6+
"fmt"
7+
"os"
8+
69
"github.com/spf13/cobra"
10+
"github.com/spf13/viper"
711

812
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils"
913
)
@@ -17,12 +21,15 @@ var (
1721

1822
func AddKubeconfigFlag(targetCmd *cobra.Command) {
1923
targetCmd.Flags().StringVarP(&kubeConfig, "kubeconfig", "k", "", "Path to the kubeconfig file")
20-
err := targetCmd.MarkFlagRequired("kubeconfig")
24+
err := viper.BindPFlag("kubeconfig", targetCmd.Flags().Lookup("kubeconfig"))
2125
utils.IfErrorExitOrPanic(err)
2226
}
2327

2428
func AddOutputFlag(targetCmd *cobra.Command) {
2529
targetCmd.Flags().StringVarP(&outputFile, "output", "o", "", "Path to the output file")
30+
err := viper.BindPFlag("output_file", targetCmd.Flags().Lookup("output"))
31+
utils.IfErrorExitOrPanic(err)
32+
viper.RegisterAlias("output", "output_file")
2633
}
2734

2835
func AddFormatFlag(targetCmd *cobra.Command) {
@@ -33,10 +40,31 @@ func AddFormatFlag(targetCmd *cobra.Command) {
3340
false,
3441
"Output in a format to be used by analysers from vse-sync-pp",
3542
)
43+
err := viper.BindPFlag("use_analyser_format", targetCmd.Flags().Lookup("use-analyser-format"))
44+
utils.IfErrorExitOrPanic(err)
3645
}
3746

3847
func AddInterfaceFlag(targetCmd *cobra.Command) {
3948
targetCmd.Flags().StringVarP(&ptpInterface, "interface", "i", "", "Name of the PTP interface")
40-
err := targetCmd.MarkFlagRequired("interface")
49+
err := viper.BindPFlag("ptp_interface", targetCmd.Flags().Lookup("interface"))
50+
utils.IfErrorExitOrPanic(err)
51+
viper.RegisterAlias("interface", "ptp_interface")
52+
}
53+
54+
type Params interface {
55+
CheckForRequiredFields() error
56+
}
57+
58+
func populateParams(cmd *cobra.Command, params Params) error {
59+
err := viper.Unmarshal(params)
4160
utils.IfErrorExitOrPanic(err)
61+
err = params.CheckForRequiredFields()
62+
if err != nil {
63+
cmd.PrintErrln(err.Error())
64+
err = cmd.Usage()
65+
utils.IfErrorExitOrPanic(err)
66+
os.Exit(int(utils.InvalidArgs))
67+
return fmt.Errorf("failed to populate params: %w", err)
68+
}
69+
return nil
4270
}

pkg/cmd/root.go

+34-3
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,41 @@ import (
77

88
log "github.com/sirupsen/logrus"
99
"github.com/spf13/cobra"
10+
"github.com/spf13/viper"
1011

1112
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/logging"
13+
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/utils"
1214
)
1315

16+
type RootParams struct {
17+
LogLevel string `mapstructure:"verbosity"`
18+
}
19+
20+
func (p *RootParams) CheckForRequiredFields() error {
21+
return nil
22+
}
23+
1424
var (
15-
logLevel string
25+
configFile string
26+
logLevel string
1627

1728
// rootCmd represents the base command when called without any subcommands
1829
rootCmd = &cobra.Command{
19-
Use: "vse-sync-testsuite",
30+
Use: "vse-sync-collection-tools",
2031
Short: "A monitoring tool for PTP related metrics",
2132
Long: `A monitoring tool for PTP related metrics.`,
2233
PersistentPreRun: func(cmd *cobra.Command, args []string) {
23-
logging.SetupLogging(logLevel, os.Stdout)
34+
if configFile != "" {
35+
log.Debugf("config: %v", configFile)
36+
viper.SetConfigFile(configFile)
37+
err := viper.ReadInConfig()
38+
utils.IfErrorExitOrPanic(err)
39+
}
40+
params := RootParams{}
41+
err := populateParams(cmd, &params)
42+
if err == nil {
43+
logging.SetupLogging(params.LogLevel, os.Stdout)
44+
}
2445
},
2546
}
2647
)
@@ -35,11 +56,21 @@ func Execute() {
3556
}
3657

3758
func init() {
59+
viper.AutomaticEnv()
60+
viper.SetEnvPrefix("COLLECTOR")
61+
configureFlags()
62+
}
63+
64+
func configureFlags() { //nolint:funlen // Allow this to get a little long
65+
rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "Path to config file")
3866
rootCmd.PersistentFlags().StringVarP(
3967
&logLevel,
4068
"verbosity",
4169
"v",
4270
log.WarnLevel.String(),
4371
"Log level (debug, info, warn, error, fatal, panic)",
4472
)
73+
err := viper.BindPFlag("verbosity", rootCmd.PersistentFlags().Lookup("verbosity"))
74+
utils.IfErrorExitOrPanic(err)
75+
viper.RegisterAlias("log_level", "verbosity")
4576
}

pkg/cmd/verifyEnv.go

+32-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
package cmd
44

55
import (
6+
"fmt"
7+
"strings"
8+
69
"github.com/spf13/cobra"
710

811
"github.com/redhat-partner-solutions/vse-sync-collection-tools/pkg/verify"
@@ -14,13 +17,41 @@ var envCmd = &cobra.Command{
1417
Long: `environment based actions`,
1518
}
1619

20+
type VerifyParams struct {
21+
KubeConfig string `mapstructure:"kubeconfig"`
22+
PTPInterface string `mapstructure:"ptp_interface"`
23+
UseAnalyserJSON bool `mapstructure:"use_analyser_format"`
24+
}
25+
26+
func (p *VerifyParams) CheckForRequiredFields() error {
27+
missing := make([]string, 0)
28+
if p.KubeConfig == "" {
29+
missing = append(missing, "kubeconfig")
30+
}
31+
if p.PTPInterface == "" {
32+
missing = append(missing, "interface")
33+
}
34+
if len(missing) > 0 {
35+
return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missing, `", "`))
36+
}
37+
return nil
38+
}
39+
1740
// verifyEnvCmd represents the verifyEnv command
1841
var verifyEnvCmd = &cobra.Command{
1942
Use: "verify",
2043
Short: "verify the environment is ready for collection",
2144
Long: `verify the environment is ready for collection`,
2245
Run: func(cmd *cobra.Command, args []string) {
23-
verify.Verify(ptpInterface, kubeConfig, useAnalyserJSON)
46+
runtimeConfig := &VerifyParams{}
47+
err := populateParams(cmd, runtimeConfig)
48+
if err == nil {
49+
verify.Verify(
50+
runtimeConfig.PTPInterface,
51+
runtimeConfig.KubeConfig,
52+
runtimeConfig.UseAnalyserJSON,
53+
)
54+
}
2455
},
2556
}
2657

0 commit comments

Comments
 (0)