add json body, Pushbullet example
This commit is contained in:
		
							parent
							
								
									4b9230bd90
								
							
						
					
					
						commit
						7b84c74754
					
				
							
								
								
									
										49
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								README.md
									
									
									
									
									
								
							@ -147,6 +147,35 @@ The `from` address can be _any_ domain in your mailgun account.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
`subject` is the plain-text subject and `text` must be plain-text (not html) email contents.
 | 
					`subject` is the plain-text subject and `text` must be plain-text (not html) email contents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</details>
 | 
				
			||||||
 | 
					<details>
 | 
				
			||||||
 | 
					  <summary>How to use with Pushbullet</summary>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pushbullet is a push notification service that I found pretty easy to work with.
 | 
				
			||||||
 | 
					I logged in with my iPhone through facebook, as well as in a web browser,
 | 
				
			||||||
 | 
					grabbed the API token, and I was able to test the documentation all in just a few minutes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `my_pushbullet`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Replace `my_pushbullet` with whatever name you like, or leave it the same.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's an arbitrary name for you to reference.
 | 
				
			||||||
 | 
					For example, you may have different Pushbullet configurations for different domains.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Replace `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` in the HTTP Access-Token header
 | 
				
			||||||
 | 
					with your API token.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You'll find this on the Pushbullet dashboard under Settings, Account, Access Tokens,
 | 
				
			||||||
 | 
					and you'll have to click to create it:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- <https://www.pushbullet.com/#settings/account>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The example was taken from the Pushbullet API documentation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- <https://docs.pushbullet.com/#create-push>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</details>
 | 
					</details>
 | 
				
			||||||
<details>
 | 
					<details>
 | 
				
			||||||
  <summary>How to use with Twilio</summary>
 | 
					  <summary>How to use with Twilio</summary>
 | 
				
			||||||
@ -188,7 +217,7 @@ All phone numbers should have the country code prefix (`+1` for USA) attached.
 | 
				
			|||||||
<details>
 | 
					<details>
 | 
				
			||||||
  <summary>How to use with Nexmo, Mailjet, and other webhook-enabled services</summary>
 | 
					  <summary>How to use with Nexmo, Mailjet, and other webhook-enabled services</summary>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See the examples of Twilio and Mailgun.
 | 
					See the examples of Mailgun, Pushbullet, Twilio.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Look for "curl" in the documentation of the service that you're using.
 | 
					Look for "curl" in the documentation of the service that you're using.
 | 
				
			||||||
It should be fairly easy to just look at the headers that are being set and repeat.
 | 
					It should be fairly easy to just look at the headers that are being set and repeat.
 | 
				
			||||||
@ -199,7 +228,7 @@ It should be fairly easy to just look at the headers that are being set and repe
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
You can set notifications for _any_ service that supports HTTPS webhooks.
 | 
					You can set notifications for _any_ service that supports HTTPS webhooks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The examples below are shown with Twilio and Mailgun, as taken from their `curl` documentation.
 | 
					The examples below are shown with Mailgun, Pushbullet, and Twilio, as taken from their `curl` documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```json
 | 
					```json
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -208,7 +237,7 @@ The examples below are shown with Twilio and Mailgun, as taken from their `curl`
 | 
				
			|||||||
      "name": "Example Site",
 | 
					      "name": "Example Site",
 | 
				
			||||||
      "url": "https://example.com/",
 | 
					      "url": "https://example.com/",
 | 
				
			||||||
      "keywords": "My Site",
 | 
					      "keywords": "My Site",
 | 
				
			||||||
      "webhooks": ["my_mailgun", "my_twilio"],
 | 
					      "webhooks": ["my_mailgun", "my_pushbullet", "my_twilio"],
 | 
				
			||||||
      "recover_script": "systemctl restart example-site"
 | 
					      "recover_script": "systemctl restart example-site"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
@ -231,6 +260,20 @@ The examples below are shown with Twilio and Mailgun, as taken from their `curl`
 | 
				
			|||||||
        "text": "The system is down. Check up on {{ .Name }} ASAP."
 | 
					        "text": "The system is down. Check up on {{ .Name }} ASAP."
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "name": "my_pushbullet",
 | 
				
			||||||
 | 
					      "method": "POST",
 | 
				
			||||||
 | 
					      "url": "https://api.pushbullet.com/v2/pushes",
 | 
				
			||||||
 | 
					      "headers": {
 | 
				
			||||||
 | 
					        "Access-Token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
 | 
				
			||||||
 | 
					        "User-Agent": "Watchdog/1.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "json": {
 | 
				
			||||||
 | 
					        "body": "The system is down. Check up on {{ .Name }} ASAP.",
 | 
				
			||||||
 | 
					        "title": "{{ .Name }} is down.",
 | 
				
			||||||
 | 
					        "type": "note"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "name": "my_twilio",
 | 
					      "name": "my_twilio",
 | 
				
			||||||
      "method": "POST",
 | 
					      "method": "POST",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										32
									
								
								watchdog.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								watchdog.go
									
									
									
									
									
								
							@ -138,7 +138,10 @@ func (d *Dog) watch() {
 | 
				
			|||||||
		err := d.check()
 | 
							err := d.check()
 | 
				
			||||||
		if nil != err {
 | 
							if nil != err {
 | 
				
			||||||
			failure = true
 | 
								failure = true
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								failure = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// We should notify if
 | 
							// We should notify if
 | 
				
			||||||
		// * We've had success since the last notification
 | 
							// * We've had success since the last notification
 | 
				
			||||||
		// * It's been at least 5 minutes since the last notification
 | 
							// * It's been at least 5 minutes since the last notification
 | 
				
			||||||
@ -146,7 +149,7 @@ func (d *Dog) watch() {
 | 
				
			|||||||
		if d.lastPassed.After(d.lastNotified) && d.lastNotified.Before(fiveMinutesAgo) {
 | 
							if d.lastPassed.After(d.lastNotified) && d.lastNotified.Before(fiveMinutesAgo) {
 | 
				
			||||||
			d.notify(failure)
 | 
								d.notify(failure)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if d.failures >= 5 {
 | 
							if !failure || d.failures >= 5 {
 | 
				
			||||||
			// go back to the main 5-minute loop
 | 
								// go back to the main 5-minute loop
 | 
				
			||||||
			break
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -213,7 +216,7 @@ func (d *Dog) recover() {
 | 
				
			|||||||
	err = cmd.Wait()
 | 
						err = cmd.Wait()
 | 
				
			||||||
	cancel()
 | 
						cancel()
 | 
				
			||||||
	if nil != err {
 | 
						if nil != err {
 | 
				
			||||||
		d.logger <- fmt.Sprintf("[Recover] '%s' failed: %s", d.Recover, err)
 | 
							d.logger <- fmt.Sprintf("[Recover] '%s' failed for '%s': %s", d.Recover, d.Name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -241,26 +244,40 @@ func (d *Dog) notify(hardFail bool) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var body *strings.Reader
 | 
							var body *strings.Reader
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							// TODO real templates
 | 
				
			||||||
		if 0 != len(h.Form) {
 | 
							if 0 != len(h.Form) {
 | 
				
			||||||
			form := url.Values{}
 | 
								form := url.Values{}
 | 
				
			||||||
			for k := range h.Form {
 | 
								for k := range h.Form {
 | 
				
			||||||
				v := h.Form[k]
 | 
									v := h.Form[k]
 | 
				
			||||||
				// TODO real templates
 | 
									// because `{{` gets urlencoded
 | 
				
			||||||
 | 
									//k = strings.Replace(k, "{{ .Name }}", d.Name, -1)
 | 
				
			||||||
				v = strings.Replace(v, "{{ .Name }}", d.Name, -1)
 | 
									v = strings.Replace(v, "{{ .Name }}", d.Name, -1)
 | 
				
			||||||
 | 
									d.logger <- fmt.Sprintf("[HEADER] %s: %s", k, v)
 | 
				
			||||||
				form.Set(k, v)
 | 
									form.Set(k, v)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			body = strings.NewReader(form.Encode())
 | 
								body = strings.NewReader(form.Encode())
 | 
				
			||||||
 | 
							} else if 0 != len(h.JSON) {
 | 
				
			||||||
 | 
								bodyBuf, err := json.Marshal(h.JSON)
 | 
				
			||||||
 | 
								if nil != err {
 | 
				
			||||||
 | 
									d.logger <- fmt.Sprintf("[Notify] JSON Marshal Error for '%s': %s", h.Name, err)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// `{{` should be left alone
 | 
				
			||||||
 | 
								body = strings.NewReader(strings.Replace(string(bodyBuf), "{{ .Name }}", d.Name, -1))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		client := NewHTTPClient()
 | 
							client := NewHTTPClient()
 | 
				
			||||||
		req, err := http.NewRequest(h.Method, h.URL, body)
 | 
							req, err := http.NewRequest(h.Method, h.URL, body)
 | 
				
			||||||
		if nil != err {
 | 
							if nil != err {
 | 
				
			||||||
			log.Println("[Notify] HTTP Client Network Error:", err)
 | 
								d.logger <- fmt.Sprintf("[Notify] HTTP Client Network Error for '%s': %s", h.Name, err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if 0 != len(h.Form) {
 | 
							if 0 != len(h.Form) {
 | 
				
			||||||
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 | 
								req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 | 
				
			||||||
 | 
							} else if 0 != len(h.JSON) {
 | 
				
			||||||
 | 
								req.Header.Set("Content-Type", "application/json")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if 0 != len(h.Auth) {
 | 
							if 0 != len(h.Auth) {
 | 
				
			||||||
@ -282,12 +299,12 @@ func (d *Dog) notify(hardFail bool) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		resp, err := client.Do(req)
 | 
							resp, err := client.Do(req)
 | 
				
			||||||
		if nil != err {
 | 
							if nil != err {
 | 
				
			||||||
			d.logger <- fmt.Sprintf("[Notify] HTTP Client Error: %s", err)
 | 
								d.logger <- fmt.Sprintf("[Notify] HTTP Client Error for '%s': %s", h.Name, err)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !(resp.StatusCode >= 200 && resp.StatusCode < 300) {
 | 
							if !(resp.StatusCode >= 200 && resp.StatusCode < 300) {
 | 
				
			||||||
			d.logger <- fmt.Sprintf("[Notify] Response Error: %s", resp.Status)
 | 
								d.logger <- fmt.Sprintf("[Notify] Response Error for '%s': %s", h.Name, resp.Status)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -297,7 +314,7 @@ func (d *Dog) notify(hardFail bool) {
 | 
				
			|||||||
		decoder := json.NewDecoder(resp.Body)
 | 
							decoder := json.NewDecoder(resp.Body)
 | 
				
			||||||
		err = decoder.Decode(&data)
 | 
							err = decoder.Decode(&data)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			d.logger <- fmt.Sprintf("[Notify] Response Body Error: %s", resp.Status)
 | 
								d.logger <- fmt.Sprintf("[Notify] Response Body Error for '%s': %s", h.Name, resp.Status)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -326,6 +343,7 @@ type ConfigWebhook struct {
 | 
				
			|||||||
	Auth    map[string]string   `json:"auth"`
 | 
						Auth    map[string]string   `json:"auth"`
 | 
				
			||||||
	Headers map[string]string   `json:"headers"`
 | 
						Headers map[string]string   `json:"headers"`
 | 
				
			||||||
	Form    map[string]string   `json:"form"`
 | 
						Form    map[string]string   `json:"form"`
 | 
				
			||||||
 | 
						JSON    map[string]string   `json:"json"`
 | 
				
			||||||
	Config  map[string]string   `json:"config"`
 | 
						Config  map[string]string   `json:"config"`
 | 
				
			||||||
	Configs []map[string]string `json:"configs"`
 | 
						Configs []map[string]string `json:"configs"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user