From f1ebc440a4bcdd30b5af9889961211d72063c754 Mon Sep 17 00:00:00 2001 From: Adnan Hajdarevic Date: Wed, 27 May 2015 09:16:26 +0200 Subject: [PATCH] match all hooks with the same id --- hook/hook.go | 17 ++++++++++++++ webhook.go | 56 ++++++++++++++++++++++++++------------------- webhook_windows.go | 57 +++++++++++++++++++++++++++------------------- 3 files changed, 82 insertions(+), 48 deletions(-) diff --git a/hook/hook.go b/hook/hook.go index 5315b64..f3cb78b 100644 --- a/hook/hook.go +++ b/hook/hook.go @@ -260,6 +260,23 @@ func (h *Hooks) Match(id string) *Hook { return nil } +// MatchAll iterates through Hooks and returns all of the hooks that match the +// given ID, if no hook matches the given ID, nil is returned +func (h *Hooks) MatchAll(id string) []*Hook { + matchedHooks := make([]*Hook, 0) + for i := range *h { + if (*h)[i].ID == id { + matchedHooks = append(matchedHooks, &(*h)[i]) + } + } + + if len(matchedHooks) > 0 { + return matchedHooks + } + + return nil +} + // Rules is a structure that contains one of the valid rule types type Rules struct { And *AndRule `json:"and"` diff --git a/webhook.go b/webhook.go index 9c9ccb6..7279e34 100644 --- a/webhook.go +++ b/webhook.go @@ -25,7 +25,7 @@ import ( ) const ( - version = "2.3.3" + version = "2.3.4" ) var ( @@ -144,10 +144,10 @@ func main() { func hookHandler(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] - hook := hooks.Match(id) + matchedHooks := hooks.MatchAll(id) - if hook != nil { - log.Printf("%s got matched\n", id) + if matchedHooks != nil { + log.Printf("%s got matched (%d time(s))\n", id, len(matchedHooks)) body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -183,13 +183,26 @@ func hookHandler(w http.ResponseWriter, r *http.Request) { } } - hook.ParseJSONParameters(&headers, &query, &payload) - // handle hook - go handleHook(hook, &headers, &query, &payload, &body) + for _, hook := range matchedHooks { + hook.ParseJSONParameters(&headers, &query, &payload) + if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(&headers, &query, &payload, &body) { + log.Printf("%s hook triggered successfully\n", hook.ID) - // send the hook defined response message - fmt.Fprintf(w, hook.ResponseMessage) + go handleHook(hook, &headers, &query, &payload, &body) + + // send the hook defined response message + fmt.Fprintf(w, hook.ResponseMessage) + + return + } + } + + // if none of the hooks got triggered + log.Printf("%s got matched (%d time(s)), but didn't get triggered because the trigger rules were not satisfied\n", matchedHooks[0].ID, len(matchedHooks)) + + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Hook rules were not satisfied.") } else { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "Hook not found.") @@ -197,26 +210,21 @@ func hookHandler(w http.ResponseWriter, r *http.Request) { } func handleHook(hook *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) { - if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(headers, query, payload, body) { - log.Printf("%s hook triggered successfully\n", hook.ID) + cmd := exec.Command(hook.ExecuteCommand) + cmd.Args = hook.ExtractCommandArguments(headers, query, payload) + cmd.Dir = hook.CommandWorkingDirectory - cmd := exec.Command(hook.ExecuteCommand) - cmd.Args = hook.ExtractCommandArguments(headers, query, payload) - cmd.Dir = hook.CommandWorkingDirectory + log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir) - log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir) + out, err := cmd.Output() - out, err := cmd.Output() + log.Printf("stdout: %s\n", out) - log.Printf("stdout: %s\n", out) - - if err != nil { - log.Printf("stderr: %+v\n", err) - } - log.Printf("finished handling %s\n", hook.ID) - } else { - log.Printf("%s hook did not get triggered\n", hook.ID) + if err != nil { + log.Printf("stderr: %+v\n", err) } + + log.Printf("finished handling %s\n", hook.ID) } func reloadHooks() { diff --git a/webhook_windows.go b/webhook_windows.go index f42e8bf..1c26828 100644 --- a/webhook_windows.go +++ b/webhook_windows.go @@ -23,7 +23,7 @@ import ( ) const ( - version = "2.3.3" + version = "2.3.4" ) var ( @@ -133,10 +133,10 @@ func main() { func hookHandler(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["id"] - hook := hooks.Match(id) + matchedHooks := hooks.MatchAll(id) - if hook != nil { - log.Printf("%s got matched\n", id) + if matchedHooks != nil { + log.Printf("%s got matched (%d time(s))\n", id, len(matchedHooks)) body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -172,13 +172,27 @@ func hookHandler(w http.ResponseWriter, r *http.Request) { } } - hook.ParseJSONParameters(&headers, &query, &payload) - // handle hook - go handleHook(hook, &headers, &query, &payload, &body) + for _, hook := range matchedHooks { + hook.ParseJSONParameters(&headers, &query, &payload) - // send the hook defined response message - fmt.Fprintf(w, hook.ResponseMessage) + if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(&headers, &query, &payload, &body) { + log.Printf("%s hook triggered successfully\n", hook.ID) + + go handleHook(hook, &headers, &query, &payload, &body) + + // send the hook defined response message + fmt.Fprintf(w, hook.ResponseMessage) + + return + } + } + + // if none of the hooks got triggered + log.Printf("%s got matched (%d time(s)), but didn't get triggered because the trigger rules were not satisfied\n", matchedHooks[0].ID, len(matchedHooks)) + + w.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(w, "Hook rules were not satisfied.") } else { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "Hook not found.") @@ -186,26 +200,21 @@ func hookHandler(w http.ResponseWriter, r *http.Request) { } func handleHook(hook *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) { - if hook.TriggerRule == nil || hook.TriggerRule != nil && hook.TriggerRule.Evaluate(headers, query, payload, body) { - log.Printf("%s hook triggered successfully\n", hook.ID) + cmd := exec.Command(hook.ExecuteCommand) + cmd.Args = hook.ExtractCommandArguments(headers, query, payload) + cmd.Dir = hook.CommandWorkingDirectory - cmd := exec.Command(hook.ExecuteCommand) - cmd.Args = hook.ExtractCommandArguments(headers, query, payload) - cmd.Dir = hook.CommandWorkingDirectory + log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir) - log.Printf("executing %s (%s) with arguments %s using %s as cwd\n", hook.ExecuteCommand, cmd.Path, cmd.Args, cmd.Dir) + out, err := cmd.Output() - out, err := cmd.Output() + log.Printf("stdout: %s\n", out) - log.Printf("stdout: %s\n", out) - - if err != nil { - log.Printf("stderr: %+v\n", err) - } - log.Printf("finished handling %s\n", hook.ID) - } else { - log.Printf("%s hook did not get triggered\n", hook.ID) + if err != nil { + log.Printf("stderr: %+v\n", err) } + + log.Printf("finished handling %s\n", hook.ID) } func reloadHooks() {