From 90ccba673083c8b6f1a2aabb60527069fe63bfa5 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Fri, 22 Jul 2022 09:39:24 -0400 Subject: [PATCH] cmd/gitops-pusher: port to use ffcli (#5113) Signed-off-by: Xe --- cmd/gitops-pusher/gitops-pusher.go | 127 +++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/cmd/gitops-pusher/gitops-pusher.go b/cmd/gitops-pusher/gitops-pusher.go index 54e62818d..96e7d8d2d 100644 --- a/cmd/gitops-pusher/gitops-pusher.go +++ b/cmd/gitops-pusher/gitops-pusher.go @@ -20,39 +20,27 @@ import ( "strings" "time" + "github.com/peterbourgon/ff/v3/ffcli" "github.com/tailscale/hujson" ) var ( - policyFname = flag.String("policy-file", "./policy.hujson", "filename for policy file") - timeout = flag.Duration("timeout", 5*time.Minute, "timeout for the entire CI run") - githubSyntax = flag.Bool("github-syntax", true, "use GitHub Action error syntax (https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message)") + rootFlagSet = flag.NewFlagSet("gitops-pusher", flag.ExitOnError) + policyFname = rootFlagSet.String("policy-file", "./policy.hujson", "filename for policy file") + timeout = rootFlagSet.Duration("timeout", 5*time.Minute, "timeout for the entire CI run") + githubSyntax = rootFlagSet.Bool("github-syntax", true, "use GitHub Action error syntax (https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message)") ) -func main() { - flag.Parse() - ctx, cancel := context.WithTimeout(context.Background(), *timeout) - defer cancel() - - tailnet, ok := os.LookupEnv("TS_TAILNET") - if !ok { - log.Fatal("set envvar TS_TAILNET to your tailnet's name") - } - apiKey, ok := os.LookupEnv("TS_API_KEY") - if !ok { - log.Fatal("set envvar TS_API_KEY to your Tailscale API key") - } - - switch flag.Arg(0) { - case "apply": +func apply(tailnet, apiKey string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { controlEtag, err := getACLETag(ctx, tailnet, apiKey) if err != nil { - log.Fatal(err) + return err } localEtag, err := sumFile(*policyFname) if err != nil { - log.Fatal(err) + return err } log.Printf("control: %s", controlEtag) @@ -60,23 +48,27 @@ func main() { if controlEtag == localEtag { log.Println("no update needed, doing nothing") - os.Exit(0) + return nil } if err := applyNewACL(ctx, tailnet, apiKey, *policyFname, controlEtag); err != nil { - fmt.Println(err) - os.Exit(1) + return err } - case "test": + return nil + } +} + +func test(tailnet, apiKey string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { controlEtag, err := getACLETag(ctx, tailnet, apiKey) if err != nil { - log.Fatal(err) + return err } localEtag, err := sumFile(*policyFname) if err != nil { - log.Fatal(err) + return err } log.Printf("control: %s", controlEtag) @@ -84,15 +76,86 @@ func main() { if controlEtag == localEtag { log.Println("no updates found, doing nothing") - os.Exit(0) + return nil } if err := testNewACLs(ctx, tailnet, apiKey, *policyFname); err != nil { - fmt.Println(err) - os.Exit(1) + return err + } + return nil + } +} + +func getChecksums(tailnet, apiKey string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { + controlEtag, err := getACLETag(ctx, tailnet, apiKey) + if err != nil { + return err + } + + localEtag, err := sumFile(*policyFname) + if err != nil { + return err } - default: - log.Fatalf("usage: %s [options] ", os.Args[0]) + + log.Printf("control: %s", controlEtag) + log.Printf("local: %s", localEtag) + + return nil + } +} + +func main() { + tailnet, ok := os.LookupEnv("TS_TAILNET") + if !ok { + log.Fatal("set envvar TS_TAILNET to your tailnet's name") + } + apiKey, ok := os.LookupEnv("TS_API_KEY") + if !ok { + log.Fatal("set envvar TS_API_KEY to your Tailscale API key") + } + + applyCmd := &ffcli.Command{ + Name: "apply", + ShortUsage: "gitops-pusher [options] apply", + ShortHelp: "Pushes changes to CONTROL", + LongHelp: `Pushes changes to CONTROL`, + Exec: apply(tailnet, apiKey), + } + + testCmd := &ffcli.Command{ + Name: "test", + ShortUsage: "gitops-pusher [options] test", + ShortHelp: "Tests ACL changes", + LongHelp: "Tests ACL changes", + Exec: test(tailnet, apiKey), + } + + cksumCmd := &ffcli.Command{ + Name: "checksum", + ShortUsage: "Shows checksums of ACL files", + ShortHelp: "Fetch checksum of CONTROL's ACL and the local ACL for comparison", + LongHelp: "Fetch checksum of CONTROL's ACL and the local ACL for comparison", + Exec: getChecksums(tailnet, apiKey), + } + + root := &ffcli.Command{ + ShortUsage: "gitops-pusher [options] ", + ShortHelp: "Push Tailscale ACLs to CONTROL using a GitOps workflow", + Subcommands: []*ffcli.Command{applyCmd, cksumCmd, testCmd}, + FlagSet: rootFlagSet, + } + + if err := root.Parse(os.Args[1:]); err != nil { + log.Fatal(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), *timeout) + defer cancel() + + if err := root.Run(ctx); err != nil { + fmt.Println(err) + os.Exit(1) } }