vitess.io/vitess@v0.16.2/go/cmd/vtorc/main.go (about) 1 /* 2 Copyright 2014 Outbrain Inc. 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 main 18 19 import ( 20 "strings" 21 22 _ "github.com/go-sql-driver/mysql" 23 "github.com/spf13/pflag" 24 _ "modernc.org/sqlite" 25 26 "vitess.io/vitess/go/acl" 27 "vitess.io/vitess/go/vt/log" 28 "vitess.io/vitess/go/vt/servenv" 29 "vitess.io/vitess/go/vt/vtorc/config" 30 "vitess.io/vitess/go/vt/vtorc/inst" 31 "vitess.io/vitess/go/vt/vtorc/logic" 32 "vitess.io/vitess/go/vt/vtorc/server" 33 ) 34 35 // transformArgsForPflag turns a slice of raw args passed on the command line, 36 // possibly incompatible with pflag (because the user is expecting stdlib flag 37 // parsing behavior) and transforms them into the arguments that should have 38 // been passed to conform to pflag parsing behavior. 39 // 40 // the primary function is to catch any cases where the user specified a longopt 41 // with only a single hyphen (e.g. `-myflag`) and correct it to be 42 // double-hyphenated. 43 // 44 // note that this transformation does _not_ actually validate the arguments; for 45 // example if the user specifies `--myflag`, but the FlagSet has no such flag 46 // defined, that will still appear in the returned result and will (correctly) 47 // cause a parse error later on in `main`, at which point the CLI usage will 48 // be printed. 49 // 50 // note also that this transformation is incomplete. pflag allows interspersing 51 // of flag and positional arguments, whereas stdlib flag does not. however, for 52 // vtorc specifically, with the exception of `vtorc help <topic>`, the CLI only 53 // consumes flag arguments (in other words, there are no supported subcommands), 54 // so this is a non-issue, and is not implemented here in order to make this 55 // function a bit simpler. 56 func transformArgsForPflag(fs *pflag.FlagSet, args []string) (result []string) { 57 for i, arg := range args { 58 switch { 59 case arg == "--": 60 // pflag stops parsing at `--`, so we're done transforming the CLI 61 // arguments. Just append everything remaining and be done. 62 result = append(result, args[i:]...) 63 return result 64 case strings.HasPrefix(arg, "--"): 65 // Long-hand flag. Append it and continue. 66 result = append(result, arg) 67 case strings.HasPrefix(arg, "-"): 68 // Most complex case. This is either: 69 // 1. A legacy long-hand flag that needs a double-dash (e.g. `-myflag` => `--myflag`). 70 // 2. One _or more_ pflag shortopts all shoved together (think `rm -rf` as `rm -r -f`). 71 // 72 // In the latter case, we don't need to do any transformations, but 73 // in the former, we do. 74 name := strings.SplitN(arg[1:], "=", 2)[0] // discard any potential value (`-myflag` and `-myflag=10` both have the name of `myflag`) 75 if fs.Lookup(name) != nil || name == "help" { 76 // Case 1: We have a long opt with this name, so we need to 77 // prepend an additional hyphen. 78 result = append(result, "-"+arg) 79 } else { 80 // Case 2: No transformation needed. 81 result = append(result, arg) 82 } 83 default: 84 // Just a flag argument. Nothing to transform. 85 result = append(result, arg) 86 } 87 } 88 89 return result 90 } 91 92 // main is the application's entry point. It will spawn an HTTP interface. 93 func main() { 94 servenv.RegisterDefaultFlags() 95 servenv.RegisterFlags() 96 97 var configFile string 98 servenv.OnParseFor("vtorc", func(fs *pflag.FlagSet) { 99 logic.RegisterFlags(fs) 100 server.RegisterFlags(fs) 101 config.RegisterFlags(fs) 102 acl.RegisterFlags(fs) 103 104 fs.StringVar(&configFile, "config", "", "config file name") 105 }) 106 servenv.ParseFlags("vtorc") 107 config.UpdateConfigValuesFromFlags() 108 109 log.Info("starting vtorc") 110 if len(configFile) > 0 { 111 config.ForceRead(configFile) 112 } else { 113 config.Read("/etc/vtorc.conf.json", "conf/vtorc.conf.json", "vtorc.conf.json") 114 } 115 if config.Config.AuditToSyslog { 116 inst.EnableAuditSyslog() 117 } 118 config.MarkConfigurationLoaded() 119 120 // Log final config values to debug if something goes wrong. 121 config.LogConfigValues() 122 server.StartVTOrcDiscovery() 123 124 server.RegisterVTOrcAPIEndpoints() 125 servenv.OnRun(func() { 126 addStatusParts() 127 }) 128 129 // For backward compatability, we require that VTOrc functions even when the --port flag is not provided. 130 // In this case, it should function like before but without the servenv pages. 131 // Therefore, currently we don't check for the --port flag to be necessary, but release 16+ that check 132 // can be added to always have the serenv page running in VTOrc. 133 servenv.RunDefault() 134 }