From 8e08a282eb4f29618c8de8090927b521ea0c9c2b Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Wed, 8 Feb 2017 16:44:55 +0100 Subject: [PATCH] feat templater: Add ability to exclude resource sets * renamed --limit to --include (-i) * added --exclude (-e) Kontemplate users can now explicitly include and exclude certain resource sets. Excludes always override includes. Closes #11 --- main.go | 23 +++++++++----- templater/templater.go | 68 +++++++++++++++++++++++++++++------------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/main.go b/main.go index 1a775bf7c..f6e492143 100644 --- a/main.go +++ b/main.go @@ -37,9 +37,10 @@ func templateCommand() cli.Command { Usage: "Interpolate and print templates", Flags: commonFlags(), Action: func(c *cli.Context) error { - limit := c.StringSlice("limit") + include := c.StringSlice("include") + exclude := c.StringSlice("exclude") ctx, err := loadContext(c) - resources, err := templater.LoadAndPrepareTemplates(&limit, ctx) + resources, err := templater.LoadAndPrepareTemplates(&include, &exclude, ctx) if err != nil { return err @@ -66,9 +67,10 @@ func applyCommand() cli.Command { Destination: &dryRun, }), Action: func(c *cli.Context) error { - limit := c.StringSlice("limit") + include := c.StringSlice("include") + exclude := c.StringSlice("exclude") ctx, err := loadContext(c) - resources, err := templater.LoadAndPrepareTemplates(&limit, ctx) + resources, err := templater.LoadAndPrepareTemplates(&include, &exclude, ctx) if err != nil { return err @@ -92,9 +94,10 @@ func replaceCommand() cli.Command { Usage: "Interpolate templates and run 'kubectl replace'", Flags: commonFlags(), Action: func(c *cli.Context) error { - limit := c.StringSlice("limit") + include := c.StringSlice("include") + exclude := c.StringSlice("exclude") ctx, err := loadContext(c) - resources, err := templater.LoadAndPrepareTemplates(&limit, ctx) + resources, err := templater.LoadAndPrepareTemplates(&include, &exclude, ctx) if err != nil { return err @@ -140,8 +143,12 @@ func commonFlags() []cli.Flag { Usage: "Cluster configuration file to use", }, cli.StringSliceFlag{ - Name: "limit, l", - Usage: "Limit templating to certain resource sets", + Name: "include, i", + Usage: "Limit templating to explicitly included resource sets", + }, + cli.StringSliceFlag{ + Name: "exclude, e", + Usage: "Exclude certain resource sets from templating", }, } } diff --git a/templater/templater.go b/templater/templater.go index 6e443c14b..bb65cd1df 100644 --- a/templater/templater.go +++ b/templater/templater.go @@ -26,34 +26,20 @@ type TemplatingError struct { meep.AllTraits } -func LoadAndPrepareTemplates(limit *[]string, c *context.Context) (output []string, err error) { - for _, rs := range c.ResourceSets { - if resourceSetIncluded(limit, &rs.Name) { - err = processResourceSet(c, &rs, &output) +func LoadAndPrepareTemplates(include *[]string, exclude *[]string, c *context.Context) (output []string, err error) { + limitedResourceSets := applyLimits(&c.ResourceSets, include, exclude) - if err != nil { - return - } + for _, rs := range *limitedResourceSets { + err = processResourceSet(c, &rs, &output) + + if err != nil { + return } } return } -func resourceSetIncluded(limit *[]string, resourceSetName *string) bool { - if len(*limit) == 0 { - return true - } - - for _, name := range *limit { - if name == *resourceSetName { - return true - } - } - - return false -} - func processResourceSet(c *context.Context, rs *context.ResourceSet, output *[]string) error { fmt.Fprintf(os.Stderr, "Loading resources for %s\n", rs.Name) @@ -125,6 +111,46 @@ func templateFile(c *context.Context, rs *context.ResourceSet, filename string) return b.String(), nil } +// Applies the limits of explicitly included or excluded resources and returns the updated resource set. +// Exclude takes priority over include +func applyLimits(rs *[]context.ResourceSet, include *[]string, exclude *[]string) *[]context.ResourceSet { + if len(*include) == 0 && len(*exclude) == 0 { + return rs + } + + // Exclude excluded resource sets + excluded := make([]context.ResourceSet, 0) + for _, r := range *rs { + if !contains(exclude, &r.Name) { + excluded = append(excluded, r) + } + } + + // Include included resource sets + if len(*include) == 0 { + return &excluded + } + included := make([]context.ResourceSet, 0) + for _, r := range excluded { + if contains(include, &r.Name) { + included = append(included, r) + } + } + + return &included +} + +// Check whether a certain string is contained in a string slice +func contains(s *[]string, v *string) bool { + for _, r := range *s { + if r == *v { + return true + } + } + + return false +} + func templateFuncs() template.FuncMap { m := sprig.TxtFuncMap() m["json"] = func(data interface{}) string {