Reduce to a single webhook call

This commit is contained in:
Thomas Jackson 2019-01-22 12:10:49 -08:00
parent 96714ebed2
commit fdc9b49de2
2 changed files with 48 additions and 42 deletions

View File

@ -21,7 +21,6 @@ package main // import "k8s.io/git-sync/cmd/git-sync"
import (
"bytes"
"context"
"encoding/json"
"flag"
"fmt"
"io"
@ -63,8 +62,14 @@ var flMaxSyncFailures = flag.Int("max-sync-failures", envInt("GIT_SYNC_MAX_SYNC_
var flChmod = flag.Int("change-permissions", envInt("GIT_SYNC_PERMISSIONS", 0),
"the file permissions to apply to the checked-out files")
var flWebhooks = flag.String("webhook", envString("GIT_SYNC_WEBHOOK", ""),
"the JSON formatted array of webhooks to be sent when git is synced")
var flWebhookURL = flag.String("webhook-url", envString("GIT_SYNC_WEBHOOK_URL", ""),
"the URL for the webook to send to. Default is \"\" which disables the webook.")
var flWebhookMethod = flag.String("webhook-method", envString("GIT_SYNC_WEBHOOK_METHOD", "POST"),
"the method for the webook to send with")
var flWebhookStatusSuccess = flag.Int("webhook-success-status", envInt("GIT_SYNC_WEBHOOK_SUCCESS_STATUS", 200),
"the status code which indicates a successful webhook call")
var flWebhookTimeout = flag.Duration("webhook-timeout-duration", envDuration("GIT_SYNC_WEBHOOK_TIMEOUT_DURATION", time.Second),
"the timeout used when communicating with the webhook target")
var flUsername = flag.String("username", envString("GIT_SYNC_USERNAME", ""),
"the username to use")
@ -140,6 +145,18 @@ func envFloat(key string, def float64) float64 {
return def
}
func envDuration(key string, def time.Duration) time.Duration {
if env := os.Getenv(key); env != "" {
val, err := time.ParseDuration(env)
if err != nil {
log.Errorf("invalid value for %q: using default: %v", key, def)
return def
}
return val
}
return def
}
func main() {
setFlagDefaults()
@ -175,13 +192,6 @@ func main() {
}
}
if *flWebhooks != "" {
if err := json.Unmarshal([]byte(*flWebhooks), &WebhookArray); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing webhooks JSON: %v\n", err)
os.Exit(1)
}
}
if *flSSH {
if err := setupGitSSH(*flSSHKnownHosts); err != nil {
fmt.Fprintf(os.Stderr, "ERROR: can't configure SSH: %v\n", err)
@ -200,8 +210,16 @@ func main() {
log.V(0).Infof("starting up: %q", os.Args)
// Startup webhooks goroutine
webhookTriggerChan := make(chan struct{})
go ServeWebhooks(webhookTriggerChan)
webhookTriggerChan := make(chan struct{}, 1)
if *flWebhookURL != "" {
webhook := Webhook{
URL: *flWebhookURL,
Method: *flWebhookMethod,
Success: flWebhookStatusSuccess,
Timeout: *flWebhookTimeout,
}
go webhook.run(webhookTriggerChan)
}
initialSync := true
failCount := 0
@ -220,8 +238,14 @@ func main() {
time.Sleep(waitTime(*flWait))
continue
} else if changed {
// Trigger webhooks to be called
webhookTriggerChan <- struct{}{}
// Trigger webhooks to be called. We do a non-blocking write to the channel as we
// don't want to backup the syncing locally because we can't complete a webhook call.
// Since the channel has a buffer of 1 we ensure that it is called for a change, but
// this allows us to de-dupe calls if they happen before the webhook call completes.
select {
case webhookTriggerChan <- struct{}{}:
default:
}
}
if initialSync {
if *flOneTime {

View File

@ -2,38 +2,22 @@ package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
)
// Webhook collection
var WebhookArray = []Webhook{}
// WebHook structure
type Webhook struct {
// URL for the http/s request
URL string `json:"url"`
URL string
// Method for the http/s request
Method string `json:"method"`
Method string
// Code to look for when determining if the request was successful.
// If this is not specified, request is sent and forgotten about.
Success *int `json:"success"`
Success *int
// Timeout for the http/s request
Timeout time.Duration `json:"timeout"`
}
func (w *Webhook) UnmarshalJSON(data []byte) error {
type testAlias Webhook
test := &testAlias{
Timeout: time.Second * 5,
}
_ = json.Unmarshal(data, test)
*w = Webhook(*test)
return nil
Timeout time.Duration
}
func (w *Webhook) Do() error {
@ -62,20 +46,18 @@ func (w *Webhook) Do() error {
}
// Wait for trigger events from the channel, and send webhooks when triggered
func ServeWebhooks(ch chan struct{}) {
func (w *Webhook) run(ch chan struct{}) {
for {
// Wait for trigger
<-ch
// Calling webhook - one after another
for _, v := range WebhookArray {
log.V(0).Infof("calling webhook %v\n", v.URL)
if err := v.Do(); err != nil {
log.Errorf("error calling webhook %v: %v", v.URL, err)
for {
if err := w.Do(); err != nil {
log.Errorf("error calling webhook %v: %v", w.URL, err)
} else {
log.V(0).Infof("calling webhook %v was: OK\n", v.URL)
log.V(0).Infof("calling webhook %v was: OK\n", w.URL)
break
}
}
}
}