reusing registry client

pull/178/head
Karolis Rusenas 2018-03-31 22:08:22 +01:00
parent 63a9c5d608
commit b2aaf46acc
2 changed files with 81 additions and 38 deletions

View File

@ -1,8 +1,14 @@
package registry
import (
"crypto/tls"
"errors"
"hash/fnv"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/rusenask/docker-registry-client/registry"
@ -31,11 +37,17 @@ type Client interface {
// New - new registry client
func New() *DefaultClient {
return &DefaultClient{}
return &DefaultClient{
mu: &sync.Mutex{},
registries: make(map[uint32]*registry.Registry),
}
}
// DefaultClient - default client implementation
type DefaultClient struct {
// a map of registries to reuse for polling
mu *sync.Mutex
registries map[uint32]*registry.Registry
}
// Opts - registry client opts. If username & password are not supplied
@ -50,33 +62,82 @@ func LogFormatter(format string, args ...interface{}) {
log.Debugf(format, args...)
}
// Get - get repository
func (c *DefaultClient) Get(opts Opts) (*Repository, error) {
func hash(s string) uint32 {
h := fnv.New32a()
h.Write([]byte(s))
return h.Sum32()
}
repo := &Repository{}
func (c *DefaultClient) getRegistryClient(registryAddress, username, password string) (*registry.Registry, error) {
c.mu.Lock()
defer c.mu.Unlock()
var hub *registry.Registry
var err error
var r *registry.Registry
h := hash(registryAddress + username + password)
r, ok := c.registries[h]
if ok {
return r, nil
}
url := strings.TrimSuffix(registryAddress, "/")
if os.Getenv(EnvInsecure) == "true" {
hub, err = registry.NewInsecure(opts.Registry, opts.Username, opts.Password)
if err != nil {
return nil, err
r = &registry.Registry{
URL: url,
Client: &http.Client{
Transport: &registry.BasicTransport{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
MaxIdleConns: 10,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
URL: url,
Username: username,
Password: password,
},
},
}
} else {
hub, err = registry.New(opts.Registry, opts.Username, opts.Password)
if err != nil {
return nil, err
r = &registry.Registry{
URL: url,
Client: &http.Client{
Transport: &registry.BasicTransport{
Transport: http.DefaultTransport,
URL: url,
Username: username,
Password: password,
},
},
}
}
hub.Logf = LogFormatter
r.Logf = LogFormatter
c.registries[h] = r
return r, nil
}
// Get - get repository
func (c *DefaultClient) Get(opts Opts) (*Repository, error) {
hub, err := c.getRegistryClient(opts.Registry, opts.Username, opts.Password)
if err != nil {
return nil, err
}
tags, err := hub.Tags(opts.Name)
if err != nil {
return nil, err
}
repo.Tags = tags
repo := &Repository{
Tags: tags,
}
return repo, nil
}
@ -87,29 +148,11 @@ func (c *DefaultClient) Digest(opts Opts) (string, error) {
return "", ErrTagNotSupplied
}
log.WithFields(log.Fields{
"registry": opts.Registry,
"repository": opts.Name,
"tag": opts.Tag,
}).Debug("registry client: getting digest")
var hub *registry.Registry
var err error
if os.Getenv(EnvInsecure) == "true" {
hub, err = registry.NewInsecure(opts.Registry, opts.Username, opts.Password)
if err != nil {
return "", err
}
} else {
hub, err = registry.New(opts.Registry, opts.Username, opts.Password)
if err != nil {
return "", err
}
hub, err := c.getRegistryClient(opts.Registry, opts.Username, opts.Password)
if err != nil {
return "", err
}
hub.Logf = LogFormatter
manifestDigest, err := hub.ManifestDigest(opts.Name, opts.Tag)
if err != nil {
return "", err

View File

@ -13,15 +13,15 @@ func TestDigest(t *testing.T) {
client := New()
digest, err := client.Digest(Opts{
Registry: "https://index.docker.io",
Name: "karolisr/keel",
Tag: "0.2.2",
Name: "karolisr/webhook-demo",
Tag: "alpha",
})
if err != nil {
t.Errorf("error while getting digest: %s", err)
}
if digest != "sha256:0604af35299dd37ff23937d115d103532948b568a9dd8197d14c256a8ab8b0bb" {
if digest != "sha256:c76aa6ac847308941171a21ca87d611a8b7ec1511ed841f0a7646aa1eb3064b8" {
t.Errorf("unexpected digest: %s", digest)
}
}