about summary refs log tree commit diff
path: root/fun/clbot/clbot.go
diff options
context:
space:
mode:
authorLuke Granger-Brown <git@lukegb.com>2020-06-13T22·43+0100
committerlukegb <lukegb@tvl.fyi>2020-06-14T17·16+0000
commitc05803ff14f7d7c911bdc91383703b5cd9342396 (patch)
tree0d930afc22b541f06f3778378185d85a455a10db /fun/clbot/clbot.go
parentf6c7c85d9410a8314191913f4f1a22dc526b8b79 (diff)
feat(clbot): Create Gerrit watcher and basic clbot binary. r/950
gerrit.Watcher is a class which watches the Gerrit stream-events SSH
connection and produces events.

There's a basic CLBot binary as well, to demonstrate driving it to
produce messages on the logging output. It doesn't really do anything
else.

Change-Id: I274fe0a77c8329f79456425405e2fbdc3ca2edf0
Reviewed-on: https://cl.tvl.fyi/c/depot/+/245
Reviewed-by: tazjin <mail@tazj.in>
Diffstat (limited to 'fun/clbot/clbot.go')
-rw-r--r--fun/clbot/clbot.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/fun/clbot/clbot.go b/fun/clbot/clbot.go
new file mode 100644
index 0000000000..943df3bd38
--- /dev/null
+++ b/fun/clbot/clbot.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+	"context"
+	"flag"
+	"io/ioutil"
+	"os"
+	"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)
+	}
+}
+
+func main() {
+	flag.Parse()
+	checkRequired(required)
+
+	ctx := context.Background()
+	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)
+	}
+
+	for e := range gw.Events() {
+		log.Infof("hello: %v", spew.Sdump(e))
+	}
+}