package flags import ( "flag" "fmt" "os" "github.com/linkerd/linkerd2/pkg/version" "github.com/bombsimon/logrusr/v4" log "github.com/sirupsen/logrus" "github.com/spf13/pflag" "helm.sh/helm/v3/pkg/cli/values" klog "k8s.io/klog/v2" ) const ( // EnvOverrideNamespace is the environment variable used in the CLI to // overidde the control-plane's namespace EnvOverrideNamespace = "LINKERD_NAMESPACE" // EnvOverrideDockerRegistry is the environment variable used in the // CLI to override the docker images' registry in the control-plane // manifests EnvOverrideDockerRegistry = "LINKERD_DOCKER_REGISTRY" ) // ConfigureAndParse adds flags that are common to all go processes. This // func calls flag.Parse(), so it should be called after all other flags have // been configured. func ConfigureAndParse(cmd *flag.FlagSet, args []string) { logLevel := cmd.String("log-level", log.InfoLevel.String(), "log level, must be one of: panic, fatal, error, warn, info, debug, trace") logFormat := cmd.String("log-format", "plain", "log format, must be one of: plain, json") printVersion := cmd.Bool("version", false, "print version and exit") // We'll assume the args being passed in by calling functions have already // been validated and that parsing does not have errors. //nolint:errcheck cmd.Parse(args) log.SetFormatter(getFormatter(*logFormat)) klog.InitFlags(nil) klog.SetLogger(logrusr.New(log.StandardLogger())) setLogLevel(*logLevel) maybePrintVersionAndExit(*printVersion) } // AddTraceFlags adds the trace-collector flag // to the flagSet and returns their pointers for usage func AddTraceFlags(cmd *flag.FlagSet) *string { traceCollector := cmd.String("trace-collector", "", "Enables OC Tracing with the specified endpoint as collector") return traceCollector } func setLogLevel(logLevel string) { level, err := log.ParseLevel(logLevel) if err != nil { log.Fatalf("invalid log-level: %s", logLevel) } log.SetLevel(level) // Loosely based on k8s logging conventions, except for 'tracing' that we // bump to 10 (we can see in client-go source code that level is actually // used) and `debug` to 6 (given that at level 7 and higher auth tokens get // logged) // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md switch level { case log.PanicLevel: flag.Set("v", "0") case log.FatalLevel: flag.Set("v", "0") case log.ErrorLevel: flag.Set("v", "0") case log.WarnLevel: flag.Set("v", "0") case log.InfoLevel: flag.Set("v", "2") case log.DebugLevel: flag.Set("v", "6") case log.TraceLevel: flag.Set("v", "10") } } func maybePrintVersionAndExit(printVersion bool) { if printVersion { fmt.Println(version.Version) os.Exit(0) } log.Infof("running version %s", version.Version) } func getFormatter(format string) log.Formatter { switch format { case "json": return &log.JSONFormatter{} default: return &log.TextFormatter{FullTimestamp: true} } } // AddValueOptionsFlags adds flags used to override default values func AddValueOptionsFlags(f *pflag.FlagSet, v *values.Options) { f.StringSliceVarP(&v.ValueFiles, "values", "f", []string{}, "specify values in a YAML file or a URL (can specify multiple)") f.StringArrayVar(&v.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") f.StringArrayVar(&v.StringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") f.StringArrayVar(&v.FileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") }