Implement same_tag versioning mode

This commit is contained in:
2020-11-11 15:12:59 +01:00
parent c01d192e08
commit 5984349df3
12 changed files with 278 additions and 196 deletions

View File

@ -1,31 +1,35 @@
package registry
import (
"fmt"
"net/http"
l "hulthe.net/lookbuilding/internal/pkg/logging"
"hulthe.net/lookbuilding/internal/pkg/semver"
"github.com/heroku/docker-registry-client/registry"
"github.com/opencontainers/go-digest"
d "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)
type tagListReq struct {
repository string
responder chan<- tagListResp
responder chan<- tagListResp
}
type tagListResp struct {
Data []Tag
Data []Tag
Error error
}
type digestReq struct {
repository string
tag string
responder chan<- digestResp
tag string
responder chan<- digestResp
}
type digestResp struct {
Data digest.Digest
Data d.Digest
Error error
}
@ -33,23 +37,68 @@ type repoCache struct {
Tags []Tag
// Map tags to digests
Digests map[string]digest.Digest
Digests map[string]d.Digest
}
type cache struct {
TagListReq chan<- tagListReq
DigestReq chan<- digestReq
DigestReq chan<- digestReq
}
func newCache(registry registry.Registry) cache {
tagListReq := make(chan tagListReq)
digestReq := make(chan digestReq)
cache := cache{
tagListReq,
digestReq,
}
store := map[string]repoCache{}
go func() {
for {
select {
case req := <-digestReq:
repo, isPresent := store[req.repository]
if !isPresent {
req.responder <- digestResp{Error: errors.Errorf(
`repo "%s" not present in cache, can't fetch digest'`, req.repository,
)}
}
digest, isPresent := repo.Digests[req.tag]
if isPresent {
req.responder <- digestResp{Data: digest}
} else {
url := fmt.Sprintf("%s/v2/%s/manifests/%s", registry.URL, req.repository, req.tag)
l.Logger.Infof("registry.manifest.head url=%s repository=%s reference=%s", url, req.repository, req.tag)
httpReq, _ := http.NewRequest("HEAD", url, nil)
httpReq.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json")
resp, err := registry.Client.Do(httpReq)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
req.responder <- digestResp{Error: errors.Wrapf(
err, "failed to get digest for repo=%s tag=%s", req.repository, req.tag,
)}
}
digest, err := d.Parse(resp.Header.Get("Docker-Content-Digest"))
/*
digest, err := registry.ManifestDigest(req.repository, req.tag)
if err != nil {
req.responder <- digestResp{Error: errors.Wrapf(
err, `failed to get digest for repo=%s tag=%s`, req.repository, req.tag,
)}
}
*/
repo.Digests[req.tag] = digest
req.responder <- digestResp{Data: digest}
}
case req := <-tagListReq:
repo, isPresent := store[req.repository]
@ -71,50 +120,26 @@ func newCache(registry registry.Registry) cache {
var tags []Tag
for _, tagName := range tagNames {
tags = append(tags, Tag{
Name: tagName,
SemVer: semver.ParseTagAsSemVer(tagName),
Name: tagName,
SemVer: semver.ParseTagAsSemVer(tagName),
repository: req.repository,
cache: cache,
})
}
// store result in cache
store[req.repository] = repoCache{
Tags: tags,
Digests: map[string]digest.Digest{},
Digests: map[string]d.Digest{},
}
req.responder <- tagListResp{
Data: tags,
}
}
case req := <-digestReq:
repo, isPresent := store[req.repository]
if !isPresent {
req.responder <- digestResp{Error: errors.Errorf(
`repo "%s" not present in cache, can't fetch digest'`, req.repository,
)}
}
digest, isPresent := repo.Digests[req.tag]
if isPresent {
req.responder <- digestResp{Data: digest}
} else {
digest, err := registry.ManifestDigest(req.repository, req.tag)
if err != nil {
req.responder <- digestResp{Error: errors.Wrapf(
err, `failed to get digest for repo=%s tag=%s`, req.repository, req.tag,
)}
}
repo.Digests[req.tag] = digest
req.responder <- digestResp{Data: digest}
}
}
}
}()
return cache {
tagListReq,
digestReq,
}
}
return cache
}