120 lines
3.3 KiB
Go
120 lines
3.3 KiB
Go
package http
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/keel-hq/keel/types"
|
|
"github.com/keel-hq/keel/util/image"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var newHarborWebhooksCounter = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "harbor_webhook_requests_total",
|
|
Help: "How many /v1/webhooks/harbor requests processed, partitioned by image.",
|
|
},
|
|
[]string{"image"},
|
|
)
|
|
|
|
func init() {
|
|
prometheus.MustRegister(newHarborWebhooksCounter)
|
|
}
|
|
|
|
// Example of Harbor trigger
|
|
// {
|
|
// "type": "pushImage",
|
|
// "occur_at": 1582640688,
|
|
// "operator": "<user>",
|
|
// "event_data": {
|
|
// "resources": [
|
|
// {
|
|
// "digest": "sha256:b4758aaed11c155a476b9857e1178f157759c99cb04c907a04993f5481eff848",
|
|
// "tag": "2.1.6",
|
|
// "resource_url": "<url>/<namespace>/<repo>:<version>"
|
|
// }
|
|
// ],
|
|
// "repository": {
|
|
// "date_created": 1582634337,
|
|
// "name": "<repo>",
|
|
// "namespace": "<namespace>",
|
|
// "repo_full_name": "<namespace>/<repo>",
|
|
// "repo_type": "private"
|
|
// }
|
|
// }
|
|
|
|
type harborWebhook struct {
|
|
Type string `json:"type"`
|
|
OccurAt int `json:"occur_at"`
|
|
Operator string `json:"operator"`
|
|
EventData struct {
|
|
Resources []struct {
|
|
Digest string `json:"digest"`
|
|
Tag string `json:"tag"`
|
|
ResourceURL string `json:"resource_url"`
|
|
} `json:"resources"`
|
|
Repository struct {
|
|
DateCreated int `json:"date_created"`
|
|
Name string `json:"name"`
|
|
Namespace string `json:"namespace"`
|
|
RepoFullName string `json:"repo_full_name"`
|
|
RepoType string `json:"repo_type"`
|
|
} `json:"repository"`
|
|
} `json:"event_data"`
|
|
}
|
|
|
|
func (s *TriggerServer) harborHandler(resp http.ResponseWriter, req *http.Request) {
|
|
hn := harborWebhook{}
|
|
if err := json.NewDecoder(req.Body).Decode(&hn); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
}).Error("trigger.harborHandler: failed to decode request")
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
log.WithFields(log.Fields{
|
|
"event": hn,
|
|
}).Debug("harborHandler: received event, looking for a pushImage tag")
|
|
|
|
if hn.Type == "pushImage" || hn.Type == "PUSH_ARTIFACT" {
|
|
// go trough all the ressource items
|
|
for _, e := range hn.EventData.Resources {
|
|
imageRepo, err := image.Parse(e.ResourceURL)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"repository": e.ResourceURL,
|
|
}).Error("trigger.harborHandler: failed to parse repository")
|
|
|
|
resp.WriteHeader(http.StatusBadRequest)
|
|
fmt.Fprintf(resp, "failed to parse repository %s, error: %s", e.ResourceURL, err)
|
|
return
|
|
}
|
|
|
|
//create event
|
|
event := types.Event{}
|
|
event.CreatedAt = time.Now()
|
|
event.TriggerName = "harbor"
|
|
event.Repository.Name = imageRepo.Repository()
|
|
event.Repository.Tag = imageRepo.Tag()
|
|
|
|
log.WithFields(log.Fields{
|
|
"action": hn.Type,
|
|
"tag": imageRepo.Tag(),
|
|
"repository": imageRepo.Repository(),
|
|
"digest": e.Digest,
|
|
}).Debug("harborHandler: got registry notification, processing")
|
|
|
|
s.trigger(event)
|
|
newHarborWebhooksCounter.With(prometheus.Labels{"image": event.Repository.Name}).Inc()
|
|
}
|
|
}
|
|
|
|
resp.WriteHeader(http.StatusOK)
|
|
}
|