8 Commits
0.8.0 ... 0.8.2

Author SHA1 Message Date
Roman Vynar
ee38e35ba6 Fix tests 2019-07-30 09:18:46 +03:00
Roman Vynar
3d90f7b176 Release 0.8.2 2019-07-30 09:06:48 +03:00
Roman Vynar
3125554074 Bump go version 2019-07-30 09:02:36 +03:00
Roman Vynar
d5b6669eee Add event_deletion_enabled option to the config, useful for master-master/cluster setups 2019-07-30 09:02:25 +03:00
하광일 / TC / CE
fe0f3e28e8 Generate from response body if no Docker-Content-Digest header (#41) 2019-07-29 10:40:25 +03:00
Roman Vynar
5bce4ad9c6 Better breadcrumb 2019-02-20 16:44:35 +02:00
Roman Vynar
7151e7b269 Add favicon 2019-02-20 10:22:52 +02:00
Roman Vynar
4b6870cc35 Add favicon 2019-02-20 10:19:57 +02:00
15 changed files with 66 additions and 31 deletions

View File

@@ -1,5 +1,15 @@
## Changelog
### 0.8.2 (2019-07-30)
* Add event_deletion_enabled option to the config, useful for master-master/cluster setups.
* Generate SHA256 from response body if no Docker-Content-Digest header is present, e.g. with AWS ECR.
* Bump go version.
### 0.8.1 (2019-02-20)
* Add favicon.
### 0.8.0 (2019-02-19)
* Use go 1.11.5, alpine 3.9, echo 3.3.10.

View File

@@ -1,4 +1,4 @@
FROM golang:1.11.5-alpine3.9 as builder
FROM golang:1.12.7-alpine3.9 as builder
ENV GOPATH /opt
ENV GO111MODULE on

View File

@@ -30,6 +30,10 @@ event_database_location: data/registry_events.db
# event_database_driver: mysql
# event_database_location: user:password@tcp(localhost:3306)/docker_events
# You can disable event deletion on some hosts when you are running docker-registry on master-master or
# cluster setup to avoid deadlocks or replication break.
event_deletion_enabled: True
# Cache refresh interval in minutes.
# How long to cache repository list and tag counts.
cache_refresh_interval: 10

View File

@@ -10,6 +10,7 @@ import (
"github.com/hhkbp2/go-logging"
"github.com/quiq/docker-registry-ui/registry"
// 🐒 patching of "database/sql".
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
@@ -35,6 +36,7 @@ type EventListener struct {
databaseDriver string
databaseLocation string
retention int
eventDeletion bool
logger logging.Logger
}
@@ -54,11 +56,12 @@ type EventRow struct {
}
// NewEventListener initialize EventListener.
func NewEventListener(databaseDriver, databaseLocation string, retention int) *EventListener {
func NewEventListener(databaseDriver, databaseLocation string, retention int, eventDeletion bool) *EventListener {
return &EventListener{
databaseDriver: databaseDriver,
databaseLocation: databaseLocation,
retention: retention,
eventDeletion: eventDeletion,
logger: registry.SetupLogging("events.event_listener"),
}
}
@@ -74,7 +77,7 @@ func (e *EventListener) ProcessEvents(request *http.Request) {
e.logger.Debugf("Received event: %+v", t)
j, _ := json.Marshal(t)
db, err := e.getDababaseHandler()
db, err := e.getDatabaseHandler()
if err != nil {
e.logger.Error(err)
return
@@ -112,6 +115,9 @@ func (e *EventListener) ProcessEvents(request *http.Request) {
}
// Purge old records.
if !e.eventDeletion {
return
}
var res sql.Result
if e.databaseDriver == "mysql" {
stmt, _ := db.Prepare("DELETE FROM events WHERE created < DATE_SUB(NOW(), INTERVAL ? DAY)")
@@ -128,7 +134,7 @@ func (e *EventListener) ProcessEvents(request *http.Request) {
func (e *EventListener) GetEvents(repository string) []EventRow {
var events []EventRow
db, err := e.getDababaseHandler()
db, err := e.getDatabaseHandler()
if err != nil {
e.logger.Error(err)
return events
@@ -154,7 +160,7 @@ func (e *EventListener) GetEvents(repository string) []EventRow {
return events
}
func (e *EventListener) getDababaseHandler() (*sql.DB, error) {
func (e *EventListener) getDatabaseHandler() (*sql.DB, error) {
firstRun := false
schema := schemaSQLite
if e.databaseDriver == "sqlite3" {

7
go.mod
View File

@@ -10,7 +10,6 @@ require (
github.com/hhkbp2/go-logging v0.0.0-20171106042747-377ba05d9897
github.com/hhkbp2/go-strftime v0.0.0-20150709091403-d82166ec6782 // indirect
github.com/hhkbp2/testify v0.0.0-20150512090439-112845ebc045 // indirect
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.2.8 // indirect
@@ -21,16 +20,12 @@ require (
github.com/parnurzeal/gorequest v0.2.15
github.com/pkg/errors v0.0.0-20180311214515-816c9085562c // indirect
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945
github.com/stretchr/testify v1.3.0 // indirect
github.com/tidwall/gjson v1.1.3
github.com/tidwall/match v1.0.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 // indirect
golang.org/x/net v0.0.0-20181217023233-e147a9138326 // indirect
golang.org/x/sys v0.0.0-20181217223516-dcdaa6325bcb // indirect
google.golang.org/appengine v1.3.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.2

26
go.sum
View File

@@ -2,6 +2,7 @@ github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a h1:3SgJcK9l5
github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
github.com/CloudyKit/jet v2.1.2+incompatible h1:ybZoYzMBdoijK6I+Ke3vg9GZsmlKo/ZhKdNMWz0P26c=
github.com/CloudyKit/jet v2.1.2+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -10,6 +11,7 @@ github.com/elazarl/goproxy v0.0.0-20181111060418-2ce16c963a8a/go.mod h1:/Zj4wYkg
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hhkbp2/go-logging v0.0.0-20171106042747-377ba05d9897 h1:0vxLTAKJQ8n7revuQ11xssUZbuyGwMuDGMRdaxrviuM=
@@ -18,13 +20,14 @@ github.com/hhkbp2/go-strftime v0.0.0-20150709091403-d82166ec6782 h1:Evl9i7wBY3bj
github.com/hhkbp2/go-strftime v0.0.0-20150709091403-d82166ec6782/go.mod h1:x8/IOQ5qQ4DKfiTmD9wBhQ40edg5wh7gMRwdLg07mMw=
github.com/hhkbp2/testify v0.0.0-20150512090439-112845ebc045 h1:MmQwR3zANTXzs2yZexVBDY6qcH2vJXOl/2dZFkWVM7w=
github.com/hhkbp2/testify v0.0.0-20150512090439-112845ebc045/go.mod h1:8DUHF4igllRoOCbQKJsylsDqROcRtPTdb+SQUfjCYLo=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
@@ -46,9 +49,10 @@ github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 h1:x7xEyJDP7Hv3LVgvWhz
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI=
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tidwall/gjson v1.1.3 h1:u4mspaByxY+Qk4U1QYYVzGFI8qxN/3jtEV0ZDb2vRic=
github.com/tidwall/gjson v1.1.3/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
@@ -58,14 +62,16 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 h1:gKMu1Bf6QINDnvyZuTaACm9ofY+PRh+5vFz4oxBZeF8=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181217023233-e147a9138326 h1:iCzOf0xz39Tstp+Tu/WwyGjUXCk34QhQORRxBeXXTA4=
golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20181217223516-dcdaa6325bcb h1:zzdd4xkMwu/GRxhSUJaCPh4/jil9kAbsU7AUmXboO+A=
golang.org/x/sys v0.0.0-20181217223516-dcdaa6325bcb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -31,6 +31,7 @@ type configData struct {
EventRetentionDays int `yaml:"event_retention_days"`
EventDatabaseDriver string `yaml:"event_database_driver"`
EventDatabaseLocation string `yaml:"event_database_location"`
EventDeletionEnabled bool `yaml:"event_deletion_enabled"`
CacheRefreshInterval uint8 `yaml:"cache_refresh_interval"`
AnyoneCanDelete bool `yaml:"anyone_can_delete"`
Admins []string `yaml:"admins"`
@@ -128,7 +129,9 @@ func main() {
if a.config.EventDatabaseDriver != "sqlite3" && a.config.EventDatabaseDriver != "mysql" {
panic(fmt.Errorf("event_database_driver should be either sqlite3 or mysql"))
}
a.eventListener = events.NewEventListener(a.config.EventDatabaseDriver, a.config.EventDatabaseLocation, a.config.EventRetentionDays)
a.eventListener = events.NewEventListener(
a.config.EventDatabaseDriver, a.config.EventDatabaseLocation, a.config.EventRetentionDays, a.config.EventDeletionEnabled,
)
// Template engine init.
e := echo.New()

View File

@@ -1,6 +1,7 @@
package registry
import (
"crypto"
"crypto/tls"
"fmt"
"regexp"
@@ -124,9 +125,17 @@ func (c *Client) callRegistry(uri, scope string, manifest uint, delete bool) (st
return "", resp
}
digest := resp.Header.Get("Docker-Content-Digest")
if digest == "" {
// Try to get digest from body instead, should be equal to what would be presented
// in Docker-Content-Digest
h := crypto.SHA256.New()
h.Write([]byte(data))
resp.Header.Set("Docker-Content-Digest", fmt.Sprintf("sha256:%x", h.Sum(nil)))
}
if delete {
// Delete by manifest digest reference.
digest := resp.Header.Get("Docker-Content-Digest")
parts := strings.Split(uri, "/manifests/")
uri = parts[0] + "/manifests/" + digest
resp, _, errs := c.request.Delete(c.url+uri).Set("Accept", acceptHeader).Set("Authorization", authHeader).Set("User-Agent", "docker-registry-ui").End()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -12,10 +12,10 @@
<body>
<div class="container">
<div style="float: left">
<h2>Docker Registry UI</h2>
<h2><a href="{{ basePath }}/" style="text-decoration: none">Docker Registry UI</a></h2>
</div>
<div style="float: right">
<a href="{{ basePath }}/events">Event Log</a>
<h4><a href="{{ basePath }}/events">Event Log</a></h4>
</div>
<div style="clear: both"></div>

View File

@@ -17,7 +17,6 @@
{{block body()}}
<ol class="breadcrumb">
<li><a href="{{ basePath }}/">Home</a></li>
<li class="active">Event Log</li>
</ol>

View File

@@ -41,7 +41,10 @@
</div>
<ol class="breadcrumb">
<li><a href="{{ basePath }}/">Home</a></li>
<li><a href="{{ basePath }}/">{{ registryHost }}</a></li>
{{if namespace != "library"}}
<li><a href="{{ basePath }}/{{ namespace }}">{{ namespace }}</a></li>
{{end}}
</ol>
<table id="datatable" class="table table-striped table-bordered">

View File

@@ -4,7 +4,7 @@
{{block body()}}
<ol class="breadcrumb">
<li><a href="{{ basePath }}/">Home</a></li>
<li><a href="{{ basePath }}/">{{ registryHost }}</a></li>
{{if namespace != "library"}}
<li><a href="{{ basePath }}/{{ namespace }}">{{ namespace }}</a></li>
{{end}}

View File

@@ -32,7 +32,7 @@
{{block body()}}
<ol class="breadcrumb">
<li><a href="{{ basePath }}/">Home</a></li>
<li><a href="{{ basePath }}/">{{ registryHost }}</a></li>
{{if namespace != "library"}}
<li><a href="{{ basePath }}/{{ namespace }}">{{ namespace }}</a></li>
{{end}}

View File

@@ -1,3 +1,3 @@
package main
const version = "0.8.0"
const version = "0.8.2"