-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #53 from bnfinet/v5
receive docker hub notification of automated build
- Loading branch information
Showing
3 changed files
with
218 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package docker | ||
|
||
// this package recieves the Docker Hub Automated Build webhook | ||
// https://docs.docker.com/docker-hub/webhooks/ | ||
// NOT the Docker Trusted Registry webhook | ||
// https://docs.docker.com/ee/dtr/user/create-and-manage-webhooks/ | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"io" | ||
"io/ioutil" | ||
"net/http" | ||
) | ||
|
||
// parse errors | ||
var ( | ||
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method") | ||
ErrParsingPayload = errors.New("error parsing payload") | ||
) | ||
|
||
// Event defines a Docker hook event type | ||
type Event string | ||
|
||
// Docker hook types (only one for now) | ||
const ( | ||
BuildEvent Event = "build" | ||
) | ||
|
||
// BuildPayload a docker hub build notice | ||
// https://docs.docker.com/docker-hub/webhooks/ | ||
type BuildPayload struct { | ||
CallbackURL string `json:"callback_url"` | ||
PushData struct { | ||
Images []string `json:"images"` | ||
PushedAt float32 `json:"pushed_at"` | ||
Pusher string `json:"pusher"` | ||
Tag string `json:"tag"` | ||
} `json:"push_data"` | ||
Repository struct { | ||
CommentCount int `json:"comment_count"` | ||
DateCreated float32 `json:"date_created"` | ||
Description string `json:"description"` | ||
Dockerfile string `json:"dockerfile"` | ||
FullDescription string `json:"full_description"` | ||
IsOfficial bool `json:"is_official"` | ||
IsPrivate bool `json:"is_private"` | ||
IsTrusted bool `json:"is_trusted"` | ||
Name string `json:"name"` | ||
Namespace string `json:"namespace"` | ||
Owner string `json:"owner"` | ||
RepoName string `json:"repo_name"` | ||
RepoURL string `json:"repo_url"` | ||
StarCount int `json:"star_count"` | ||
Status string `json:"status"` | ||
} `json:"repository"` | ||
} | ||
|
||
// Webhook instance contains all methods needed to process events | ||
type Webhook struct { | ||
secret string | ||
} | ||
|
||
// New creates and returns a WebHook instance | ||
func New() (*Webhook, error) { | ||
hook := new(Webhook) | ||
return hook, nil | ||
} | ||
|
||
// Parse verifies and parses the events specified and returns the payload object or an error | ||
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) { | ||
defer func() { | ||
_, _ = io.Copy(ioutil.Discard, r.Body) | ||
_ = r.Body.Close() | ||
}() | ||
|
||
if r.Method != http.MethodPost { | ||
return nil, ErrInvalidHTTPMethod | ||
} | ||
|
||
payload, err := ioutil.ReadAll(r.Body) | ||
if err != nil || len(payload) == 0 { | ||
return nil, ErrParsingPayload | ||
} | ||
|
||
var pl BuildPayload | ||
err = json.Unmarshal([]byte(payload), &pl) | ||
if err != nil { | ||
return nil, ErrParsingPayload | ||
} | ||
return pl, err | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package docker | ||
|
||
import ( | ||
"log" | ||
"net/http" | ||
"net/http/httptest" | ||
"os" | ||
"testing" | ||
|
||
"reflect" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// NOTES: | ||
// - Run "go test" to run tests | ||
// - Run "gocov test | gocov report" to report on test converage by file | ||
// - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called | ||
// | ||
// or | ||
// | ||
// -- may be a good idea to change to output path to somewherelike /tmp | ||
// go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html | ||
// | ||
|
||
const ( | ||
path = "/webhooks" | ||
) | ||
|
||
var hook *Webhook | ||
|
||
func TestMain(m *testing.M) { | ||
|
||
// setup | ||
var err error | ||
hook, err = New() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
os.Exit(m.Run()) | ||
// teardown | ||
} | ||
|
||
func newServer(handler http.HandlerFunc) *httptest.Server { | ||
mux := http.NewServeMux() | ||
mux.HandleFunc(path, handler) | ||
return httptest.NewServer(mux) | ||
} | ||
|
||
func TestWebhooks(t *testing.T) { | ||
assert := require.New(t) | ||
tests := []struct { | ||
name string | ||
event Event | ||
typ interface{} | ||
filename string | ||
headers http.Header | ||
}{ | ||
{ | ||
name: "BuildEvent", | ||
event: BuildEvent, | ||
typ: BuildPayload{}, | ||
filename: "../testdata/docker/docker_hub_build_notice.json", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
tc := tt | ||
client := &http.Client{} | ||
t.Run(tt.name, func(t *testing.T) { | ||
t.Parallel() | ||
payload, err := os.Open(tc.filename) | ||
assert.NoError(err) | ||
defer func() { | ||
_ = payload.Close() | ||
}() | ||
|
||
var parseError error | ||
var results interface{} | ||
server := newServer(func(w http.ResponseWriter, r *http.Request) { | ||
results, parseError = hook.Parse(r, tc.event) | ||
}) | ||
defer server.Close() | ||
req, err := http.NewRequest(http.MethodPost, server.URL+path, payload) | ||
assert.NoError(err) | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
resp, err := client.Do(req) | ||
assert.NoError(err) | ||
assert.Equal(http.StatusOK, resp.StatusCode) | ||
assert.NoError(parseError) | ||
assert.Equal(reflect.TypeOf(tc.typ), reflect.TypeOf(results)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"callback_url": "https://registry.hub.docker.com/u/svendowideit/testhook/hook/2141b5bi5i5b02bec211i4eeih0242eg11000a/", | ||
"push_data": { | ||
"images": [ | ||
"27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3", | ||
"51a9c7c1f8bb2fa19bcd09789a34e63f35abb80044bc10196e304f6634cc582c", | ||
"..." | ||
], | ||
"pushed_at": 1.417566161e+09, | ||
"pusher": "trustedbuilder", | ||
"tag": "latest" | ||
}, | ||
"repository": { | ||
"comment_count": 0, | ||
"date_created": 1.417494799e+09, | ||
"description": "", | ||
"dockerfile": "#\n# BUILD\u0009\u0009docker build -t svendowideit/apt-cacher .\n# RUN\u0009\u0009docker run -d -p 3142:3142 -name apt-cacher-run apt-cacher\n#\n# and then you can run containers with:\n# \u0009\u0009docker run -t -i -rm -e http_proxy http://192.168.1.2:3142/ debian bash\n#\nFROM\u0009\u0009ubuntu\n\n\nVOLUME\u0009\u0009[/var/cache/apt-cacher-ng]\nRUN\u0009\u0009apt-get update ; apt-get install -yq apt-cacher-ng\n\nEXPOSE \u0009\u00093142\nCMD\u0009\u0009chmod 777 /var/cache/apt-cacher-ng ; /etc/init.d/apt-cacher-ng start ; tail -f /var/log/apt-cacher-ng/*\n", | ||
"full_description": "Docker Hub based automated build from a GitHub repo", | ||
"is_official": false, | ||
"is_private": true, | ||
"is_trusted": true, | ||
"name": "testhook", | ||
"namespace": "svendowideit", | ||
"owner": "svendowideit", | ||
"repo_name": "svendowideit/testhook", | ||
"repo_url": "https://registry.hub.docker.com/u/svendowideit/testhook/", | ||
"star_count": 0, | ||
"status": "Active" | ||
} | ||
} |