mirror of
https://github.com/ncarlier/webhookd.git
synced 2025-04-05 18:03:41 +00:00
chore(): small pkg refactoring
This commit is contained in:
parent
43204677d3
commit
c21443c10e
11
README.md
11
README.md
|
@ -75,6 +75,9 @@ You can override the default using the `WHD_SCRIPTS` environment variable or `-s
|
|||
Note that Webhookd is able to run any type of file in this directory as long as the file is executable.
|
||||
For example, you can execute a Node.js file if you give execution rights to the file and add the appropriate `#!` header (in this case: `#!/usr/bin/env node`).
|
||||
|
||||
You can find sample scripts in the [example folder](./scripts/examples).
|
||||
In particular, examples of integration with Gitlab and Github.
|
||||
|
||||
### Webhook URL
|
||||
|
||||
The directory structure define the webhook URL.
|
||||
|
@ -308,7 +311,7 @@ $ curl -X POST \
|
|||
-H 'Date: <req-date>' \
|
||||
-H 'Signature: keyId=<key-id>,algorithm="rsa-sha256",headers="(request-target) date",signature=<signature-string>' \
|
||||
-H 'Accept: application/json' \
|
||||
"http://loclahost:8080/echo?msg=hello"
|
||||
"http://localhost:8080/echo?msg=hello"
|
||||
```
|
||||
|
||||
You can find a small HTTP client in the ["tooling" directory](./tooling/httpsig/README.md) that is capable of forging HTTP signatures.
|
||||
|
@ -345,4 +348,10 @@ On *nix, if you want to listen on ports 80 and 443, don't forget to use `setcap`
|
|||
sudo setcap CAP_NET_BIND_SERVICE+ep webhookd
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
See [LICENSE](./LICENSE) to see the full text.
|
||||
|
||||
---
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package tools
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/ncarlier/webhookd/pkg/config"
|
||||
"github.com/ncarlier/webhookd/pkg/logger"
|
||||
"github.com/ncarlier/webhookd/pkg/model"
|
||||
"github.com/ncarlier/webhookd/pkg/tools"
|
||||
"github.com/ncarlier/webhookd/pkg/worker"
|
||||
)
|
||||
|
||||
|
@ -58,7 +57,7 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Get script location
|
||||
p := strings.TrimPrefix(r.URL.Path, "/")
|
||||
script, err := tools.ResolveScript(scriptDir, p)
|
||||
script, err := worker.ResolveScript(scriptDir, p)
|
||||
if err != nil {
|
||||
logger.Error.Println(err.Error())
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
|
@ -72,8 +71,8 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
params := tools.QueryParamsToShellVars(r.URL.Query())
|
||||
params = append(params, tools.HTTPHeadersToShellVars(r.Header)...)
|
||||
params := QueryParamsToShellVars(r.URL.Query())
|
||||
params = append(params, HTTPHeadersToShellVars(r.Header)...)
|
||||
|
||||
// logger.Debug.Printf("API REQUEST: \"%s\" with params %s...\n", p, params)
|
||||
|
||||
|
@ -119,7 +118,7 @@ func getWebhookLog(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Get script location
|
||||
name := path.Dir(strings.TrimPrefix(r.URL.Path, "/"))
|
||||
_, err := tools.ResolveScript(scriptDir, name)
|
||||
_, err := worker.ResolveScript(scriptDir, name)
|
||||
if err != nil {
|
||||
logger.Error.Println(err.Error())
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package tools_test
|
||||
package test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/ncarlier/webhookd/pkg/api"
|
||||
"github.com/ncarlier/webhookd/pkg/assert"
|
||||
"github.com/ncarlier/webhookd/pkg/tools"
|
||||
)
|
||||
|
||||
func TestQueryParamsToShellVars(t *testing.T) {
|
||||
|
@ -14,7 +14,7 @@ func TestQueryParamsToShellVars(t *testing.T) {
|
|||
"string": []string{"foo"},
|
||||
"list": []string{"foo", "bar"},
|
||||
}
|
||||
values := tools.QueryParamsToShellVars(tc)
|
||||
values := api.QueryParamsToShellVars(tc)
|
||||
assert.ContainsStr(t, "string=foo", values, "")
|
||||
assert.ContainsStr(t, "list=foo,bar", values, "")
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func TestHTTPHeadersToShellVars(t *testing.T) {
|
|||
"Content-Type": []string{"text/plain"},
|
||||
"X-Foo-Bar": []string{"foo", "bar"},
|
||||
}
|
||||
values := tools.HTTPHeadersToShellVars(tc)
|
||||
values := api.HTTPHeadersToShellVars(tc)
|
||||
assert.ContainsStr(t, "content_type=text/plain", values, "")
|
||||
assert.ContainsStr(t, "x_foo_bar=foo,bar", values, "")
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncarlier/webhookd/pkg/assert"
|
||||
)
|
||||
|
||||
func TestValidateCredentials(t *testing.T) {
|
||||
htpasswdFile, err := NewHtpasswdFromFile("test.htpasswd")
|
||||
assert.Nil(t, err, ".htpasswd file should be loaded")
|
||||
assert.NotNil(t, htpasswdFile, ".htpasswd file should be loaded")
|
||||
assert.Equal(t, true, htpasswdFile.validateCredentials("foo", "bar"), "credentials should be valid")
|
||||
assert.Equal(t, false, htpasswdFile.validateCredentials("foo", "bir"), "credentials should not be valid")
|
||||
}
|
23
pkg/auth/test/htpasswd-file_test.go
Normal file
23
pkg/auth/test/htpasswd-file_test.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/ncarlier/webhookd/pkg/assert"
|
||||
"github.com/ncarlier/webhookd/pkg/auth"
|
||||
)
|
||||
|
||||
func TestValidateCredentials(t *testing.T) {
|
||||
htpasswdFile, err := auth.NewHtpasswdFromFile("test.htpasswd")
|
||||
assert.Nil(t, err, ".htpasswd file should be loaded")
|
||||
assert.NotNil(t, htpasswdFile, ".htpasswd file should be loaded")
|
||||
|
||||
req, err := http.NewRequest("POST", "http://localhost:8080", nil)
|
||||
assert.Nil(t, err, "")
|
||||
req.SetBasicAuth("foo", "bar")
|
||||
assert.Equal(t, true, htpasswdFile.Validate(req), "credentials should be valid")
|
||||
|
||||
req.SetBasicAuth("foo", "bad")
|
||||
assert.Equal(t, false, htpasswdFile.Validate(req), "credentials should not be valid")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package tools
|
||||
package worker
|
||||
|
||||
import (
|
||||
"errors"
|
|
@ -1,32 +1,32 @@
|
|||
package tools_test
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ncarlier/webhookd/pkg/assert"
|
||||
"github.com/ncarlier/webhookd/pkg/tools"
|
||||
"github.com/ncarlier/webhookd/pkg/worker"
|
||||
)
|
||||
|
||||
func TestResolveScript(t *testing.T) {
|
||||
script, err := tools.ResolveScript("../../scripts", "../scripts/echo")
|
||||
script, err := worker.ResolveScript("../../../scripts", "../scripts/echo")
|
||||
assert.Nil(t, err, "")
|
||||
assert.Equal(t, "../../scripts/echo.sh", script, "")
|
||||
assert.Equal(t, "../../../scripts/echo.sh", script, "")
|
||||
}
|
||||
|
||||
func TestNotResolveScript(t *testing.T) {
|
||||
_, err := tools.ResolveScript("../../scripts", "foo")
|
||||
_, err := worker.ResolveScript("../../scripts", "foo")
|
||||
assert.NotNil(t, err, "")
|
||||
assert.Equal(t, "Script not found: ../../scripts/foo.sh", err.Error(), "")
|
||||
}
|
||||
|
||||
func TestResolveBadScript(t *testing.T) {
|
||||
_, err := tools.ResolveScript("../../scripts", "../tests/test_simple")
|
||||
_, err := worker.ResolveScript("../../scripts", "../tests/test_simple")
|
||||
assert.NotNil(t, err, "")
|
||||
assert.Equal(t, "Invalid script path: ../tests/test_simple.sh", err.Error(), "")
|
||||
}
|
||||
|
||||
func TestResolveScriptWithExtension(t *testing.T) {
|
||||
_, err := tools.ResolveScript("../../scripts", "node.js")
|
||||
_, err := worker.ResolveScript("../../scripts", "node.js")
|
||||
assert.NotNil(t, err, "")
|
||||
assert.Equal(t, "Script not found: ../../scripts/node.js", err.Error(), "")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package worker
|
||||
package test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/ncarlier/webhookd/pkg/assert"
|
||||
"github.com/ncarlier/webhookd/pkg/logger"
|
||||
"github.com/ncarlier/webhookd/pkg/model"
|
||||
"github.com/ncarlier/webhookd/pkg/worker"
|
||||
)
|
||||
|
||||
func printWorkMessages(work *model.WorkRequest) {
|
||||
|
@ -24,7 +25,7 @@ func printWorkMessages(work *model.WorkRequest) {
|
|||
|
||||
func TestWorkRunner(t *testing.T) {
|
||||
logger.Init("debug")
|
||||
script := "../../tests/test_simple.sh"
|
||||
script := "./test_simple.sh"
|
||||
args := []string{
|
||||
"name=foo",
|
||||
"user_agent=test",
|
||||
|
@ -33,14 +34,14 @@ func TestWorkRunner(t *testing.T) {
|
|||
work := model.NewWorkRequest("test", script, payload, os.TempDir(), args, 5)
|
||||
assert.NotNil(t, work, "")
|
||||
printWorkMessages(work)
|
||||
err := run(work)
|
||||
err := worker.Run(work)
|
||||
assert.Nil(t, err, "")
|
||||
assert.Equal(t, work.Status, model.Success, "")
|
||||
assert.Equal(t, work.GetLogContent("notify:"), "OK\n", "")
|
||||
|
||||
// Test that we can retrieve log file afterward
|
||||
id := strconv.FormatUint(work.ID, 10)
|
||||
logFile, err := RetrieveLogFile(id, "test", os.TempDir())
|
||||
logFile, err := worker.RetrieveLogFile(id, "test", os.TempDir())
|
||||
defer logFile.Close()
|
||||
assert.Nil(t, err, "Log file should exists")
|
||||
assert.NotNil(t, logFile, "Log file should be retrieve")
|
||||
|
@ -48,11 +49,11 @@ func TestWorkRunner(t *testing.T) {
|
|||
|
||||
func TestWorkRunnerWithError(t *testing.T) {
|
||||
logger.Init("debug")
|
||||
script := "../../tests/test_error.sh"
|
||||
script := "./test_error.sh"
|
||||
work := model.NewWorkRequest("test", script, "", os.TempDir(), []string{}, 5)
|
||||
assert.NotNil(t, work, "")
|
||||
printWorkMessages(work)
|
||||
err := run(work)
|
||||
err := worker.Run(work)
|
||||
assert.NotNil(t, err, "")
|
||||
assert.Equal(t, work.Status, model.Error, "")
|
||||
assert.Equal(t, "exit status 1", err.Error(), "")
|
||||
|
@ -60,11 +61,11 @@ func TestWorkRunnerWithError(t *testing.T) {
|
|||
|
||||
func TestWorkRunnerWithTimeout(t *testing.T) {
|
||||
logger.Init("debug")
|
||||
script := "../../tests/test_timeout.sh"
|
||||
script := "./test_timeout.sh"
|
||||
work := model.NewWorkRequest("test", script, "", os.TempDir(), []string{}, 1)
|
||||
assert.NotNil(t, work, "")
|
||||
printWorkMessages(work)
|
||||
err := run(work)
|
||||
err := worker.Run(work)
|
||||
assert.NotNil(t, err, "")
|
||||
assert.Equal(t, work.Status, model.Error, "")
|
||||
assert.Equal(t, "signal: killed", err.Error(), "")
|
|
@ -23,7 +23,8 @@ func (c *ChanWriter) Write(p []byte) (int, error) {
|
|||
return len(p), nil
|
||||
}
|
||||
|
||||
func run(work *model.WorkRequest) error {
|
||||
// Run work request
|
||||
func Run(work *model.WorkRequest) error {
|
||||
work.Status = model.Running
|
||||
logger.Info.Printf("job %s#%d started...\n", work.Name, work.ID)
|
||||
logger.Debug.Printf("job %s#%d script: %s\n", work.Name, work.ID, work.Script)
|
||||
|
|
|
@ -10,16 +10,15 @@ import (
|
|||
"github.com/ncarlier/webhookd/pkg/notification"
|
||||
)
|
||||
|
||||
// NewWorker creates, and returns a new Worker object. Its only argument
|
||||
// is a channel that the worker can add itself to whenever it is done its
|
||||
// work.
|
||||
// NewWorker creates, and returns a new Worker object.
|
||||
func NewWorker(id int, workerQueue chan chan model.WorkRequest) Worker {
|
||||
// Create, and return the worker.
|
||||
worker := Worker{
|
||||
ID: id,
|
||||
Work: make(chan model.WorkRequest),
|
||||
WorkerQueue: workerQueue,
|
||||
QuitChan: make(chan bool)}
|
||||
QuitChan: make(chan bool),
|
||||
}
|
||||
|
||||
return worker
|
||||
}
|
||||
|
@ -45,7 +44,7 @@ func (w Worker) Start() {
|
|||
// Receive a work request.
|
||||
logger.Debug.Printf("worker #%d received job request: %s#%d\n", w.ID, work.Name, work.ID)
|
||||
metric.Requests.Add(1)
|
||||
err := run(&work)
|
||||
err := Run(&work)
|
||||
if err != nil {
|
||||
metric.RequestsFailed.Add(1)
|
||||
work.MessageChan <- []byte(fmt.Sprintf("error: %s", err.Error()))
|
||||
|
|
Loading…
Reference in New Issue
Block a user