k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/flags/flags.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package flags 18 19 import ( 20 "flag" 21 "fmt" 22 "os" 23 "strconv" 24 "strings" 25 "time" 26 27 "github.com/spf13/pflag" 28 "k8s.io/klog/v2" 29 ) 30 31 func init() { 32 pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) 33 klog.InitFlags(nil) 34 pflag.CommandLine.AddGoFlagSet(flag.CommandLine) 35 } 36 37 var flags []flagFunc 38 39 // StringVar creates string flag with given parameters. 40 func StringVar(s *string, flagName, defaultValue, description string) { 41 pflag.StringVar(s, flagName, defaultValue, description) 42 } 43 44 // IntVar creates int flag with given parameters. 45 func IntVar(i *int, flagName string, defaultValue int, description string) { 46 pflag.IntVar(i, flagName, defaultValue, description) 47 } 48 49 // BoolVar creates a bool flag with given parameters. 50 func BoolVar(b *bool, flagName string, defaultValue bool, description string) { 51 pflag.BoolVar(b, flagName, defaultValue, description) 52 } 53 54 // DurationVar creates a time.Duration flag with given parameters. 55 func DurationVar(d *time.Duration, flagName string, defaultValue time.Duration, description string) { 56 pflag.DurationVar(d, flagName, defaultValue, description) 57 } 58 59 // StringEnvVar creates string flag with given parameters. 60 // If flag is not provided, it will try to get env variable. 61 func StringEnvVar(s *string, flagName, envVariable, defaultValue, description string) { 62 stringFlag := &stringFlagFunc{ 63 valPtr: s, 64 initializeFunc: func() error { return parseEnvString(s, envVariable, defaultValue) }, 65 } 66 pflag.Var(stringFlag, flagName, description) 67 flags = append(flags, stringFlag) 68 } 69 70 // StringArrayVar creates string flag with given parameters. Flag can be used multiple times. 71 func StringArrayVar(s *[]string, flagName string, defaultValue []string, description string) { 72 pflag.StringArrayVar(s, flagName, defaultValue, description) 73 } 74 75 // StringSliceEnvVar creates a string slice flag with the given parameters. 76 // If the flag is not provided, it will try to get the env variable. 77 // Flag accepts multiple values separated by commas. 78 func StringSliceEnvVar(s *[]string, flagName, envVariable string, defaultValue []string, description string) { 79 stringSliceFlag := &stringSliceFlagFunc{ 80 valPtr: s, 81 initializeFunc: func() error { return parseEnvStringSlice(s, envVariable, defaultValue) }, 82 } 83 pflag.Var(stringSliceFlag, flagName, description) 84 flags = append(flags, stringSliceFlag) 85 } 86 87 // IntEnvVar creates int flag with given parameters. 88 // If flag is not provided, it will try to get env variable. 89 func IntEnvVar(i *int, flagName, envVariable string, defaultValue int, description string) { 90 intFlag := &intFlagFunc{ 91 valPtr: i, 92 initializeFunc: func() error { return parseEnvInt(i, envVariable, defaultValue) }, 93 } 94 pflag.Var(intFlag, flagName, description) 95 flags = append(flags, intFlag) 96 } 97 98 // BoolEnvVar creates bool flag with given parameters. 99 // If flag is not provided, it will try to get env variable. 100 func BoolEnvVar(b *bool, flagName, envVariable string, defaultValue bool, description string) { 101 boolFlag := &boolFlagFunc{ 102 valPtr: b, 103 initializeFunc: func() error { return parseEnvBool(b, envVariable, defaultValue) }, 104 } 105 // Set NoOptDefValue, to make --flag-name equivalent to --flag-name=true 106 pflag.CommandLine.VarPF(boolFlag, flagName, "", description).NoOptDefVal = "true" 107 flags = append(flags, boolFlag) 108 } 109 110 // DurationEnvVar creates time.Duration flag with given parameters. 111 // If flag is not provided, it will try to get env variable. 112 func DurationEnvVar(d *time.Duration, flagName, envVariable string, defaultValue time.Duration, description string) { 113 durationFlag := &durationFlagFunc{ 114 valPtr: d, 115 initializeFunc: func() error { return parseEnvDuration(d, envVariable, defaultValue) }, 116 } 117 pflag.Var(durationFlag, flagName, description) 118 flags = append(flags, durationFlag) 119 } 120 121 // Parse parses provided flags and env variables. 122 func Parse() error { 123 for i := range flags { 124 if err := flags[i].initialize(); err != nil { 125 return err 126 } 127 } 128 if err := pflag.CommandLine.Parse(os.Args[1:]); err != nil { 129 return err 130 } 131 return nil 132 } 133 134 // MarkDeprecated indicates that a flag is deprecated 135 func MarkDeprecated(name string, usageMessage string) error { 136 return pflag.CommandLine.MarkDeprecated(name, usageMessage) 137 } 138 139 func parseEnvString(s *string, envVariable, defaultValue string) error { 140 *s = defaultValue 141 if envVariable != "" { 142 if val, ok := os.LookupEnv(envVariable); ok { 143 *s = val 144 return nil 145 } 146 } 147 return nil 148 } 149 150 func parseEnvStringSlice(s *[]string, envVariable string, defaultValue []string) error { 151 *s = defaultValue 152 if envVariable != "" { 153 if val, ok := os.LookupEnv(envVariable); ok && val != "" { 154 *s = strings.Split(val, ",") 155 } 156 } 157 return nil 158 } 159 160 func parseEnvInt(i *int, envVariable string, defaultValue int) error { 161 *i = defaultValue 162 if envVariable != "" { 163 if val, ok := os.LookupEnv(envVariable); ok { 164 iVal, err := strconv.Atoi(val) 165 if err != nil { 166 return fmt.Errorf("parsing env variable %s failed", envVariable) 167 } 168 *i = iVal 169 return nil 170 } 171 } 172 return nil 173 } 174 175 func parseEnvBool(b *bool, envVariable string, defaultValue bool) error { 176 *b = defaultValue 177 if envVariable != "" { 178 if val, ok := os.LookupEnv(envVariable); ok { 179 bVal, err := strconv.ParseBool(val) 180 if err != nil { 181 return fmt.Errorf("parsing env variable %s failed", envVariable) 182 } 183 *b = bVal 184 return nil 185 } 186 } 187 return nil 188 } 189 190 func parseEnvDuration(d *time.Duration, envVariable string, defaultValue time.Duration) error { 191 *d = defaultValue 192 if envVariable != "" { 193 if val, ok := os.LookupEnv(envVariable); ok { 194 dVal, err := time.ParseDuration(val) 195 if err != nil { 196 return fmt.Errorf("parsing env variable %s failed", envVariable) 197 } 198 *d = dVal 199 return nil 200 } 201 } 202 return nil 203 }