diff --git a/.gitignore b/.gitignore index f9c99b6..29be076 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -helix +^helix$ diff --git a/cmd/helix/main.go b/cmd/helix/main.go index 3f0a556..b2d661b 100644 --- a/cmd/helix/main.go +++ b/cmd/helix/main.go @@ -5,152 +5,130 @@ import ( "fmt" "os" - "github.com/leaanthony/clir" "forge.dananglin.me.uk/code/dananglin/helix/internal/config" "forge.dananglin.me.uk/code/dananglin/helix/internal/stacks" + "github.com/urfave/cli/v2" ) func main() { if err := run(); err != nil { - fmt.Printf("ERROR: %v.\n", err) + fmt.Printf("Error: %s.\n", err) os.Exit(1) } } func run() error { - helix := clir.NewCli("helix", "A CLI tool for managing your forge platform.", "v0.0.1") - helix.LongDescription(`Helix is a command line tool used to help manage your forge platform. -This uses the Pulumi Automation API library to create and manage different components -that builds your forge platform on a Linode instance.`) + cli.VersionPrinter = func(c *cli.Context) { + fmt.Printf("helix version %s\n", c.App.Version) + } - versionCmd := helix.NewSubCommand("version", "Print the version of this application.") - versionCmd.Action(versionFunc(helix.Version())) + stackFlag := cli.StringFlag{ + Name: "stack", + Aliases: []string{"s"}, + Value: "", + Usage: "the name of the stack.", + EnvVars: []string{"HELIX_STACK"}, + Required: false, + } - var file string - var stack string + instanceFlag := cli.StringFlag{ + Name: "instance", + Aliases: []string{"i"}, + Value: "", + Usage: "the `path` to your forge platform instance file.", + EnvVars: []string{"HELIX_INSTANCE"}, + Required: true, + } + helix := &cli.App{ + Authors: []*cli.Author{ + { + Name: "Dan Anglin", + Email: "d.n.i.anglin@gmail.com", + }, + }, + Copyright: "Copyright (c) 2021 Dan Anglin", + Name: "helix", + Usage: "A CLI tool for managing a forge platform on a Linode instance.", + Flags: []cli.Flag{&instanceFlag, &stackFlag}, + Version: "v0.0.1", + Commands: []*cli.Command{ + { + Name: "preview", + Usage: "preview upcoming changes to a stack.", + Action: previewFunc, + }, + { + Name: "update", + Usage: "update a stack.", + Action: updateFunc, + }, + { + Name: "destroy", + Usage: "destroy a stack.", + Action: destroyFunc, + }, + }, + } + + return helix.Run(os.Args) +} + +func previewFunc(c *cli.Context) error { ctx := context.Background() - updateCmd := helix.NewSubCommand("update", "Update a stack.") - updateCmd.Action(updateFunc(ctx, &file, &stack)) - updateCmd.StringFlag("file", "the path to the configuration file", &file) - updateCmd.StringFlag("stack", "the name of the stack", &stack) - - previewCmd := helix.NewSubCommand("preview", "Preview upcoming changes to a stack.") - previewCmd.Action(previewFunc(ctx, &file, &stack)) - previewCmd.StringFlag("file", "the path to the configuration file", &file) - previewCmd.StringFlag("stack", "the name of the stack", &stack) - - destroyCmd := helix.NewSubCommand("destroy", "Destroy a stack.") - destroyCmd.Action(destroyFunc(ctx, &file, &stack)) - destroyCmd.StringFlag("file", "the path to the configuration file", &file) - destroyCmd.StringFlag("stack", "the name of the stack", &stack) - - helix.DefaultCommand(versionCmd) - - return helix.Run() -} - -func versionFunc(version string) clir.Action { - return func() error { - fmt.Printf("helix version %s\n", version) - - return nil - } -} - -func previewFunc(ctx context.Context, file, stack *string) clir.Action { - flagMap := map[string]*string{ - "file": file, - "stack": stack, + cfg, err := config.NewConfig(c.String("instance")) + if err != nil { + return fmt.Errorf("unable to get configuration...\n%v", err) } - return func() error { - if err := checkFlags(flagMap); err != nil { - return err - } - - c, err := config.NewConfig(*flagMap["file"]) - if err != nil { - return fmt.Errorf("unable to get configuration...\n%v", err) - } - - previewer, err := stacks.NewPreviewer(ctx, *stack, c) - if err != nil { - return err - } - - if err := previewer.Preview(ctx); err != nil { - return err - } - - return nil - } -} - -func updateFunc(ctx context.Context, file, stack *string) clir.Action { - flagMap := map[string]*string{ - "file": file, - "stack": stack, + previewer, err := stacks.NewPreviewer(ctx, c.String("stack"), cfg) + if err != nil { + return err } - return func() error { - if err := checkFlags(flagMap); err != nil { - return err - } - - c, err := config.NewConfig(*flagMap["file"]) - if err != nil { - return fmt.Errorf("unable to get configuration...\n%v", err) - } - - updater, err := stacks.NewUpdater(ctx, *stack, c) - if err != nil { - return err - } - - if err := updater.Update(ctx); err != nil { - return err - } - - return nil - } -} - -func destroyFunc(ctx context.Context, file, stack *string) clir.Action { - flagMap := map[string]*string{ - "file": file, - "stack": stack, - } - - return func() error { - if err := checkFlags(flagMap); err != nil { - return err - } - - c, err := config.NewConfig(*flagMap["file"]) - if err != nil { - return fmt.Errorf("unable to get configuration...\n%v", err) - } - - destroyer, err := stacks.NewDestroyer(ctx, *stack, c) - if err != nil { - return err - } - - if err := destroyer.Destroy(ctx); err != nil { - return err - } - - return nil - } -} - -func checkFlags(f map[string]*string) error { - for k, v := range f { - if len(*v) == 0 { - return fmt.Errorf("the value for the '%s' flag is not set", k) - } + if err := previewer.Preview(ctx); err != nil { + return err + } + + return nil +} + +func updateFunc(c *cli.Context) error { + ctx := context.Background() + + cfg, err := config.NewConfig(c.String("instance")) + if err != nil { + return fmt.Errorf("unable to get configuration...\n%v", err) + } + + updater, err := stacks.NewUpdater(ctx, c.String("stack"), cfg) + if err != nil { + return err + } + + if err := updater.Update(ctx); err != nil { + return err + } + + return nil +} + +func destroyFunc(c *cli.Context) error { + ctx := context.Background() + + cfg, err := config.NewConfig(c.String("instance")) + if err != nil { + return fmt.Errorf("unable to get configuration...\n%v", err) + } + + destroyer, err := stacks.NewDestroyer(ctx, c.String("stack"), cfg) + if err != nil { + return err + } + + if err := destroyer.Destroy(ctx); err != nil { + return err } return nil diff --git a/go.mod b/go.mod index 1e2efc5..747e83a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module forge.dananglin.me.uk/code/dananglin/helix go 1.16 require ( - github.com/leaanthony/clir v1.0.4 github.com/pulumi/pulumi-docker/sdk/v3 v3.1.0 github.com/pulumi/pulumi/sdk/v3 v3.11.0 + github.com/urfave/cli/v2 v2.3.0 ) diff --git a/go.sum b/go.sum index b1b319f..59af7ae 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -123,8 +125,6 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU= -github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= @@ -173,12 +173,14 @@ github.com/pulumi/pulumi/sdk/v3 v3.0.0/go.mod h1:GBHyQ7awNQSRmiKp/p8kIKrGrMOZeA/ github.com/pulumi/pulumi/sdk/v3 v3.11.0 h1:XljryA45etplc9WfmTm8/DKi5Evx94j0qQ7ovSWL/To= github.com/pulumi/pulumi/sdk/v3 v3.11.0/go.mod h1:bxxmONw/K6M4KHRKWTwP/u77JbqDFnt96p0nSsrsHnQ= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -214,6 +216,8 @@ github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -345,6 +349,7 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=