tvl-depot/fun/clbot/clbot.go
Luke Granger-Brown 5acd03817a chore(clbot): Add signal handler to make clbot shutdown cleanly on SIGINT.
Change-Id: I3c6eeeb99f9d81cdbcb10880c9075ac94c4f5d19
Reviewed-on: https://cl.tvl.fyi/c/depot/+/341
Reviewed-by: tazjin <mail@tazj.in>
2020-06-15 16:48:58 +00:00

101 lines
2.7 KiB
Go

package main
import (
"context"
"flag"
"io/ioutil"
"os"
"os/signal"
"time"
"code.tvl.fyi/fun/clbot/gerrit"
"github.com/davecgh/go-spew/spew"
log "github.com/golang/glog"
"golang.org/x/crypto/ssh"
)
var (
gerritAddr = flag.String("gerrit_host", "cl.tvl.fyi:29418", "Gerrit SSH host:port")
gerritSSHHostKey = flag.String("gerrit_ssh_pubkey", "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIUNYBYPCCBNDFSd0BuCR+8kgeuJ7IA5S2nTNQmkQUYNyXK+ot5os7rHtCk96+grd5+J8jFCuFBWisUe8h8NC0Q=", "Gerrit SSH public key")
gerritSSHTimeout = flag.Duration("gerrit_tcp_timeout", 5*time.Second, "Gerrit SSH TCP connect timeout")
required = flag.NewFlagSet("required flags", flag.ExitOnError)
gerritAuthUsername = required.String("gerrit_ssh_auth_username", "", "Gerrit SSH username")
gerritAuthKeyPath = required.String("gerrit_ssh_auth_key", "", "Gerrit SSH private key path")
)
func mustFixedHostKey(f string) ssh.HostKeyCallback {
pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(f))
if err != nil {
log.Exitf("ParseAuthorizedKey(%q): %v", f, err)
}
return ssh.FixedHostKey(pk)
}
func mustPrivateKey(p string) ssh.AuthMethod {
pkBytes, err := ioutil.ReadFile(p)
if err != nil {
log.Exitf("reading SSH private key from %q: %v", p, err)
}
pk, err := ssh.ParsePrivateKey(pkBytes)
if err != nil {
log.Exitf("parsing private key from %q: %v", p, err)
}
return ssh.PublicKeys(pk)
}
func checkRequired(fs *flag.FlagSet) {
missing := map[string]bool{}
fs.VisitAll(func(f *flag.Flag) { missing[f.Name] = true })
fs.Visit(func(f *flag.Flag) { delete(missing, f.Name) })
for f := range missing {
log.Errorf("flag %q was unset but is required", f)
}
if len(missing) > 0 {
os.Exit(1)
}
}
var shutdownFuncs []func()
func callOnShutdown(f func()) {
shutdownFuncs = append(shutdownFuncs, f)
}
func main() {
flag.Parse()
checkRequired(required)
shutdownCh := make(chan os.Signal)
signal.Notify(shutdownCh, os.Interrupt)
go func() {
<-shutdownCh
for n := len(shutdownFuncs); n >= 0; n-- {
shutdownFuncs[n]()
}
}()
ctx, cancel := context.WithCancel(context.Background())
callOnShutdown(cancel)
cfg := &ssh.ClientConfig{
User: *gerritAuthUsername,
Auth: []ssh.AuthMethod{mustPrivateKey(*gerritAuthKeyPath)},
HostKeyCallback: mustFixedHostKey(*gerritSSHHostKey),
Timeout: *gerritSSHTimeout,
}
cfg.SetDefaults()
gw, err := gerrit.New(ctx, "tcp", *gerritAddr, cfg)
if err != nil {
log.Errorf("gerrit.New(%q): %v", *gerritAddr, err)
}
callOnShutdown(func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
gw.Close(ctx)
})
for e := range gw.Events() {
log.Infof("hello: %v", spew.Sdump(e))
}
}