123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- package main
- import (
- "context"
- "encoding/json"
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "os"
- "strings"
- "time"
- "git.lattuga.net/boyska/circolog"
- )
- 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,
- "status": statusCmd,
- "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 statusCmd(args []string) error {
- flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
- outFormat := flagset.String("format", "plain", "Which format to use as output for this command (json, pretty, plain)")
- flagset.Parse(args[1:])
- resp, err := ctl.Get("http://unix/status")
- if err != nil {
- return err
- }
- defer resp.Body.Close()
- respBytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return err
- }
- respJSON := make(map[string]circolog.StatusResponse)
- err = json.Unmarshal(respBytes, &respJSON)
- if err != nil {
- return err
- }
- switch *outFormat {
- case "json":
- fmt.Printf("%s", string(respBytes))
- case "pretty":
- prettyJSON, err := json.MarshalIndent(respJSON, "", " ")
- if err != nil {
- return err
- }
- fmt.Printf("%s\n", prettyJSON)
- case "plain":
- fmt.Printf("Buffer Size: %d\n", respJSON["status"].Size)
- fmt.Printf("Server Status: %s\n", respJSON["status"].Status())
- fmt.Printf("Filter String: %s\n", respJSON["status"].Filter)
- }
- return nil
- }
- 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 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 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)
- }
|