package main import ( "context" "flag" "fmt" "io" "io/ioutil" "net" "net/http" "os" "strings" "time" ) var globalOpts struct { ctlSock string verbose bool debug bool } var ctl http.Client type commandFunc func([]string) error var cmdMap map[string]commandFunc func init() { cmdMap = map[string]commandFunc{ // TODO: implement set and get of config at runtime //"set": setCmd, //"get": getCmd, "pause": pauseCmd, "filter": filterCmd, "reload": reloadCmd, "restart": restartCmd, "help": helpCmd, } } //func setCmd(ctlSock string, args []string) error {} //func getCmd(ctlSock string, args []string) error {} func filterCmd(args []string) error { filter := strings.Join(args[1:], " ") postBody := make(map[string][]string) postBody["where"] = []string{filter} if globalOpts.debug { fmt.Println("[DEBUG] postBody:", postBody) } resp, err := ctl.PostForm("http://unix/filter", postBody) if resp.StatusCode != 200 || globalOpts.verbose { defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return err } fmt.Println(string(bodyBytes)) } return err } func pauseCmd(args []string) error { var dontChangeAgain time.Duration flagset := flag.NewFlagSet(args[0], flag.ExitOnError) waitTime := flagset.Duration("wait-time", dontChangeAgain, "How long to wait before untoggling the state, defaults to never") flagset.Parse(args[1:]) postBody := make(map[string][]string) if *waitTime != dontChangeAgain { postBody["waitTime"] = []string{fmt.Sprintf("%s", *waitTime)} } if globalOpts.debug { fmt.Println("[DEBUG] postBody:", postBody) } resp, err := ctl.PostForm("http://unix/pause/toggle", postBody) if globalOpts.verbose { defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return err } fmt.Println(string(bodyBytes)) } return err } func reloadCmd(args []string) error { return nil } func restartCmd(args []string) error { return nil } func helpCmd(args []string) error { usage(os.Stdout) os.Exit(0) return nil } func usage(w io.Writer) { fmt.Fprintf(w, "USAGE: %s [globalOpts] [SUBCOMMAND] [opts]\n", os.Args[0]) fmt.Fprintf(w, "\nSUBCOMMANDS:\n\n") for command := range cmdMap { fmt.Fprintf(w, "\t%s\n", command) } } func parseAndRun(args []string) { cmdName := args[0] cmdToRun, ok := cmdMap[cmdName] if !ok { fmt.Fprintf(os.Stderr, "Unknown subcommand: %s\n", cmdName) usage(os.Stderr) os.Exit(2) } // from here: https://gist.github.com/teknoraver/5ffacb8757330715bcbcc90e6d46ac74 ctl = http.Client{ Transport: &http.Transport{ DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { return net.Dial("unix", globalOpts.ctlSock) }, }, } err := cmdToRun(args) if err != nil { fmt.Fprintf(os.Stderr, "Error:\n%s\n", err) os.Exit(1) } } func main() { flag.StringVar(&globalOpts.ctlSock, "ctl-socket", "/tmp/circologd-ctl.sock", "Path to a unix domain socket for the control server; leave empty to disable") flag.BoolVar(&globalOpts.verbose, "verbose", false, "Print more output") flag.BoolVar(&globalOpts.debug, "debug", false, "Print debugging info") flag.Parse() args := flag.Args() if len(args) == 0 { usage(os.Stderr) os.Exit(-1) } parseAndRun(args) }