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`.
This commit is contained in:
Vincent Ambo 2017-02-08 15:32:44 +01:00
parent 25f2a1616c
commit bc9fc9730d

128
main.go
View file

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"os/exec"
"github.com/polydawn/meep" "github.com/polydawn/meep"
"github.com/tazjin/kontemplate/context" "github.com/tazjin/kontemplate/context"
@ -10,6 +11,10 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
) )
type KubeCtlError struct {
meep.AllTraits
}
func main() { func main() {
app := cli.NewApp() app := cli.NewApp()
@ -18,46 +23,20 @@ func main() {
app.Version = "0.0.1" app.Version = "0.0.1"
app.Commands = []cli.Command{ app.Commands = []cli.Command{
ApplyCommand(), templateCommand(),
applyCommand(),
} }
app.Run(os.Args) app.Run(os.Args)
} }
func ApplyCommand() cli.Command { func templateCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "run", Name: "template",
Usage: "Interpolate and print templates", Usage: "Interpolate and print templates",
Flags: []cli.Flag{ Flags: commonFlags(),
cli.StringFlag{
Name: "file, f",
Usage: "Cluster configuration file to use",
},
cli.StringSliceFlag{
Name: "limit, l",
Usage: "Limit templating to certain resource sets",
},
},
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
limit := c.StringSlice("limit") resources, err := templateResources(c)
f := c.String("file")
if f == "" {
return meep.New(
&meep.ErrInvalidParam{
Param: "file",
Reason: "Cluster config file must be specified",
},
)
}
ctx, err := context.LoadContextFromFile(f)
if err != nil {
return err
}
resources, err := templater.LoadAndPrepareTemplates(&limit, ctx)
if err != nil { if err != nil {
return err return err
@ -71,3 +50,88 @@ func ApplyCommand() cli.Command {
}, },
} }
} }
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
}
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 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.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)
}