Permalink
Browse files

Template Support (#200)

Add text/template support to goss to allow using conditions, var files, and environment variables (see README and manual changes).

* text/template support
* Update tests to use text/template
* Update documentation
  • Loading branch information...
aelsabbahy committed Mar 6, 2017
1 parent 5ceba07 commit f10346230ee7296f32ceb333fc0c928fa73d0a59
View
@@ -104,6 +104,11 @@ Total Duration: 0.021s # <- yeah, it's that fast..
Count: 15, Failed: 0
```
+* Edit it to use [templates](https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#templates), and run with a vars file
+```
+goss --vars vars.yaml validate
+```
+
* keep running it until the system enters a valid state or we timeout
```
goss validate --retry-timeout 30s --sleep 1s
@@ -118,10 +123,11 @@ goss serve --format json &
curl localhost:8080/healthz
```
-### Patterns, matchers and metadata
-Goss files can be manually edited to match:
+### Manually editing Goss files
+Goss files can be manually edited to use:
* [Patterns](https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#patterns)
-* [Advanced Matchers](https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#advanced-matchers).
+* [Advanced Matchers](https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#advanced-matchers)
+* [Templates](https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#templates)
* `title` and `meta` (arbitrary data) attributes are persisted when adding other resources with `goss add`
Some examples:
@@ -153,6 +159,16 @@ package:
- have-len: 3
- not:
contain-element: 4.4.0
+
+ # Loaded from --vars YAML/JSON file
+ {{.Vars.package}}:
+ installed: true
+
+{{if eq .Env.OS "centos"}}
+ # This test is only when $OS environment variable is set to "centos"
+ libselinux:
+ installed: true
+{{end}}
```
## Supported resources
View
4 add.go
@@ -14,7 +14,7 @@ import (
// Simple wrapper to add multiple resources
func AddResources(fileName, resourceName string, keys []string, c *cli.Context) error {
- setStoreFormatFromFileName(fileName)
+ OutStoreFormat = getStoreFormatFromFileName(fileName)
config := util.Config{
IgnoreList: c.GlobalStringSlice("exclude-attr"),
Timeout: int(c.Duration("timeout") / time.Millisecond),
@@ -159,7 +159,7 @@ func AddResource(fileName string, gossConfig GossConfig, resourceName, key strin
// Simple wrapper to add multiple resources
func AutoAddResources(fileName string, keys []string, c *cli.Context) error {
- setStoreFormatFromFileName(fileName)
+ OutStoreFormat = getStoreFormatFromFileName(fileName)
config := util.Config{
IgnoreList: c.GlobalStringSlice("exclude-attr"),
Timeout: int(c.Duration("timeout") / time.Millisecond),
View
@@ -27,6 +27,11 @@ func main() {
Usage: "Goss file to read from / write to",
EnvVar: "GOSS_FILE",
},
+ cli.StringFlag{
+ Name: "vars",
+ Usage: "json/yaml file containing variables for template",
+ EnvVar: "GOSS_VARS",
+ },
cli.StringFlag{
Name: "package",
Usage: "Package type to use [rpm, deb, apk, pacman]",
@@ -118,8 +123,14 @@ func main() {
Name: "render",
Aliases: []string{"r"},
Usage: "render gossfile after imports",
+ Flags: []cli.Flag{
+ cli.BoolFlag{
+ Name: "debug, d",
+ Usage: fmt.Sprintf("Print debugging info when rendering"),
+ },
+ },
Action: func(c *cli.Context) error {
- fmt.Print(goss.RenderJSON(c.GlobalString("gossfile")))
+ fmt.Print(goss.RenderJSON(c))
return nil
},
},
@@ -7,6 +7,7 @@ INTEGRATION_TEST_DIR="$SCRIPT_DIR/../integration-tests/"
for docker_file in $INTEGRATION_TEST_DIR/Dockerfile_*; do
+ [[ $docker_file == *.md5 ]] && continue
os=$(cut -d '_' -f2 <<<"$docker_file")
docker build -t "aelsabbahy/goss_${os}:latest" - < "$docker_file"
done
@@ -16,4 +16,3 @@ popd
for image in $images; do
docker push "${image}:latest"
done
-
View
@@ -14,6 +14,7 @@
* [validate, v \- Validate the system](#validate-v---validate-the-system)
* [Important note about goss file format](#important-note-about-goss-file-format)
* [Available tests](#available-tests)
+ * [addr](#addr)
* [command](#command)
* [dns](#dns)
* [file](#file)
@@ -30,7 +31,7 @@
* [user](#user)
* [Patterns](#patterns)
* [Advanced Matchers](#advanced-matchers)
-
+* [Templates](#templates)
## Usage
@@ -54,6 +55,7 @@ COMMANDS:
GLOBAL OPTIONS:
--gossfile, -g "./goss.yaml" Goss file to read from / write to [$GOSS_FILE]
+ --vars value json/yaml file containing variables for template [$GOSS_VARS]
--package Package type to use [rpm, deb, apk, pacman]
--help, -h show help
--generate-bash-completion
@@ -71,6 +73,13 @@ Valid formats:
* **YAML** (default)
* **JSON**
+### --vars
+The file to read variables from when rendering gossfile [templates](#templates).
+
+Valid formats:
+* **YAML** (default)
+* **JSON**
+
### --package <type>
The package type to check for.
@@ -188,6 +197,10 @@ process:
### render, r - Render gossfile after importing all referenced gossfiles
This command allows you to keep your tests separated and render a single, valid, gossfile, by including them with the `gossfile` directive.
+#### Flags
+##### --debug
+This prints the rendered golang template prior to printing the parsed JSON/YAML gossfile.
+
#### Example:
```bash
@@ -676,7 +689,7 @@ For the attributes that use patterns (ex. `file`, `command` `output`), each patt
**NOTE:** Pattern attributes do not support [Advanced Matchers](#advanced-matchers)
-**NOTE:** Regex support is based on golangs regex engine documented [here](https://golang.org/pkg/regexp/syntax/)
+**NOTE:** Regex support is based on golang's regex engine documented [here](https://golang.org/pkg/regexp/syntax/)
**NOTE:** You will **need** the double backslash (`\\`) escape for Regex special entities, for example `\\s` for blank spaces.
@@ -738,3 +751,97 @@ package:
For more information see:
* [gomega_test.go](https://github.com/aelsabbahy/goss/blob/master/resource/gomega_test.go) - For a complete set of supported json -> Gomega mapping
* [gomega](https://onsi.github.io/gomega/) - Gomega matchers reference
+
+## Templates
+
+Goss test files can leverage golang's [text/template](https://golang.org/pkg/text/template/) to allow for dynamic or conditional tests.
+
+Available variables:
+* `{{.Env}}` - Containing environment variables
+* `{{.Vars}}` - Containing the values defined in [--vars](#global-options) file
+
+Available functions beyond text/template [built-in functions](https://golang.org/pkg/text/template/#hdr-Functions):
+* `mkSlice` - Retuns a slice of all the arguments. See examples below for usage.
+
+**NOTE:** gossfiles containing text/template `{{}}` controls will no longer work with `goss add/autoadd`. One way to get around this is to split your template and static goss files and use [gossfile](#gossfile) to import.
+
+### Examples
+
+Using [puppetlabs/facter](https://github.com/puppetlabs/facter) or [chef/ohai](https://github.com/chef/ohai) as external tools to provide vars.
+```bash
+$ goss --vars <(ohai) validate
+$ goss --vars <(facter -j) validate
+```
+
+Using `mkSlice` to define a loop locally.
+```yaml
+file:
+{{- range mkSlice "/etc/passwd" "/etc/group"}}
+ {{.}}:
+ exists: true
+ mode: "0644"
+ owner: root
+ group: root
+ filetype: file
+{{end}}
+```
+
+Using Env variables and a vars file:
+
+**vars.yaml:**
+```yaml
+centos:
+ packages:
+ kernel:
+ - "4.9.11-centos"
+ - "4.9.11-centos2"
+debian:
+ packages:
+ kernel:
+ - "4.9.11-debian"
+ - "4.9.11-debian2"
+users:
+ - user1
+ - user2
+```
+
+**goss.yaml:**
+```yaml
+package:
+# Looping over a variables defined in a vars.yaml using $OS environment variable as a lookup key
+{{range $name, $vers := index .Vars .Env.OS "packages"}}
+ {{$name}}:
+ installed: true
+ versions:
+ {{range $vers}}
+ - {{.}}
+ {{end}}
+{{end}}
+
+# This test is only when OS=centos variable is defined
+{{if eq .Env.OS "centos"}}
+ libselinux:
+ installed: true
+{{end}}
+
+# Loop over users
+user:
+{{range .Vars.users}}
+ {{.}}:
+ exists: true
+ groups:
+ - {{.}}
+ home: /home/{{.}}
+ shell: /bin/bash
+{{end}}
+```
+
+Rendered results:
+```bash
+# To validate:
+$ OS=centos goss --vars vars.yaml validate
+# To render:
+$ OS=centos goss --vars vars.yaml render
+# To render with debugging enabled:
+$ OS=centos goss --vars vars.yaml render --debug
+```
@@ -1 +1 @@
-b430b4a6a2ea84679f9ae705a65b2c25 Dockerfile_arch
+f73a8fa9e9c0940ce2bfc09c13c3aaf5 Dockerfile_arch
@@ -1,13 +1,5 @@
---
-package:
- apache2:
- installed: true
- versions:
- - 2.4.23-r1
service:
- apache2:
- enabled: true
- running: true
autofs:
enabled: false
running: false
@@ -1,13 +1,5 @@
---
-package:
- httpd:
- installed: true
- versions:
- - 2.4.6
service:
- httpd:
- enabled: true
- running: true
autofs:
enabled: false
running: false
@@ -3,3 +3,10 @@ service:
foobar:
enabled: false
running: false
+{{if eq .Env.OS "centos7"}}
+ httpd:
+{{else}}
+ apache2:
+{{end}}
+ enabled: true
+ running: true
@@ -11,14 +11,16 @@ command:
stderr:
- not found
file:
- "/etc/passwd":
+{{range mkSlice "/etc/passwd" "/etc/group"}}
+ {{.}}:
exists: true
mode: '0644'
owner: root
group: root
filetype: file
contains:
- root
+{{end}}
"/goss/hellogoss.txt":
exists: true
md5: 7c9bb14b3bf178e82c00c2a4398c93cd
@@ -34,6 +36,12 @@ file:
package:
foobar:
installed: false
+{{- range $name, $ver := index .Vars .Env.OS "packages"}}
+ {{$name}}:
+ installed: true
+ versions:
+ - {{$ver}}
+{{end}}
addr:
tcp://google.com:22:
reachable: false
@@ -1,13 +1,5 @@
---
-package:
- apache2:
- installed: true
- versions:
- - 2.2.22-1ubuntu1.11
service:
- apache2:
- enabled: true
- running: true
autofs:
enabled: true
running: true
@@ -0,0 +1,15 @@
+---
+alpine3:
+ packages:
+ apache2: "2.4.23-r1"
+arch:
+ packages:
+centos7:
+ packages:
+ httpd: "2.4.6"
+precise:
+ packages:
+ apache2: "2.2.22-1ubuntu1.11"
+wheezy:
+ packages:
+ apache2: "2.2.22-13+deb7u7"
@@ -1,13 +1,5 @@
---
-package:
- apache2:
- installed: true
- versions:
- - 2.2.22-13+deb7u7
service:
- apache2:
- enabled: true
- running: true
autofs:
enabled: false
running: false
Oops, something went wrong.

0 comments on commit f103462

Please sign in to comment.