cmd/gitops-pusher: port to use ffcli (#5113)

Signed-off-by: Xe <xe@tailscale.com>
pull/5122/head
Xe Iaso 2 years ago committed by GitHub
parent f7a36dfeb1
commit 90ccba6730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -20,39 +20,27 @@ import (
"strings" "strings"
"time" "time"
"github.com/peterbourgon/ff/v3/ffcli"
"github.com/tailscale/hujson" "github.com/tailscale/hujson"
) )
var ( var (
policyFname = flag.String("policy-file", "./policy.hujson", "filename for policy file") rootFlagSet = flag.NewFlagSet("gitops-pusher", flag.ExitOnError)
timeout = flag.Duration("timeout", 5*time.Minute, "timeout for the entire CI run") policyFname = rootFlagSet.String("policy-file", "./policy.hujson", "filename for policy file")
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)") 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() { func apply(tailnet, apiKey string) func(context.Context, []string) error {
flag.Parse() return func(ctx context.Context, args []string) error {
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":
controlEtag, err := getACLETag(ctx, tailnet, apiKey) controlEtag, err := getACLETag(ctx, tailnet, apiKey)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
localEtag, err := sumFile(*policyFname) localEtag, err := sumFile(*policyFname)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
log.Printf("control: %s", controlEtag) log.Printf("control: %s", controlEtag)
@ -60,23 +48,27 @@ func main() {
if controlEtag == localEtag { if controlEtag == localEtag {
log.Println("no update needed, doing nothing") log.Println("no update needed, doing nothing")
os.Exit(0) return nil
} }
if err := applyNewACL(ctx, tailnet, apiKey, *policyFname, controlEtag); err != nil { if err := applyNewACL(ctx, tailnet, apiKey, *policyFname, controlEtag); err != nil {
fmt.Println(err) return err
os.Exit(1) }
return nil
}
} }
case "test": func test(tailnet, apiKey string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
controlEtag, err := getACLETag(ctx, tailnet, apiKey) controlEtag, err := getACLETag(ctx, tailnet, apiKey)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
localEtag, err := sumFile(*policyFname) localEtag, err := sumFile(*policyFname)
if err != nil { if err != nil {
log.Fatal(err) return err
} }
log.Printf("control: %s", controlEtag) log.Printf("control: %s", controlEtag)
@ -84,16 +76,87 @@ func main() {
if controlEtag == localEtag { if controlEtag == localEtag {
log.Println("no updates found, doing nothing") log.Println("no updates found, doing nothing")
os.Exit(0) return nil
} }
if err := testNewACLs(ctx, tailnet, apiKey, *policyFname); err != nil { if err := testNewACLs(ctx, tailnet, apiKey, *policyFname); err != nil {
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
}
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] <command>",
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) fmt.Println(err)
os.Exit(1) os.Exit(1)
} }
default:
log.Fatalf("usage: %s [options] <test|apply>", os.Args[0])
}
} }
func sumFile(fname string) (string, error) { func sumFile(fname string) (string, error) {

Loading…
Cancel
Save