What is Goss?
Goss is a YAML based server testing tool written in Go.
It checks statuses of process, ports and else.
Goss - Quick and Easy server validation
Goss in 45 seconds
Note: For testing containers see the dgoss wrapper. Also, user submitted wrapper scripts for Kubernetes kgoss and Docker Compose dcgoss.
Note: For some Docker/Kubernetes healthcheck, health endpoint, and container ordering examples, see my blog post here.
Introduction
What is Goss?
Goss is a YAML based serverspec alternative tool for validating a server's configuration. It eases the process of writing tests by allowing the user to generate tests from the current system state. Once the test suite is written they can be executed, waited-on, or served as a health endpoint.
Why use Goss?
- Goss is EASY! - Goss in 45 seconds
- Goss is FAST! - small-medium test suites are near instantaneous, see benchmarks
- Goss is SMALL! - <10MB single self-contained binary
Installation
Note: For macOS and Windows, see: platform-feature-parity.
This will install goss and dgoss.
…
Differences from Serverspec
As it is Serverspec alternative tool, there are some differences between them.
Pros of Goss
Easier to write as it is YAML
Tests can be defined by a single YAML file, easier to manage and doesn't require much time to learn.
Able to create test suite within a second.
Goss provides a command to define a test state automatically.
Easy to install
Goss comes with one single binary so no need to think about dependency.
Pros of Serverspec
Executable from remote
Like Ansible or Chef, able to execute from a remote node with SSH
More Resources
Goss supports about 20 Resources but Serverspec has twice (as of Mar 28th, 2019)
More flexible
Serverspec is more flexible as it allows us to code with Ruby.
Let's try
CentOS 7.5.1804 on Vagrant.
Goss v0.3.6.
Install
A script is prepared officially so it cannot be easier to install.
Also, dgoss
which is a command for Docker container would be installed but I am not going to use it this time.
And please be noted that the script is not recommended for production environment.
Try manual install instead.
[vagrant@Vag2] ~
% curl -fsSL https://goss.rocks/install | sudo sh
Downloading https://github.com/aelsabbahy/goss/releases/download/v0.3.6/goss-linux-amd64
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 606 0 606 0 0 808 0 --:--:-- --:--:-- --:--:-- 809
100 8324k 100 8324k 0 0 236k 0 0:00:35 0:00:35 --:--:-- 240k
Goss v0.3.6 has been installed to /usr/local/bin/goss
goss --version
goss version v0.3.6
Downloading https://raw.githubusercontent.com/aelsabbahy/goss/master/extras/dgoss/dgoss
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3803 100 3803 0 0 9722 0 --:--:-- --:--:-- --:--:-- 9726
dgoss master has been installed to /usr/local/bin/dgoss
[vagrant@Vag2] ~
% which goss
/usr/local/bin/goss
[vagrant@Vag2] ~
%
Create a test suite
As I mentioned earlier, Goss has commands to create a test suite automatically.
goss.yaml will be created by goss autoadd
or goss add [resource]
.
In this post, I will work on a host which HAProxy is installed.
[vagrant@Vag2] ~/work
% goss autoadd haproxy
Adding Group to './goss.yaml':
haproxy:
exists: true
gid: 188
Adding Package to './goss.yaml':
haproxy:
installed: true
versions:
- 1.5.18
Adding Process to './goss.yaml':
haproxy:
running: true
Adding Service to './goss.yaml':
haproxy:
enabled: true
running: true
Adding User to './goss.yaml':
haproxy:
exists: true
uid: 188
gid: 188
groups:
- haproxy
home: /var/lib/haproxy
shell: /sbin/nologin
[vagrant@Vag2] ~/work
%
After goss autoadd
, the created goss.yaml is here.
[vagrant@Vag2] ~/work
% ls -l goss.yaml
-rw-r--r-- 1 vagrant vagrant 347 Mar 23 03:55 goss.yaml
[vagrant@Vag2] ~/work
% cat goss.yaml
package:
haproxy:
installed: true
versions:
- 1.5.18
service:
haproxy:
enabled: true
running: true
user:
haproxy:
exists: true
uid: 188
gid: 188
groups:
- haproxy
home: /var/lib/haproxy
shell: /sbin/nologin
group:
haproxy:
exists: true
gid: 188
process:
haproxy:
running: true
[vagrant@Vag2] ~/work
%
Just a single command, below test items are created.
Test items vary on the target.
Installed packages
is-active, is-enabled of service
User definition
Group definition
Process status
You can use add [resource]
command to specify each item one by one.
Test execution
Success
Then Let's try testing.
Of course, it is easy to execute.
[vagrant@Vag2] ~/work
% goss validate
.............
Total Duration: 0.033s
Count: 13, Failed: 0, Skipped: 0
[vagrant@Vag2] ~/work
%
Each dots(...) mean each test.
The speed of the test is incredible.
It takes only 0.033 sec to test 13 items.
Fail
So next, we let the test fail.
Stopped the process.
[vagrant@Vag2] ~/work
% sudo systemctl stop haproxy
[vagrant@Vag2] ~/work
% sudo systemctl is-active haproxy
inactive
zsh: exit 3 sudo systemctl is-active haproxy
[vagrant@Vag2] ~/work
%
Then retry.
[vagrant@Vag2] ~/work
% goss validate
..F.........F
Failures/Skipped:
Process: haproxy: running:
Expected
<bool>: false
to equal
<bool>: true
Service: haproxy: running:
Expected
<bool>: false
to equal
<bool>: true
Total Duration: 0.051s
Count: 13, Failed: 2, Skipped: 0
zsh: exit 1 goss validate
[vagrant@Vag2] ~/work
%
As expected, process/service checks failed.
Changing format
Goss has several formats to output the result.
It has like JSON, and tap is the most human readable I think.
[vagrant@Vag2] ~/work
% goss validate --format tap
1..13
ok 1 - Group: haproxy: exists: matches expectation: [true]
ok 2 - Group: haproxy: gid: matches expectation: [188]
not ok 3 - Process: haproxy: running: doesn't match, expect: [true] found: [false]
ok 4 - User: haproxy: exists: matches expectation: [true]
ok 5 - User: haproxy: uid: matches expectation: [188]
ok 6 - User: haproxy: gid: matches expectation: [188]
ok 7 - User: haproxy: home: matches expectation: ["/var/lib/haproxy"]
ok 8 - User: haproxy: groups: matches expectation: [["haproxy"]]
ok 9 - User: haproxy: shell: matches expectation: ["/sbin/nologin"]
ok 10 - Package: haproxy: installed: matches expectation: [true]
ok 11 - Package: haproxy: version: matches expectation: [["1.5.18"]]
ok 12 - Service: haproxy: enabled: matches expectation: [true]
not ok 13 - Service: haproxy: running: doesn't match, expect: [true] found: [false]
zsh: exit 1 goss validate --format tap
[vagrant@Vag2] ~/work
%
Check with http
Goss can serve http mode and work as Healthcheck endpoint.
[vagrant@Vag2] ~/work
% goss serve &
2019/03/23 04:00:20 Starting to listen on: :8080
[vagrant@Vag2] ~/work
% curl localhost:8080/healthz
2019/03/23 04:00:23 [::1]:48704: requesting health probe
2019/03/23 04:00:23 [::1]:48704: Stale cache, running tests
..F.........F
Failures/Skipped:
Process: haproxy: running:
Expected
<bool>: false
to equal
<bool>: true
Service: haproxy: running:
Expected
<bool>: false
to equal
<bool>: true
Total Duration: 0.044s
Count: 13, Failed: 2, Skipped: 0
[vagrant@Vag2] ~/work
%
Conclusion
As I tried, Goss is extremely great since it allows us to test within a minute.
In this post, it was only a simple test but it can be applied to production environment with more customize.
I assume Ansible can be a good match with Goss when comes to production use.
Or maybe it can extend monitoring accuracy with Goss healthcheck mode.
Top comments (1)
Hi , thanks for the goss overview . You can also consider Bird - Linux servers validation tool, written on Raku (former Perl6). See my announcement on yc - news.ycombinator.com/item?id=28064404