Skip to content
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
@@ -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
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),
@@ -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

@@ -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

0 comments on commit f103462

Please sign in to comment.
You can’t perform that action at this time.