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  }