circolog/cmd/circologctl/main.go

185 lines
4.3 KiB
Go
Raw Normal View History

2018-12-20 09:45:05 +01:00
package main
import (
"context"
2019-01-03 11:15:30 +01:00
"encoding/json"
2018-12-20 09:45:05 +01:00
"flag"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
2018-12-20 09:45:05 +01:00
"os"
"strings"
"time"
2019-01-03 11:15:30 +01:00
"git.lattuga.net/boyska/circolog"
2018-12-20 09:45:05 +01:00
)
var globalOpts struct {
ctlSock string
verbose bool
2018-12-24 18:41:06 +01:00
debug bool
2018-12-20 09:45:05 +01:00
}
var ctl http.Client
2018-12-20 09:45:05 +01:00
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,
2019-01-03 11:15:30 +01:00
"status": statusCmd,
2018-12-20 09:45:05 +01:00
"pause": pauseCmd,
"filter": filterCmd,
2018-12-20 09:45:05 +01:00
"reload": reloadCmd,
"restart": restartCmd,
"help": helpCmd,
}
}
//func setCmd(ctlSock string, args []string) error {}
//func getCmd(ctlSock string, args []string) error {}
2019-01-03 11:15:30 +01:00
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":
2019-01-03 12:11:03 +01:00
fmt.Printf("Buffer Size: %d\n", respJSON["status"].Size)
2019-01-03 11:15:30 +01:00
fmt.Printf("Server Status: %s\n", respJSON["status"].Status())
2019-01-03 13:42:16 +01:00
fmt.Printf("Filter String: %s\n", respJSON["status"].Filter)
2019-01-03 11:15:30 +01:00
}
return nil
}
2018-12-20 09:45:05 +01:00
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:])
2018-12-24 18:41:06 +01:00
postBody := make(map[string][]string)
if *waitTime != dontChangeAgain {
2018-12-24 18:41:06 +01:00
postBody["waitTime"] = []string{fmt.Sprintf("%s", *waitTime)}
}
2018-12-24 18:41:06 +01:00
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
2018-12-20 09:45:05 +01:00
}
2019-01-03 12:23:20 +01:00
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
}
2018-12-20 09:45:05 +01:00
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)
},
},
}
2018-12-20 09:45:05 +01:00
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")
2018-12-24 18:41:06 +01:00
flag.BoolVar(&globalOpts.debug, "debug", false, "Print debugging info")
2018-12-20 09:45:05 +01:00
flag.Parse()
args := flag.Args()
if len(args) == 0 {
usage(os.Stderr)
os.Exit(-1)
}
parseAndRun(args)
}