--- /dev/null
+package main
+
+import (
+ "fmt"
+ logpkg "log"
+ "os"
+ "strconv"
+
+ "github.com/DreamItGetIT/statuscake"
+)
+
+var log *logpkg.Logger
+
+type command func(*statuscake.Client, ...string) error
+
+var commands map[string]command
+
+func init() {
+ log = logpkg.New(os.Stderr, "", 0)
+ commands = map[string]command{
+ "list": cmdList,
+ "detail": cmdDetail,
+ "delete": cmdDelete,
+ "create": cmdCreate,
+ "update": cmdUpdate,
+ }
+}
+
+func colouredStatus(s string) string {
+ switch s {
+ case "Up":
+ return fmt.Sprintf("\033[0;32m%s\033[0m", s)
+ case "Down":
+ return fmt.Sprintf("\033[0;31m%s\033[0m", s)
+ default:
+ return s
+ }
+}
+
+func getEnv(name string) string {
+ v := os.Getenv(name)
+ if v == "" {
+ log.Fatalf("`%s` env variable is required", name)
+ }
+
+ return v
+}
+
+func cmdList(c *statuscake.Client, args ...string) error {
+ tt := c.Tests()
+ tests, err := tt.All()
+ if err != nil {
+ return err
+ }
+
+ for _, t := range tests {
+ var paused string
+ if t.Paused {
+ paused = "yes"
+ } else {
+ paused = "no"
+ }
+
+ fmt.Printf("* %d: %s\n", t.TestID, colouredStatus(t.Status))
+ fmt.Printf(" WebsiteName: %s\n", t.WebsiteName)
+ fmt.Printf(" TestType: %s\n", t.TestType)
+ fmt.Printf(" Paused: %s\n", paused)
+ fmt.Printf(" ContactID: %d\n", t.ContactID)
+ fmt.Printf(" Uptime: %f\n", t.Uptime)
+ }
+
+ return nil
+}
+
+func cmdDetail(c *statuscake.Client, args ...string) error {
+ if len(args) != 1 {
+ return fmt.Errorf("command `detail` requires a single argument `TestID`")
+ }
+
+ id, err := strconv.Atoi(args[0])
+ if err != nil {
+ return err
+ }
+
+ tt := c.Tests()
+ t, err := tt.Detail(id)
+ if err != nil {
+ return err
+ }
+
+ var paused string
+ if t.Paused {
+ paused = "yes"
+ } else {
+ paused = "no"
+ }
+
+ fmt.Printf("* %d: %s\n", t.TestID, colouredStatus(t.Status))
+ fmt.Printf(" WebsiteName: %s\n", t.WebsiteName)
+ fmt.Printf(" WebsiteURL: %s\n", t.WebsiteURL)
+ fmt.Printf(" PingURL: %s\n", t.PingURL)
+ fmt.Printf(" TestType: %s\n", t.TestType)
+ fmt.Printf(" Paused: %s\n", paused)
+ fmt.Printf(" ContactID: %d\n", t.ContactID)
+ fmt.Printf(" Uptime: %f\n", t.Uptime)
+
+ return nil
+}
+
+func cmdDelete(c *statuscake.Client, args ...string) error {
+ if len(args) != 1 {
+ return fmt.Errorf("command `delete` requires a single argument `TestID`")
+ }
+
+ id, err := strconv.Atoi(args[0])
+ if err != nil {
+ return err
+ }
+
+ return c.Tests().Delete(id)
+}
+
+func askString(name string) string {
+ var v string
+
+ fmt.Printf("%s: ", name)
+ _, err := fmt.Scanln(&v)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return v
+}
+
+func askInt(name string) int {
+ v := askString(name)
+ i, err := strconv.Atoi(v)
+ if err != nil {
+ log.Fatalf("Invalid number `%s`", v)
+ }
+
+ return i
+}
+
+func cmdCreate(c *statuscake.Client, args ...string) error {
+ t := &statuscake.Test{
+ WebsiteName: askString("WebsiteName"),
+ WebsiteURL: askString("WebsiteURL"),
+ TestType: askString("TestType"),
+ CheckRate: askInt("CheckRate"),
+ }
+
+ t2, err := c.Tests().Update(t)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("CREATED: \n%+v\n", t2)
+
+ return nil
+}
+
+func cmdUpdate(c *statuscake.Client, args ...string) error {
+ if len(args) != 1 {
+ return fmt.Errorf("command `update` requires a single argument `TestID`")
+ }
+
+ id, err := strconv.Atoi(args[0])
+ if err != nil {
+ return err
+ }
+
+ tt := c.Tests()
+ t, err := tt.Detail(id)
+ if err != nil {
+ return err
+ }
+
+ t.TestID = id
+ t.WebsiteName = askString(fmt.Sprintf("WebsiteName [%s]", t.WebsiteName))
+ t.WebsiteURL = askString(fmt.Sprintf("WebsiteURL [%s]", t.WebsiteURL))
+ t.TestType = askString(fmt.Sprintf("TestType [%s]", t.TestType))
+ t.CheckRate = askInt(fmt.Sprintf("CheckRate [%d]", t.CheckRate))
+
+ t2, err := c.Tests().Update(t)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("UPDATED: \n%+v\n", t2)
+
+ return nil
+}
+
+func usage() {
+ fmt.Printf("Usage:\n")
+ fmt.Printf(" %s COMMAND\n", os.Args[0])
+ fmt.Printf("Available commands:\n")
+ for k := range commands {
+ fmt.Printf(" %+v\n", k)
+ }
+}
+
+func main() {
+ username := getEnv("STATUSCAKE_USERNAME")
+ apikey := getEnv("STATUSCAKE_APIKEY")
+
+ if len(os.Args) < 2 {
+ usage()
+ os.Exit(1)
+ }
+
+ var err error
+
+ c, err := statuscake.New(statuscake.Auth{Username: username, Apikey: apikey})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if cmd, ok := commands[os.Args[1]]; ok {
+ err = cmd(c, os.Args[2:]...)
+ } else {
+ err = fmt.Errorf("Unknown command `%s`", os.Args[1])
+ }
+
+ if err != nil {
+ log.Fatalf("Error running command `%s`: %s", os.Args[1], err.Error())
+ }
+}
--- /dev/null
+{
+ "ErrNo": 0,
+ "Error": "Can not access account. Was both Username and API Key provided?"
+}
--- /dev/null
+[
+ {
+ "TestID": 100,
+ "Paused": false,
+ "TestType": "HTTP",
+ "WebsiteName": "www 1",
+ "ContactGroup": null,
+ "ContactID": "1",
+ "Status": "Up",
+ "Uptime": 100
+ },
+ {
+ "TestID": 101,
+ "Paused": true,
+ "TestType": "HTTP",
+ "WebsiteName": "www 2",
+ "ContactGroup": null,
+ "ContactID": "2",
+ "Status": "Down",
+ "Uptime": 0
+ }
+]
--- /dev/null
+{
+ "Success": false,
+ "Error": "this is an error"
+}
+
--- /dev/null
+{
+ "TestID": 6735,
+ "Affected": 1,
+ "Success": true,
+ "Message": "This Check Has Been Deleted. It can not be recovered."
+}
--- /dev/null
+{
+ "TestID": 6735,
+ "TestType": "HTTP",
+ "Paused": false,
+ "WebsiteName": "NL",
+ "CustomHeader": "{\"some\":{\"json\": [\"value\"]}}",
+ "UserAgent": "product/version (comment)",
+ "ContactGroup": "StatusCake Alerts",
+ "ContactID": "536",
+ "Status": "Up",
+ "Uptime": 0,
+ "CheckRate": 60,
+ "Timeout": 40,
+ "LogoImage": "",
+ "WebsiteHost": "Various",
+ "NodeLocations": [
+ "UK",
+ "JP",
+ "SG1",
+ "SLC"
+ ],
+ "FindString": "",
+ "DoNotFind": false,
+ "LastTested": "2013-01-20 14:38:18",
+ "NextLocation": "USNY",
+ "Processing": false,
+ "ProcessingState": "Pretest",
+ "ProcessingOn": "dalas.localdomain",
+ "DownTimes": "0",
+ "UseJar": 0,
+ "PostRaw": "",
+ "FinalEndpoint": "",
+ "FollowRedirect": false
+}
--- /dev/null
+{
+ "Issues": {
+ "WebsiteName": "issue a",
+ "WebsiteURL": "issue b",
+ "CheckRate": "issue c"
+ },
+ "Success": false,
+ "Message": "Required Data is Missing."
+}
--- /dev/null
+{
+ "Issues": ["hello", "world"],
+ "Success": false,
+ "Message": "Required Data is Missing."
+}
--- /dev/null
+{
+ "Issues": {},
+ "Success": true,
+ "Message": "",
+ "InsertID": 1234
+}
package statuscake
+import (
+ "strings"
+)
+
type autheticationErrorResponse struct {
ErrNo int
Error string
Paused bool `json:"Paused"`
WebsiteName string `json:"WebsiteName"`
URI string `json:"URI"`
- ContactID int `json:"ContactID"`
+ ContactID string `json:"ContactID"`
Status string `json:"Status"`
Uptime float64 `json:"Uptime"`
+ CustomHeader string `json:"CustomHeader"`
+ UserAgent string `json:"UserAgent"`
CheckRate int `json:"CheckRate"`
Timeout int `json:"Timeout"`
LogoImage string `json:"LogoImage"`
DownTimes int `json:"DownTimes,string"`
Sensitive bool `json:"Sensitive"`
TriggerRate int `json:"TriggerRate,string"`
+ UseJar int `json:"UseJar"`
+ PostRaw string `json:"PostRaw"`
+ FinalEndpoint string `json:"FinalEndpoint"`
+ FollowRedirect bool `json:"FollowRedirect"`
+ StatusCodes []string `json:"StatusCodes"`
}
func (d *detailResponse) test() *Test {
return &Test{
- TestID: d.TestID,
- TestType: d.TestType,
- Paused: d.Paused,
- WebsiteName: d.WebsiteName,
- WebsiteURL: d.URI,
- ContactID: d.ContactID,
- Status: d.Status,
- Uptime: d.Uptime,
- CheckRate: d.CheckRate,
- Timeout: d.Timeout,
- LogoImage: d.LogoImage,
- Confirmation: d.Confirmation,
- WebsiteHost: d.WebsiteHost,
- NodeLocations: d.NodeLocations,
- FindString: d.FindString,
- DoNotFind: d.DoNotFind,
- Port: d.Port,
- TriggerRate: d.TriggerRate,
+ TestID: d.TestID,
+ TestType: d.TestType,
+ Paused: d.Paused,
+ WebsiteName: d.WebsiteName,
+ WebsiteURL: d.URI,
+ CustomHeader: d.CustomHeader,
+ UserAgent: d.UserAgent,
+ ContactID: d.ContactID,
+ Status: d.Status,
+ Uptime: d.Uptime,
+ CheckRate: d.CheckRate,
+ Timeout: d.Timeout,
+ LogoImage: d.LogoImage,
+ Confirmation: d.Confirmation,
+ WebsiteHost: d.WebsiteHost,
+ NodeLocations: d.NodeLocations,
+ FindString: d.FindString,
+ DoNotFind: d.DoNotFind,
+ Port: d.Port,
+ TriggerRate: d.TriggerRate,
+ UseJar: d.UseJar,
+ PostRaw: d.PostRaw,
+ FinalEndpoint: d.FinalEndpoint,
+ FollowRedirect: d.FollowRedirect,
+ StatusCodes: strings.Join(d.StatusCodes[:], ","),
}
}
// Website name. Tags are stripped out
WebsiteName string `json:"WebsiteName" querystring:"WebsiteName"`
+ // CustomHeader. A special header that will be sent along with the HTTP tests.
+ CustomHeader string `json:"CustomHeader" querystring:"CustomHeader"`
+
+ // Use to populate the test with a custom user agent
+ UserAgent string `json:"UserAgent" queryString:"UserAgent"`
+
// Test location, either an IP (for TCP and Ping) or a fully qualified URL for other TestTypes
WebsiteURL string `json:"WebsiteURL" querystring:"WebsiteURL"`
Port int `json:"Port" querystring:"Port"`
// Contact group ID - will return int of contact group used else 0
- ContactID int `json:"ContactID" querystring:"ContactGroup"`
+ ContactID string `json:"ContactID" querystring:"ContactGroup"`
// Current status at last test
Status string `json:"Status"`
// Comma Seperated List of StatusCodes to Trigger Error on (on Update will replace, so send full list each time)
StatusCodes string `json:"StatusCodes" querystring:"StatusCodes"`
+
+ // Set to 1 to enable the Cookie Jar. Required for some redirects.
+ UseJar int `json:"UseJar" querystring:"UseJar"`
+
+ // Raw POST data seperated by an ampersand
+ PostRaw string `json:"PostRaw" querystring:"PostRaw"`
+
+ // Use to specify the expected Final URL in the testing process
+ FinalEndpoint string `json:"FinalEndpoint" querystring:"FinalEndpoint"`
+
+ // Use to specify whether redirects should be followed
+ FollowRedirect bool `json:"FollowRedirect" querystring:"FollowRedirect"`
}
// Validate checks if the Test is valid. If it's invalid, it returns a ValidationError with all invalid fields. It returns nil otherwise.
e["TriggerRate"] = "must be between 0 and 59"
}
+ if t.PostRaw != "" && t.TestType != "HTTP" {
+ e["PostRaw"] = "must be HTTP to submit a POST request"
+ }
+
+ if t.FinalEndpoint != "" && t.TestType != "HTTP" {
+ e["FinalEndpoint"] = "must be a Valid URL"
+ }
+
+ var jsonVerifiable map[string]interface{}
+ if json.Unmarshal([]byte(t.CustomHeader), &jsonVerifiable) != nil {
+ e["CustomHeader"] = "must be provided as json string"
+ }
+
if len(e) > 0 {
return e
}
"ignore": "appengine test github.com/hashicorp/nomad/ github.com/hashicorp/terraform/backend",
"package": [
{
- "checksumSHA1": "MV5JueYPwNkLZ+KNqmDcNDhsKi4=",
+ "checksumSHA1": "xjfJ6T+mQFmC9oMR+UKdGtbs/p4=",
"path": "github.com/DreamItGetIT/statuscake",
- "revision": "acc13ec021cd1e8a6ebb1d9035f513217f5c4562",
- "revisionTime": "2017-04-10T11:34:45Z"
+ "revision": "2081e16dbe691bccf20b1901897d8f8245beefcd",
+ "revisionTime": "2018-01-09T18:02:45Z"
},
{
"checksumSHA1": "FIL83loX9V9APvGQIjJpbxq53F0=",