grim/convey

47df081c14f8
Parents 8c7af5e9a4cc
Children bbf13b21ba8d
Add basic templating for the kubectl commands
--- a/kubectl/README.md Mon Feb 19 17:04:37 2018 -0600
+++ b/kubectl/README.md Tue Feb 20 16:43:51 2018 -0600
@@ -1,7 +1,11 @@
# kubectl
The kubectl package provides tasks for interacting with kubernetes via kubectl.
-It supplies the create, apply, and delete commands.
+It supplies the create, apply, and delete commands. It provides a few
+templating engines that can be used to template your manifests before they're
+used.
+
+If `none` or no engine is specified then no templating is done. An engine of `environment` will do normal variable swapping with the environment variables that convey knows about in the format of `${VARNAME}` or `$VARNAME`.
----
@@ -17,6 +21,7 @@
| files | Yes | | The list of manifest files to apply. |
| namespace | | | The kubernetes namespace to use. |
| selector | | | The selector to use. |
+| engine | | | The template engine to use. |
### Example
@@ -39,6 +44,7 @@
| files | Yes | | The list of manifest files to apply. |
| namespace | | | The kubernetes namespace to use. |
| selector | | | The selector to use. |
+| engine | | | The template engine to use. |
### Example
@@ -61,6 +67,7 @@
| files | Yes | | The list of manifest files to apply. |
| namespace | | | The kubernetes namespace to use. |
| selector | | | The selector to use. |
+| engine | | | The template engine to use. |
### Example
--- a/kubectl/apply.go Mon Feb 19 17:04:37 2018 -0600
+++ b/kubectl/apply.go Tue Feb 20 16:43:51 2018 -0600
@@ -33,6 +33,7 @@
Namespace: a.Namespace,
Files: a.Files,
Selector: a.Selector,
+ Engine: a.Engine,
}
return cmd.Execute(name, "apply", logger, env, st)
--- a/kubectl/command.go Mon Feb 19 17:04:37 2018 -0600
+++ b/kubectl/command.go Tue Feb 20 16:43:51 2018 -0600
@@ -17,6 +17,7 @@
package kubectl
import (
+ "io/ioutil"
"path/filepath"
"github.com/aphistic/gomol"
@@ -34,6 +35,83 @@
Namespace string `yaml:"namespace"`
Files yaml.StringOrSlice `yaml:"files"`
Selector string `yaml:"selector"`
+ Engine string `yaml:"engine"`
+}
+
+// templateNone just copies files from the workspace into the scratch directory.
+func (c *CRUDCommand) templateNone(name, scratchDir string, cmd *command.Generator, logger *gomol.LogAdapter, env []string, st *state.State) error {
+ // update the files we're going to run by joining them with our scratch directory
+ for _, file := range c.Files {
+ realFile, err := environment.Mapper(file, env)
+ if err != nil {
+ return err
+ }
+
+ cmd.Append("-f", filepath.Join(scratchDir, realFile))
+ }
+
+ // now create an export task to get our files out of the workspace
+ export := &docker.Export{
+ Files: c.Files,
+ Path: scratchDir,
+ }
+
+ // make sure the export task is valid
+ err := export.Valid()
+ if err != nil {
+ return err
+ }
+
+ // run the export
+ err = export.Execute(name, logger, env, st)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// templateEnvironment will copy files from the workspace into the scratch
+// directory and replace environment variables with those that convey knows
+// about.
+func (c *CRUDCommand) templateEnvironment(name, scratchDir string, cmd *command.Generator, logger *gomol.LogAdapter, env []string, st *state.State) error {
+ // run the normal export which we will update in place.
+ err := c.templateNone(name, scratchDir, cmd, logger, env, st)
+ if err != nil {
+ return err
+ }
+
+ // now iterate the files and replace all their environment variables with those that we have
+ for _, file := range c.Files {
+ // resolve the filename if it's templated
+ resolvedFile, err := environment.Mapper(file, env)
+ if err != nil {
+ return err
+ }
+
+ // figure out the full path to it
+ absFile := filepath.Join(scratchDir, resolvedFile)
+
+ // read the file
+ raw, err := ioutil.ReadFile(absFile)
+ if err != nil {
+ return err
+ }
+
+ // replace the environment variables in it
+ data, err := environment.Mapper(string(raw), env)
+ if err != nil {
+ return err
+ }
+
+ // write the templated data back out
+ err = ioutil.WriteFile(absFile, []byte(data), 0700)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
}
// Execute runs the given `kubectl` command with the given arguments.
@@ -75,30 +153,19 @@
return err
}
- // update the files we're going to run by joining them with our scratch directory
- for _, file := range c.Files {
- realFile, err := environment.Mapper(file, fullEnv)
- if err != nil {
- return err
- }
-
- cmd.Append("-f", filepath.Join(path, realFile))
+ // run our files through the template engine
+ switch c.Engine {
+ case "":
+ fallthrough
+ case "none":
+ err = c.templateNone(name, path, cmd, logger, fullEnv, st)
+ case "env":
+ fallthrough
+ case "environment":
+ err = c.templateEnvironment(name, path, cmd, logger, fullEnv, st)
}
- // now create an export task to get our files out of the workspace
- export := &docker.Export{
- Files: c.Files,
- Path: path,
- }
-
- // make sure the export task is valid
- err = export.Valid()
- if err != nil {
- return err
- }
-
- // run the export
- err = export.Execute(name, logger, env, st)
+ // if there was an error with templating bail
if err != nil {
return err
}
--- a/kubectl/create.go Mon Feb 19 17:04:37 2018 -0600
+++ b/kubectl/create.go Tue Feb 20 16:43:51 2018 -0600
@@ -33,6 +33,7 @@
Namespace: c.Namespace,
Files: c.Files,
Selector: c.Selector,
+ Engine: c.Engine,
}
return cmd.Execute(name, "create", logger, env, st)
--- a/kubectl/delete.go Mon Feb 19 17:04:37 2018 -0600
+++ b/kubectl/delete.go Tue Feb 20 16:43:51 2018 -0600
@@ -33,6 +33,7 @@
Namespace: d.Namespace,
Files: d.Files,
Selector: d.Selector,
+ Engine: d.Engine,
}
return cmd.Execute(name, "delete", logger, env, st)