github.com/uber/kraken@v0.1.4/tools/bin/puller/notification.go (about) 1 // Copyright (c) 2016-2019 Uber Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package main 15 16 import ( 17 "encoding/json" 18 "net/http" 19 "os" 20 "time" 21 22 "github.com/docker/distribution/notifications" 23 24 "github.com/uber/kraken/utils/log" 25 ) 26 27 const ( 28 baseManifestQuery = "http://%s/v2/%s/manifests/%s" 29 baseLayerQuery = "http://%s/v2/%s/blobs/%s" 30 transferTimeout = 120 * time.Second 31 localSource = "localhost:5051" 32 tempDir = "/tmp/kraken/tmp/puller/" 33 ) 34 35 // HealthHandler tells haproxy we'fre still alive 36 func HealthHandler(w http.ResponseWriter, request *http.Request) { 37 w.Header().Set("Content-Type", "text/plain") 38 w.Write([]byte("OK")) 39 } 40 41 // NotificationHandler receives docker push notification 42 type NotificationHandler struct { 43 queue chan uint8 44 useDocker bool 45 } 46 47 // NewNotificationHandler creates a new Notifaction 48 func NewNotificationHandler(maxChanSize int, useDocker bool) (*NotificationHandler, error) { 49 if err := os.MkdirAll(tempDir, 0775); err != nil { 50 return nil, err 51 } 52 return &NotificationHandler{ 53 queue: make(chan byte, maxChanSize), 54 useDocker: useDocker, 55 }, nil 56 } 57 58 // Handler handles messages defined in http://godoc.org/github.com/docker/distribution/notifications. 59 func (n *NotificationHandler) Handler(w http.ResponseWriter, r *http.Request) { 60 log.Debugf("notification received") 61 decoder := json.NewDecoder(r.Body) 62 var envelope notifications.Envelope 63 64 if err := decoder.Decode(&envelope); err != nil { 65 log.With("err", err).Error("cannot decode envelope") 66 return 67 } 68 for _, event := range envelope.Events { 69 if event.Action == notifications.EventActionPush { 70 url := event.Target.URL 71 repo := event.Target.Repository 72 tag := event.Target.Tag 73 digest := guessDigest(url, repo) 74 if len(digest) == 0 { 75 log.Debugf("non tag push action: target.URL: '%s', target.Repository: '%s'", url, repo) 76 } else { 77 select { 78 case n.queue <- 'c': 79 time.Sleep(2 * time.Second) 80 go func() { 81 PullImage(localSource, repo, tag, n.useDocker) 82 <-n.queue 83 }() 84 default: 85 // drop if queue full 86 log.Infof("queue full. drop %s:%s", repo, tag) 87 } 88 } 89 } 90 } 91 92 w.Header().Set("Content-Type", "application/json") 93 resString := "OK" 94 w.Write([]byte(resString)) 95 }