Skip to content

Commit

Permalink
Merge pull request #28 from sensu/response-code-functionality
Browse files Browse the repository at this point in the history
implementation of response code functionality
  • Loading branch information
chavakula committed Mar 15, 2024
2 parents c10ac4c + b9900fa commit d433fda
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic
Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased
- Added new flag `--response-code` (`-R`) to check expected http status code of a request.

## [0.7.0] - 2022-04-19

Expand Down
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -62,6 +62,7 @@ Flags:
-u, --url string URL to test (default "http://localhost:80/")
-s, --search-string string String to search for, if not provided do status check only
-r, --redirect-ok Allow redirects
-R, --response-code strings check for http response code, if not provided do status check only
-T, --timeout int Request timeout in seconds (default 15)
-H, --header strings Additional header(s) to send in check request
-C, --mtls-cert-file string Certificate file for mutual TLS auth in PEM format
Expand All @@ -79,6 +80,18 @@ Use "http-check [command] --help" for more information about a command.
http-check --url https://sensu.io --search-string Monitoring
http-check OK: found "Monitoring" at https://sensu.io
http-check --url https://sensu.io/notfound --response-code 301
http-check OK: HTTP Status 301 for https://sensu.io/notfound
http-check --url https://sensu.io --response-code 200
http-check OK: HTTP Status 200 for https://sensu.io
http-check --url https://sensu.io/notfound --redirect-ok --response-code 301
http-check CRITICAL: HTTP Status 200 for https://sensu.io/notfound. Expected [301]
http-check --url https://sensu.io/notfound --redirect-ok --response-code 301,401,200
http-check OK: HTTP Status 200 for https://sensu.io/oops
http-check --url https://sensu.io --search-string droids
http-check CRITICAL: "droids" not found at https://sensu.io
Expand All @@ -103,6 +116,7 @@ http-check OK: HTTP Status 200 for http://localhost:8000/health
* When using `--redirect-ok` it affects both the string search and status checkfunctionality.
- For a string search, if true, it searches for the string in the eventual destination.
- For a status check, if false, receiving a redirect will return a `warning` status. If true, it will return an `ok` status.
- When the --response-code option is used in conjunction with --redirect-ok, --response-code will be evaluated for the status of the redirected destination.
* Headers should be in the form of "Header-Name: Header value".

### http-perf
Expand Down
49 changes: 49 additions & 0 deletions cmd/http-check/main.go
Expand Up @@ -10,6 +10,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"

Expand All @@ -23,6 +24,7 @@ type Config struct {
sensu.PluginConfig
URL string
SearchString string
ResponseCode []string
TrustedCAFile string
InsecureSkipVerify bool
RedirectOK bool
Expand Down Expand Up @@ -62,6 +64,15 @@ var (
Usage: "String to search for, if not provided do status check only",
Value: &plugin.SearchString,
},
{
Path: "response-code",
Env: "CHECK_RESPONSE_CODE",
Argument: "response-code",
Shorthand: "R",
Default: []string{},
Usage: "check for http response code, if not provided do status check only",
Value: &plugin.ResponseCode,
},
{
Path: "insecure-skip-verify",
Env: "",
Expand Down Expand Up @@ -145,6 +156,16 @@ func checkArgs(event *types.Event) (int, error) {
}
}
}

if len(plugin.ResponseCode) > 0 {
for _, code := range plugin.ResponseCode {
_, err := strconv.Atoi(code)
if err != nil {
return sensu.CheckStateCritical, fmt.Errorf("--response-code %q value malformed, should be a valid http response code ", code)
}
}
}

if len(plugin.TrustedCAFile) > 0 {
caCertPool, err := corev2.LoadCACerts(plugin.TrustedCAFile)
if err != nil {
Expand Down Expand Up @@ -228,6 +249,25 @@ func executeCheck(event *types.Event) (int, error) {
return sensu.CheckStateCritical, nil
}

// check for response code
if len(plugin.ResponseCode) > 0 {

ExpectedCodes := make([]int, len(plugin.ResponseCode))
for i, s := range plugin.ResponseCode {
ExpectedCodes[i], _ = strconv.Atoi(s)
}

found := contains(ExpectedCodes, resp.StatusCode)

if found {
fmt.Printf("%s OK: HTTP Status %v for %s\n", plugin.PluginConfig.Name, resp.StatusCode, resp.Request.URL)
return sensu.CheckStateOK, nil
} else {
fmt.Printf("%s CRITICAL: HTTP Status %v for %s. Expected %s\n", plugin.PluginConfig.Name, resp.StatusCode, plugin.URL, plugin.ResponseCode)
return sensu.CheckStateCritical, nil
}
}

switch {
case resp.StatusCode >= http.StatusBadRequest:
fmt.Printf("%s CRITICAL: HTTP Status %v for %s\n", plugin.PluginConfig.Name, resp.StatusCode, plugin.URL)
Expand Down Expand Up @@ -255,3 +295,12 @@ func executeCheck(event *types.Event) (int, error) {
return sensu.CheckStateOK, nil
}
}

func contains(s []int, val int) bool {
for _, v := range s {
if v == val {
return true
}
}
return false
}
19 changes: 13 additions & 6 deletions cmd/http-check/main_test.go
Expand Up @@ -6,8 +6,8 @@ import (
"net/url"
"testing"

"github.com/sensu/sensu-plugin-sdk/sensu"
corev2 "github.com/sensu/sensu-go/api/core/v2"
"github.com/sensu/sensu-plugin-sdk/sensu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -50,12 +50,18 @@ func TestExecuteCheck(t *testing.T) {
returnStatus int
httpStatus int
allowRedirect bool
responseCode []string
}{
{sensu.CheckStateOK, http.StatusOK, false},
{sensu.CheckStateOK, http.StatusOK, true},
{sensu.CheckStateWarning, http.StatusMovedPermanently, false},
{sensu.CheckStateCritical, http.StatusBadRequest, false},
{sensu.CheckStateCritical, http.StatusInternalServerError, false},
{sensu.CheckStateOK, http.StatusOK, false, nil},
{sensu.CheckStateOK, http.StatusOK, true, nil},
{sensu.CheckStateCritical, http.StatusNotFound, true, []string{"301"}},
{sensu.CheckStateOK, http.StatusMovedPermanently, false, []string{"301"}},
{sensu.CheckStateOK, http.StatusOK, false, []string{"200"}},
{sensu.CheckStateOK, http.StatusNotFound, false, []string{"200", "404"}},
{sensu.CheckStateOK, http.StatusCreated, false, []string{"200", "201"}},
{sensu.CheckStateWarning, http.StatusMovedPermanently, false, nil},
{sensu.CheckStateCritical, http.StatusBadRequest, false, nil},
{sensu.CheckStateCritical, http.StatusInternalServerError, false, nil},
}

for _, tc := range testCasesStatus {
Expand All @@ -77,6 +83,7 @@ func TestExecuteCheck(t *testing.T) {
plugin.URL = test.URL
plugin.SearchString = ""
plugin.RedirectOK = tc.allowRedirect
plugin.ResponseCode = tc.responseCode
status, err := executeCheck(event)
assert.NoError(err)
assert.Equal(tc.returnStatus, status)
Expand Down

0 comments on commit d433fda

Please sign in to comment.