github.com/kristofferahl/go-centry@v1.5.0/cmd/centry/options.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/kristofferahl/go-centry/internal/pkg/cmd" 8 "github.com/kristofferahl/go-centry/internal/pkg/config" 9 "github.com/kristofferahl/go-centry/internal/pkg/shell" 10 "github.com/sirupsen/logrus" 11 "github.com/urfave/cli/v2" 12 ) 13 14 func configureDefaultOptions() { 15 cli.HelpFlag = &cli.BoolFlag{ 16 Name: "help", 17 Aliases: []string{"h"}, 18 Usage: "Show help", 19 } 20 cli.VersionFlag = &cli.BoolFlag{ 21 Name: "version", 22 Aliases: []string{"v"}, 23 Usage: "Print the version", 24 } 25 } 26 27 func createGlobalOptions(runtime *Runtime) *cmd.OptionsSet { 28 context := runtime.context 29 manifest := context.manifest 30 31 // Add global options 32 options := cmd.NewOptionsSet("Global") 33 34 options.Add(&cmd.Option{ 35 Type: cmd.StringOption, 36 Name: "centry-config-log-level", 37 Description: "Overrides the log level", 38 Default: manifest.Config.Log.Level, 39 Hidden: manifest.Config.HideInternalOptions, 40 Internal: true, 41 }) 42 options.Add(&cmd.Option{ 43 Type: cmd.BoolOption, 44 Name: "centry-quiet", 45 Description: "Disables logging", 46 Default: false, 47 Hidden: manifest.Config.HideInternalOptions, 48 Internal: true, 49 }) 50 51 // Adding global options specified by the manifest 52 for _, o := range manifest.Options { 53 o := o 54 55 if context.optionEnabledFunc != nil && context.optionEnabledFunc(o) == false { 56 continue 57 } 58 59 err := options.Add(&cmd.Option{ 60 Type: o.Type, 61 Name: o.Name, 62 Short: o.Short, 63 Description: o.Description, 64 EnvName: o.EnvName, 65 Values: mapOptionValuesToCmdOptionValues(o), 66 Default: o.Default, 67 Required: o.Required, 68 Hidden: o.Hidden, 69 }) 70 71 if err != nil { 72 runtime.events = append(runtime.events, fmt.Sprintf("failed to register global option \"%s\", error: %v", o.Name, err)) 73 continue 74 } 75 76 runtime.events = append(runtime.events, fmt.Sprintf("registered global option \"%s\"", o.Name)) 77 } 78 79 return options 80 } 81 82 func optionsSetToFlags(options *cmd.OptionsSet) []cli.Flag { 83 flags := make([]cli.Flag, 0) 84 85 for _, o := range options.Sorted() { 86 short := []string{o.Short} 87 if o.Short == "" { 88 short = nil 89 } 90 91 switch o.Type { 92 case cmd.SelectOption: 93 def := false 94 if o.Default != nil { 95 def = o.Default.(bool) 96 } 97 flags = append(flags, &cli.BoolFlag{ 98 Name: o.Name, 99 Aliases: short, 100 Usage: o.Description, 101 Value: def, 102 Required: false, 103 Hidden: o.Hidden, 104 }) 105 case cmd.SelectOptionV2: 106 def := false 107 if o.Default != nil { 108 def = o.Default.(bool) 109 } 110 for _, v := range o.Values { 111 short := []string{v.Short} 112 if v.Short == "" { 113 short = nil 114 } 115 flags = append(flags, &SelectOptionFlag{ 116 BoolFlag: cli.BoolFlag{ 117 Name: v.Name, 118 Aliases: short, 119 Usage: o.Description, 120 Value: def, 121 Required: false, 122 Hidden: o.Hidden, 123 }, 124 GroupName: o.Name, 125 GroupRequired: o.Required, 126 Values: o.Values, 127 }) 128 } 129 case cmd.IntegerOption: 130 def := 0 131 if o.Default != nil { 132 def = o.Default.(int) 133 } 134 flags = append(flags, &cli.IntFlag{ 135 Name: o.Name, 136 Aliases: short, 137 Usage: o.Description, 138 Value: def, 139 Required: o.Required, 140 Hidden: o.Hidden, 141 }) 142 case cmd.BoolOption: 143 def := false 144 if o.Default != nil { 145 def = o.Default.(bool) 146 } 147 flags = append(flags, &cli.BoolFlag{ 148 Name: o.Name, 149 Aliases: short, 150 Usage: o.Description, 151 Value: def, 152 Required: o.Required, 153 Hidden: o.Hidden, 154 }) 155 case cmd.StringOption: 156 def := "" 157 if o.Default != nil { 158 def = o.Default.(string) 159 } 160 flags = append(flags, &cli.StringFlag{ 161 Name: o.Name, 162 Aliases: short, 163 Usage: o.Description, 164 Value: def, 165 Required: o.Required, 166 Hidden: o.Hidden, 167 }) 168 default: 169 panic(fmt.Sprintf("option type \"%s\" not implemented", o.Type)) 170 } 171 } 172 173 return flags 174 } 175 176 func optionsSetToEnvVars(c *cli.Context, set *cmd.OptionsSet, prefix string) []shell.EnvironmentVariable { 177 envVars := make([]shell.EnvironmentVariable, 0) 178 for _, o := range set.Sorted() { 179 o := o 180 181 envName := o.EnvName 182 if envName == "" { 183 envName = o.Name 184 } 185 envName = strings.Replace(strings.ToUpper(envName), ".", "_", -1) 186 envName = strings.Replace(strings.ToUpper(envName), "-", "_", -1) 187 188 if prefix != "" && o.Internal == false { 189 envName = prefix + envName 190 } 191 192 value := c.String(o.Name) 193 194 switch o.Type { 195 case cmd.StringOption: 196 envVars = append(envVars, shell.EnvironmentVariable{ 197 Name: envName, 198 Value: value, 199 Type: shell.EnvironmentVariableTypeString, 200 }) 201 case cmd.BoolOption: 202 envVars = append(envVars, shell.EnvironmentVariable{ 203 Name: envName, 204 Value: value, 205 Type: shell.EnvironmentVariableTypeBool, 206 }) 207 case cmd.IntegerOption: 208 envVars = append(envVars, shell.EnvironmentVariable{ 209 Name: envName, 210 Value: value, 211 Type: shell.EnvironmentVariableTypeInteger, 212 }) 213 case cmd.SelectOption: 214 if value == "true" { 215 envVars = append(envVars, shell.EnvironmentVariable{ 216 Name: envName, 217 Value: o.Name, 218 Type: shell.EnvironmentVariableTypeString, 219 }) 220 } 221 case cmd.SelectOptionV2: 222 value := "" 223 for _, v := range o.Values { 224 ov := c.String(v.Name) 225 if ov == "true" { 226 value = v.ResolveValue() 227 break 228 } 229 } 230 231 if value != "" { 232 envVars = append(envVars, shell.EnvironmentVariable{ 233 Name: envName, 234 Value: value, 235 Type: shell.EnvironmentVariableTypeString, 236 }) 237 } 238 default: 239 panic(fmt.Sprintf("option type \"%s\" not implemented", o.Type)) 240 } 241 } 242 243 return shell.SortEnvironmentVariables(envVars) 244 } 245 246 func mapOptionValuesToCmdOptionValues(o config.Option) []cmd.OptionValue { 247 values := []cmd.OptionValue{} 248 for _, v := range o.Values { 249 values = append(values, cmd.OptionValue{ 250 Name: v.Name, 251 Short: v.Short, 252 Value: v.Value, 253 }) 254 } 255 return values 256 } 257 258 func validateOptionsSet(c *cli.Context, set *cmd.OptionsSet, cmdName string, level string, log *logrus.Entry) error { 259 selectOptions := make(map[string][]string) 260 selectOptionRequired := make(map[string]bool) 261 selectOptionSelectedValues := make(map[string][]string) 262 263 for _, o := range set.Sorted() { 264 o := o 265 266 switch o.Type { 267 case cmd.SelectOption: 268 group := o.EnvName 269 selectOptions[group] = append(selectOptions[group], o.Name) 270 if o.Required { 271 selectOptionRequired[group] = true 272 } 273 v := c.String(o.Name) 274 log.Debugf("found select option %s (group=%s value=%v required=%v)\n", o.Name, group, v, o.Required) 275 if v == "true" { 276 selectOptionSelectedValues[group] = append(selectOptionSelectedValues[group], o.Name) 277 } 278 case cmd.SelectOptionV2: 279 group := o.Name 280 if o.Required { 281 selectOptionRequired[group] = true 282 } 283 for _, ov := range o.Values { 284 selectOptions[group] = append(selectOptions[group], ov.Name) 285 v := c.String(ov.Name) 286 log.Debugf("found select option %s (group=%s value=%v required=%v)\n", ov.Name, group, v, o.Required) 287 if v == "true" { 288 selectOptionSelectedValues[group] = append(selectOptionSelectedValues[group], ov.Name) 289 } 290 } 291 } 292 } 293 294 for group := range selectOptions { 295 if selectOptionRequired[group] { 296 optionValues, ok := selectOptionSelectedValues[group] 297 if ok && optionValues[0] != "" { 298 log.Debugf("select option group %s was set by option %s", group, optionValues[0]) 299 } else { 300 cli.ShowCommandHelp(c, cmdName) 301 return fmt.Errorf("Required %s flag missing for select option group \"%s\" (one of \" %s \" must be provided)\n", level, group, strings.Join(selectOptions[group], " | ")) 302 } 303 } else { 304 log.Debugf("select option group %s does not require a value", group) 305 } 306 307 if optionValues, ok := selectOptionSelectedValues[group]; ok && len(optionValues) > 1 { 308 return fmt.Errorf("%s flag specified multiple times for select option group \"%s\" (one of \" %s \" must be provided)\n", level, group, strings.Join(selectOptions[group], " | ")) 309 } 310 } 311 return nil 312 }