func doInitialize(fs *flag.FlagSet, argv []string) error { var ( conffile = fs.String("conf", config.DefaultConfig.Conffile, "Config file path") apikey = fs.String("apikey", "", "API key from mackerel.io web site (Required)") ) fs.Parse(argv) if *apikey == "" { // Setting apikey via environment variable should be supported or not? return fmt.Errorf("-apikey option is required") } _, err := os.Stat(*conffile) confExists := err == nil if confExists { conf, err := config.LoadConfig(*conffile) if err != nil { return fmt.Errorf("Failed to load the config file: %s", err) } if conf.Apikey != "" { return apikeyAlreadySetError(*conffile) } } contents := []byte(fmt.Sprintf("apikey = %q\n", *apikey)) if confExists { cBytes, err := ioutil.ReadFile(*conffile) if err != nil { return err } contents = append(contents, cBytes...) } return ioutil.WriteFile(*conffile, contents, 0644) }
func resolveConfigForRetire(argv []string) (*config.Config, bool, error) { fs := flag.NewFlagSet("mackerel-agent retire", flag.ExitOnError) // Allow accepting unnecessary options, pidfile, diagnostic and role. // Because, these options are potentially passed in initd script by using $OTHER_OPTS. dirty... var ( conffile = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)") apibase = fs.String("apibase", config.DefaultConfig.Apibase, "API base") _ = fs.String("pidfile", config.DefaultConfig.Pidfile, "(not used in retire)") root = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information") apikey = fs.String("apikey", "", "API key from mackerel.io web site") force = fs.Bool("force", false, "force retirement without prompting") _ = fs.Bool("diagnostic", false, "(not used in retire)") ) var roleFullnames roleFullnamesFlag fs.Var(&roleFullnames, "role", "(not used in retire)") var verbose bool fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity") fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)") fs.Parse(argv) conf, err := config.LoadConfig(*conffile) if err != nil { return nil, *force, err } // overwrite config from file by config from args fs.Visit(func(f *flag.Flag) { switch f.Name { case "apibase": conf.Apibase = *apibase case "apikey": conf.Apikey = *apikey case "root": conf.Root = *root case "verbose", "v": conf.Verbose = verbose } }) return conf, *force, nil }
// resolveConfig parses command line arguments and loads config file to // return config.Config information. func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) { conf := &config.Config{} var ( conffile = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)") apibase = fs.String("apibase", config.DefaultConfig.Apibase, "API base") pidfile = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID") root = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information") apikey = fs.String("apikey", "", "(DEPRECATED) API key from mackerel.io web site") diagnostic = fs.Bool("diagnostic", false, "Enables diagnostic features") verbose bool roleFullnames roleFullnamesFlag ) fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity") fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)") // The value of "role" option is internally "roll fullname", // but we call it "role" here for ease. fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)") fs.Parse(argv) conf, confErr := config.LoadConfig(*conffile) conf.Conffile = *conffile if confErr != nil { return nil, fmt.Errorf("Failed to load the config file: %s", confErr) } // overwrite config from file by config from args fs.Visit(func(f *flag.Flag) { switch f.Name { case "apibase": conf.Apibase = *apibase case "apikey": conf.Apikey = *apikey case "pidfile": conf.Pidfile = *pidfile case "root": conf.Root = *root case "diagnostic": conf.Diagnostic = *diagnostic case "verbose", "v": conf.Verbose = verbose case "role": conf.Roles = roleFullnames } }) r := []string{} for _, roleFullName := range conf.Roles { if !roleFullnamePattern.MatchString(roleFullName) { logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName) } else { r = append(r, roleFullName) } } conf.Roles = r if conf.Verbose && conf.Silent { logger.Warningf("both of `verbose` and `silent` option are specified. In this case, `verbose` get preference over `silent`") } if conf.Apikey == "" { return nil, fmt.Errorf("Apikey must be specified in the config file (or by the DEPRECATED command-line flag)") } return conf, nil }
// resolveConfig parses command line arguments and loads config file to // return config.Config information. // As a special case, if `-version` flag is given it stops processing // and return true for the second return value. func resolveConfig(argv []string) (*config.Config, *otherOptions) { conf := &config.Config{} otherOptions := &otherOptions{} fs := flag.NewFlagSet("mackerel-agent", flag.ExitOnError) var ( conffile = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)") apibase = fs.String("apibase", config.DefaultConfig.Apibase, "API base") pidfile = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID") root = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information") apikey = fs.String("apikey", "", "API key from mackerel.io web site") diagnostic = fs.Bool("diagnostic", false, "Enables diagnostic features") runOnce = fs.Bool("once", false, "Show spec and metrics to stdout once") printVersion = fs.Bool("version", false, "Prints version and exit") ) var verbose bool fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity") fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)") // The value of "role" option is internally "roll fullname", // but we call it "role" here for ease. var roleFullnames roleFullnamesFlag fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)") fs.Parse(argv) if *printVersion { otherOptions.printVersion = true return conf, otherOptions } if *runOnce { otherOptions.runOnce = true return conf, otherOptions } conf, confErr := config.LoadConfig(*conffile) if confErr != nil { logger.Criticalf("Failed to load the config file: %s", confErr) return nil, nil } // overwrite config from file by config from args fs.Visit(func(f *flag.Flag) { switch f.Name { case "apibase": conf.Apibase = *apibase case "apikey": conf.Apikey = *apikey case "pidfile": conf.Pidfile = *pidfile case "root": conf.Root = *root case "diagnostic": conf.Diagnostic = *diagnostic case "verbose", "v": conf.Verbose = verbose case "role": conf.Roles = roleFullnames } }) r := []string{} for _, roleFullName := range conf.Roles { if !roleFullnamePattern.MatchString(roleFullName) { logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName) } else { r = append(r, roleFullName) } } conf.Roles = r return conf, nil }