From bc9fc9730dd30e2d302ce5f88cd93da9604eb6f0 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Wed, 8 Feb 2017 15:32:44 +0100 Subject: feat main: Add apply command This integrates support for actually calling out to `kubectl apply`. A dry-run flag is implemented, too. The `run` command has been renamed to `template`. --- main.go | 118 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 27 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index de734e8ac3..c39972ff60 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "os/exec" "github.com/polydawn/meep" "github.com/tazjin/kontemplate/context" @@ -10,6 +11,10 @@ import ( "github.com/urfave/cli" ) +type KubeCtlError struct { + meep.AllTraits +} + func main() { app := cli.NewApp() @@ -18,56 +23,115 @@ func main() { app.Version = "0.0.1" app.Commands = []cli.Command{ - ApplyCommand(), + templateCommand(), + applyCommand(), } app.Run(os.Args) } -func ApplyCommand() cli.Command { +func templateCommand() cli.Command { return cli.Command{ - Name: "run", + Name: "template", Usage: "Interpolate and print templates", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "file, f", - Usage: "Cluster configuration file to use", - }, - cli.StringSliceFlag{ - Name: "limit, l", - Usage: "Limit templating to certain resource sets", - }, - }, + Flags: commonFlags(), Action: func(c *cli.Context) error { - limit := c.StringSlice("limit") - f := c.String("file") - - if f == "" { - return meep.New( - &meep.ErrInvalidParam{ - Param: "file", - Reason: "Cluster config file must be specified", - }, - ) + resources, err := templateResources(c) + + if err != nil { + return err } - ctx, err := context.LoadContextFromFile(f) + for _, r := range resources { + fmt.Println(r) + } + + return nil + }, + } +} + +func applyCommand() cli.Command { + dryRun := false + + return cli.Command{ + Name: "apply", + Usage: "Interpolate templates and run 'kubectl apply'", + Flags: append(commonFlags(), cli.BoolFlag{ + Name: "dry-run", + Usage: "Only print objects that would be sent, without sending them", + Destination: &dryRun, + }), + Action: func(c *cli.Context) error { + resources, err := templateResources(c) if err != nil { return err } - resources, err := templater.LoadAndPrepareTemplates(&limit, ctx) + var kubectl *exec.Cmd + if dryRun { + kubectl = exec.Command("kubectl", "apply", "-f", "-", "--dry-run") + } else { + kubectl = exec.Command("kubectl", "apply", "-f", "-") + } + stdin, err := kubectl.StdinPipe() if err != nil { - return err + return meep.New(&KubeCtlError{}, meep.Cause(err)) + } + + kubectl.Stdout = os.Stdout + kubectl.Stderr = os.Stderr + + if err = kubectl.Start(); err != nil { + return meep.New(&KubeCtlError{}, meep.Cause(err)) } for _, r := range resources { - fmt.Println(r) + fmt.Fprintln(stdin, r) } + stdin.Close() + + kubectl.Wait() + return nil }, } } + +func commonFlags() []cli.Flag { + return []cli.Flag{ + cli.StringFlag{ + Name: "file, f", + Usage: "Cluster configuration file to use", + }, + cli.StringSliceFlag{ + Name: "limit, l", + Usage: "Limit templating to certain resource sets", + }, + } +} + +func templateResources(c *cli.Context) ([]string, error) { + limit := c.StringSlice("limit") + f := c.String("file") + + if f == "" { + return nil, meep.New( + &meep.ErrInvalidParam{ + Param: "file", + Reason: "Cluster config file must be specified", + }, + ) + } + + ctx, err := context.LoadContextFromFile(f) + + if err != nil { + return nil, err + } + + return templater.LoadAndPrepareTemplates(&limit, ctx) +} -- cgit 1.4.1