about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@gmail.com>2017-02-08T11·58+0100
committerVincent Ambo <tazjin@gmail.com>2017-02-08T11·58+0100
commit7ac63613fb64c6cec3119afc51ba4bac91b81a94 (patch)
tree58927d534621fe94ea882628df372de7901007a5
parent8fac7c1a415d6ea5e41c28f4e7ab5c1ef0883997 (diff)
feat main: Add proper CLI support
Adds a basic CLI structure with a single "run" command that takes a --file (-f)
and --limit (-l) flag.

--limit can be used to only output certain resource sets.

Closes #4
-rw-r--r--context/context.go3
-rw-r--r--main.go72
-rw-r--r--templater/templater.go70
3 files changed, 105 insertions, 40 deletions
diff --git a/context/context.go b/context/context.go
index e842feae1dc5..612faa39acab 100644
--- a/context/context.go
+++ b/context/context.go
@@ -2,9 +2,10 @@ package context
 
 import (
 	"encoding/json"
-	"github.com/polydawn/meep"
 	"io/ioutil"
 	"path"
+
+	"github.com/polydawn/meep"
 )
 
 type ResourceSet struct {
diff --git a/main.go b/main.go
index 158c9a566a86..de734e8ac37d 100644
--- a/main.go
+++ b/main.go
@@ -4,36 +4,70 @@ import (
 	"fmt"
 	"os"
 
+	"github.com/polydawn/meep"
 	"github.com/tazjin/kontemplate/context"
 	"github.com/tazjin/kontemplate/templater"
+	"github.com/urfave/cli"
 )
 
 func main() {
-	args := os.Args[1:]
-	if len(args) == 0 {
-		fmt.Fprintln(os.Stderr, "Usage: kontemplate <cluster-config>")
-		os.Exit(1)
-	}
+	app := cli.NewApp()
 
-	c, err := context.LoadContextFromFile(os.Args[1])
+	app.Name = "kontemplate"
+	app.Usage = "simple Kubernetes resource templating"
+	app.Version = "0.0.1"
 
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "%v\n", err)
-		os.Exit(1)
+	app.Commands = []cli.Command{
+		ApplyCommand(),
 	}
 
-	fmt.Fprintf(os.Stderr, "Applying cluster %s\n", c.Name)
+	app.Run(os.Args)
+}
+
+func ApplyCommand() cli.Command {
+	return cli.Command{
+		Name:  "run",
+		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",
+			},
+		},
+		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",
+					},
+				)
+			}
+
+			ctx, err := context.LoadContextFromFile(f)
+
+			if err != nil {
+				return err
+			}
+
+			resources, err := templater.LoadAndPrepareTemplates(&limit, ctx)
 
-	for _, rs := range c.ResourceSets {
-		fmt.Fprintf(os.Stderr, "Applying resource %s with values %v\n", rs.Name, rs.Values)
-		resources, err := templater.LoadAndPrepareTemplates(c)
+			if err != nil {
+				return err
+			}
 
-		if err != nil {
-			fmt.Println(err)
-		}
+			for _, r := range resources {
+				fmt.Println(r)
+			}
 
-		for _, r := range resources {
-			fmt.Print(r)
-		}
+			return nil
+		},
 	}
 }
diff --git a/templater/templater.go b/templater/templater.go
index 27beff371e5c..a2c860c60d3d 100644
--- a/templater/templater.go
+++ b/templater/templater.go
@@ -24,37 +24,67 @@ type TemplatingError struct {
 	meep.AllTraits
 }
 
-func LoadAndPrepareTemplates(c *context.Context) ([]string, error) {
-	output := make([]string, 0)
-
+func LoadAndPrepareTemplates(limit *[]string, c *context.Context) (output []string, err error) {
 	for _, rs := range c.ResourceSets {
-		fmt.Fprintf(os.Stderr, "Loading resources for %s\n", rs.Name)
+		if resourceSetIncluded(limit, &rs.Name) {
+			err = processResourceSet(c, &rs, &output)
+
+			if err != nil {
+				return
+			}
+		}
+	}
 
-		rp := path.Join(c.BaseDir, rs.Name)
-		files, err := ioutil.ReadDir(rp)
+	return
+}
 
-		if err != nil {
-			return nil, meep.New(
-				&TemplateNotFoundError{Name: rs.Name},
-				meep.Cause(err),
-			)
+func resourceSetIncluded(limit *[]string, resourceSetName *string) bool {
+	if len(*limit) == 0 {
+		return true
+	}
+
+	for _, name := range *limit {
+		if name == *resourceSetName {
+			return true
 		}
+	}
+
+	return false
+}
 
-		for _, file := range files {
-			if !file.IsDir() && isResourceFile(file) {
-				p := path.Join(rp, file.Name())
-				o, err := templateFile(c, &rs, p)
+func processResourceSet(c *context.Context, rs *context.ResourceSet, output *[]string) error {
+	fmt.Fprintf(os.Stderr, "Loading resources for %s\n", rs.Name)
 
-				if err != nil {
-					return nil, err
-				}
+	rp := path.Join(c.BaseDir, rs.Name)
+	files, err := ioutil.ReadDir(rp)
 
-				output = append(output, o)
+	err = processFiles(c, rs, rp, files, output)
+
+	if err != nil {
+		return meep.New(
+			&TemplateNotFoundError{Name: rs.Name},
+			meep.Cause(err),
+		)
+	}
+
+	return nil
+}
+
+func processFiles(c *context.Context, rs *context.ResourceSet, rp string, files []os.FileInfo, output *[]string) error {
+	for _, file := range files {
+		if !file.IsDir() && isResourceFile(file) {
+			p := path.Join(rp, file.Name())
+			o, err := templateFile(c, rs, p)
+
+			if err != nil {
+				return err
 			}
+
+			*output = append(*output, o)
 		}
 	}
 
-	return output, nil
+	return nil
 }
 
 func templateFile(c *context.Context, rs *context.ResourceSet, filename string) (string, error) {