Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #26 from jaxxstorm/api_support
Browse files Browse the repository at this point in the history
Api support
  • Loading branch information
jaxxstorm authored Jan 10, 2017
2 parents 67d1fc3 + 4e7d2be commit 580448a
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 56 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,34 @@ $ 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](https://sensuapp.org/docs/0.26/api/results-api.html)

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

### Basic Auth Support

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

```shell
$ 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

Make sure your `$GOPATH` is set: https://github.com/golang/go/wiki/GOPATH
Expand Down
20 changes: 20 additions & 0 deletions api/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package api

import "github.com/parnurzeal/gorequest"

func SendResult(url string, json string, username string, password string) (statusCode int, body string, status string) {

// set up a new request
request := gorequest.New()

if username != "" && password != "" {
request.SetBasicAuth(username, password)
}

// set up the url to post to
resp, body, _ := request.Post(url).
Send(json).
End()

return resp.StatusCode, body, resp.Status
}
59 changes: 59 additions & 0 deletions command/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package command

import (
"bytes"
"log"
"os/exec"
"syscall"
"time"
)

func RunCommand(cmdName string, cmdArgs []string, timeout int) (int, string) {

// the command we're going to run
cmd := exec.Command(cmdName, cmdArgs...)

// assign vars for output and stderr
var output bytes.Buffer
var stderr bytes.Buffer

// get the stdout and stderr and assign to pointers
cmd.Stderr = &stderr
cmd.Stdout = &output

// Start the command
if err := cmd.Start(); err != nil {
log.Fatalf("Command not found: %s", cmdName)
}

timer := time.AfterFunc(time.Second*time.Duration(timeout), func() {
if timeout > 0 {
err := cmd.Process.Kill()
if err != nil {
panic(err)
}
}
})

// Here's the good stuff
if err := cmd.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
// Command ! exit 0, capture it
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
// Check it's nagios compliant
if status.ExitStatus() == 1 || status.ExitStatus() == 2 || status.ExitStatus() == 3 {
return status.ExitStatus(), stderr.String()
} else {
// If not, force an exit code 2
return 2, stderr.String()
}
}
} else {
log.Fatalf("cmd.Wait: %v", err)
}
timer.Stop()
}
// We didn't get captured, continue!
return 0, output.String()

}
72 changes: 16 additions & 56 deletions sensu-wrapper.go
Original file line number Diff line number Diff line change
@@ -1,69 +1,17 @@
package main

import (
"bytes"
"./api"
"./command"
"encoding/json"
"fmt"
"gopkg.in/urfave/cli.v1"
"io/ioutil"
"log"
"net"
"os"
"os/exec"
"strings"
"syscall"
"time"
)

func run_command(cmdName string, cmdArgs []string, timeout int) (int, string) {

// the command we're going to run
cmd := exec.Command(cmdName, cmdArgs...)

// assign vars for output and stderr
var output bytes.Buffer
var stderr bytes.Buffer

// get the stdout and stderr and assign to pointers
cmd.Stderr = &stderr
cmd.Stdout = &output

// Start the command
if err := cmd.Start(); err != nil {
log.Fatalf("Command not found: %s", cmdName)
}

timer := time.AfterFunc(time.Second*time.Duration(timeout), func() {
if timeout > 0 {
err := cmd.Process.Kill()
if err != nil {
panic(err)
}
}
})

// Here's the good stuff
if err := cmd.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
// Command ! exit 0, capture it
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
// Check it's nagios compliant
if status.ExitStatus() == 1 || status.ExitStatus() == 2 || status.ExitStatus() == 3 {
return status.ExitStatus(), stderr.String()
} else {
// If not, force an exit code 2
return 2, stderr.String()
}
}
} else {
log.Fatalf("cmd.Wait: %v", err)
}
timer.Stop()
}
// We didn't get captured, continue!
return 0, output.String()
}

func main() {

type Output struct {
Expand All @@ -87,6 +35,9 @@ func main() {
cli.StringSliceFlag{Name: "handlers, H", Usage: "The handlers to use for the check"},
cli.StringFlag{Name: "json-file, f", Usage: "JSON file to read and add to output"},
cli.StringFlag{Name: "json, j", Usage: "JSON string to add to output"},
cli.StringFlag{Name: "api-url, a", Usage: "Send the result to the Sensu API"},
cli.StringFlag{Name: "api-username, u", Usage: "Username for Sensu API"},
cli.StringFlag{Name: "api-password, p", Usage: "Password for Sensu API", EnvVar: "SENSU_API_PASSWORD,SENSU_PASSWORD"},
}

app.Name = "Sensu Wrapper"
Expand Down Expand Up @@ -118,7 +69,7 @@ func main() {
}

// runs the command args
status, output := run_command(c.Args().First(), c.Args().Tail(), timeout)
status, output := command.RunCommand(c.Args().First(), c.Args().Tail(), timeout)

sensu_values := &Output{
Name: c.String("name"),
Expand Down Expand Up @@ -197,6 +148,16 @@ func main() {
if c.Bool("dry-run") {
fmt.Println(string(output_json))
return nil
} else if c.IsSet("api-url") {

code, result, http_status := api.SendResult(c.String("api-url"), string(output_json), c.String("api-username"), c.String("api-password"))
if code == 202 {
fmt.Println(result)
return nil
} else {
fmt.Println("Error sending result to Sensu API:", http_status)
return nil
}
} else {
conn, err := net.Dial("udp", "127.0.0.1:3030")
if err != nil {
Expand All @@ -206,7 +167,6 @@ func main() {
return nil
}
}

}

app.Run(os.Args)
Expand Down

0 comments on commit 580448a

Please sign in to comment.