/sensu-wrapper

A wrapper to send shell command results to sensu

Primary LanguageGo

Sensu Wrapper

Description

A very small, very crappy go binary which wraps around shell commands and sends the result to a local sensu socket as an event.

It's heavily inspired by @solarkennedy's sensu-shell-helper but written in Go and with additional options like TTL support.

The original was in ruby, which didn't really suit the task.

The ruby version coding inspiration is from @agent462's sensu-cli so it may look familiar in certain parts.

Usage

NAME:
   Sensu Wrapper - Execute a command and send the result to a sensu socket

USAGE:
   main [global options] command [command options] [arguments...]

VERSION:
   0.3.3

AUTHOR:
   Lee Briggs

COMMANDS:
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --dry-run, -D, -d                   Output to stdout or not
   --name value, -N value, -n value    The name of the check
   --ttl value, -t value               The TTL for the check (default: 0)
   --timeout value, -T value           Amount of time before the command times out (default: 0)
   --source value, -S value, -s value  The source of the check
   --handlers value, -H value          The handlers to use for the check
   --json-file value, -f value         JSON file to read and add to output
   --json value, -j value              JSON string to add to output
   --api-url value, -a value           Send the result to the Sensu API
   --api-port value                    Port for the sensu API (default: 4567)
   --api-tls                           Whether to use TLS for calls to API
   --api-username value, -u value      Username for Sensu API
   --api-password value, -p value      Password for Sensu API [$SENSU_API_PASSWORD, $SENSU_PASSWORD]
   --help, -h                          show help
   --version, -v                       print the version

Basic Example

The minimum required is a name and a command to run. The command isn't a flag, it will just take any arguments from the invocation.

This will send a sensu event to localhost port 3030 for sensu's local socket to process.

$ sensu-wrapper -d -n "testing" /bin/echo hello

You can check the output of the JSON that it will send to sensu with --dry-run

$ sensu-wrapper -d -n "testing" /bin/echo hello
{"name":"testing","status":0,"output":"hello\n"}

JIT Clients

If you want to send the event from a client different to the client the check is running on, use the source option

$ sensu-wrapper -n "name" -d -s "mynewclientname" /bin/false
{"name":"name","command":"/bin/false","status":2,"output":"false","handler":[],"source":"mynewclientname","duration":0.0}

TTL

If you need to hear from your check every so often and it hasn't called, pass the TTL option (seconds) with -T Sensu will create an event if it hasn't checked within its TTL.

$ sensu-wrapper -d -n "name" -d -t 60 /bin/echo hello
{"name":"name","status":0,"output":"hello\n","ttl":60}

Timeout

By default, commands will continue to run until they finish. If you wish to adjust that, specify the timeout flag:

$ sensu-wrapper -d -n "name" -d -T 25 ping 8.8.8.8
{"name":"name","status":0,"output":"hello\n"}

If a command is killed due to timeout, it's assumed to have failed and will return exit code 2

Extra JSON

Many people who use Sensu will add arbitrary JSON fields to their checks which are then used in handlers. sensu-wrapper supports this in two ways.

First, you can add JSON by specifying the path to a file to read in which will then be sent in the check. For example you might have a file like so:

# /tmp/mycheck.json
{
    "environment": "production",
    "runbook": "http://url",
    "message": "there is a problem"
}

You can specify this file with the -f flag and it'll get appended to any output:

$ sensu-wrapper -n "testing" -f /tmp/json -H default -d --ttl 30 -source "mycheck" /bin/echo hello
{"command":"/bin/echo hello","environment":"production","handlers":["default"],"message":"there is a problem","name":"testing","output":"hello\n","runbook":"http://url","source":"mycheck","status":0,"ttl":30}

Alternatively, you can specify JSON directly as a string:

$ sensu-wrapper -d -n "testing" -j '{"test_field": "hello"}' /bin/echo 'hello'
{"command":"/bin/echo hello","name":"testing","output":"hello\n","status":0,"test_field":"hello"}

Send to API

Sometimes, the place you choose to run sensu-wrapper may not have a local sensu client available.

For these clients, you can now post the result JSON to the Sensu Results API

$ sensu-wrapper -a "my-sensu-api.example.net" /bin/echo 'hello'
{"issued":1484052388}

If you need TLS, or you want to change the port to send API http requests to, you can do that too:

$ sensu-wrapper -a "my-sensu-api.example.net" --api-port 4568 --api-tls /bin/echo 'hello'
{"issued":1484052388}

Note: This doesn't take care of verification of the TLS endpoint. You'll need to trust the cert on the API

Basic Auth Support

The Sensu API can be secured with a username and password. For these instances, you can specify a username and password:

$ sensu-wrapper -a "http://my-sensu-api.example.net:4567/results" -u sensu -p correct-horse-battery-staple /bin/echo 'hello'
{"issued":1484052384}
Environment Variables

If you don't want to set the sensu api password on the command line, you can use environment variables. Just set either SENSU_API_PASSWORD or SENSU_PASSWORD

$ export SENSU_API_PASSWORD="changeme"
$ sensu-wrapper -a "http://my-sensu-api.example.net:4567/results" -u sensu /bin/echo 'hello'
{"issued":1484052394}

Building

The project uses glide for dependencies.

Make sure your $GOPATH is set: https://github.com/golang/go/wiki/GOPATH Install the dependencies

glide install

Build it!

go build main.go

That's it!

Important Notes

  • This thing is designed to run arbitrary shell commands without any escaping or safety mechanisms. It's not very safe at all.
  • This thing has absolutely no locking. If you need to lock commands, I suggest you use flock(2)
  • The performance of this thing hasn't been tested at all. It's running shell commands from within golang, make of that what you will.
  • This is terrible code.

Contributing

Please sent pull requests, I am a terrible developer and anyone who can make this better will be thanked greatly. Also, spec tests. If you fancy helping me write tests, that would also be greatly appreciated, I'm kinda new to this game.