diff --git a/plugin/comms/flags.go b/plugin/comms/flags.go index 4d9d716..06ee750 100644 --- a/plugin/comms/flags.go +++ b/plugin/comms/flags.go @@ -13,69 +13,142 @@ ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ** SOFTWARE. **/ package comms import ( + "bytes" + "errors" "flag" "fmt" "os" - "path/filepath" ) -const ( - emptyDescription = "" - boolDefault = false -) +// ErrOSExitZero is returned when no error has occurred but the program should +// exit. +var ErrOSExitZero = errors.New("no error; exit 0") -var ( - versionFlag bool - helpFlag bool -) +const helpMessageFmt = // +` +%s plugin for Zabbix Agent 2 -func InitCommonFlags() { - flag.BoolVar(&versionFlag, "version", boolDefault, emptyDescription) - flag.BoolVar(&versionFlag, "V", boolDefault, emptyDescription) - flag.BoolVar(&helpFlag, "help", boolDefault, emptyDescription) - flag.BoolVar(&helpFlag, "h", boolDefault, emptyDescription) -} +Usage of "%s" + %s -h + %s -V + +Options: +` + +// HandleFlags registers and parses version and help command line flags. +// Help and version should be the only comand line flags a plugin implement as +// when a plugin is loaded by Agent 2 no comand line flags are passed, how +// ever arguments are used to establish a socket connection. +func HandleFlags( + pluginName, pluginBinName, copyrightMessage, alphatag string, + majorVersion, minorVersion, patchVersion int, +) error { + var ( + versionFlag bool + helpFlag bool + ) + + // define a new flag set to avoid collisions with possible user defined + // flags. + cl := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + + cl.BoolVar(&versionFlag, "version", false, "Display version number") + cl.BoolVar(&versionFlag, "V", false, "Display version number") + cl.BoolVar(&helpFlag, "help", false, "Display this help message") + cl.BoolVar(&helpFlag, "h", false, "Display this help message") + + helpMessage, err := buildHelpMessage(cl, pluginName, pluginBinName) + if err != nil { + return err + } + + // cl.Usage is called when an error occurs during flag parsing. + cl.Usage = func() { + fmt.Print(helpMessage) + } + + err = cl.Parse(os.Args[1:]) + if err != nil { + return err + } -func VisitCommonFlags(pluginName string, copyrightMessage string, helpMessage string, majorVersion int, - minorVersion int, patchVersion int, alphatag string) { - if helpFlag || len(os.Args) == 1 { + // a plugin when called by agent will always have at least one argument - + // socket, hence if there are no arguments the plugin is called manually + // and a help message should be printed. + if len(os.Args) == 1 { fmt.Print(helpMessage) - os.Exit(0) + + return ErrOSExitZero } - flag.Visit(func(f *flag.Flag) { + cl.Visit(func(f *flag.Flag) { switch f.Name { + case "h", "help": + fmt.Print(helpMessage) + + err = ErrOSExitZero case "V", "version": - PrintVersion(pluginName, copyrightMessage, majorVersion, minorVersion, patchVersion, alphatag) - os.Exit(0) + PrintVersion( + pluginName, + copyrightMessage, + majorVersion, + minorVersion, + patchVersion, + alphatag, + ) + + err = ErrOSExitZero } }) -} + if err != nil { + return err + } -func GetCommonHelpMessage() string { - return fmt.Sprintf("Usage of \"%s\":\n"+ - " zabbix-agent2-plugin-postgresql -h\n"+ - " zabbix-agent2-plugin-postgresql -V\n"+ - "\n"+ - "Options:\n"+ - " -h -help Display this help message\n"+ - " -V -version Display version number\n", - filepath.Base(os.Args[0])) + return nil } -func HandleCommonFlags(pluginName string, copyrightMessage string, majorVersion int, minorVersion int, patchVersion int, - alphatag string) { - InitCommonFlags() +func buildHelpMessage( + cl *flag.FlagSet, pluginName, pluginBinName string, +) (string, error) { + allFlags := make(map[string]string) + order := []string{ + "h", + "help", + "V", + "version", + } - flag.Parse() + cl.VisitAll( + func(f *flag.Flag) { + allFlags[f.Name] = f.Usage + }, + ) + + if len(allFlags) != len(order) { + return "", errors.New("flag count mismatch") + } + + w := &bytes.Buffer{} + + fmt.Fprintf( + w, + helpMessageFmt, + pluginName, + pluginBinName, + pluginBinName, + pluginBinName, + ) + + for _, o := range order { + fmt.Fprintf(w, " -%20s %s\n", o, allFlags[o]) + } - VisitCommonFlags(pluginName, copyrightMessage, GetCommonHelpMessage(), majorVersion, minorVersion, - patchVersion, alphatag) + return w.String(), nil }