keel/registry/registry.go

163 lines
3.3 KiB
Go
Raw Normal View History

2017-07-01 12:03:00 +00:00
package registry
import (
2018-03-31 21:08:22 +00:00
"crypto/tls"
2017-07-01 12:03:00 +00:00
"errors"
2018-03-31 21:08:22 +00:00
"hash/fnv"
"net/http"
2018-03-27 13:05:30 +00:00
"os"
2018-03-31 21:08:22 +00:00
"strings"
"sync"
"time"
2017-07-01 12:03:00 +00:00
"github.com/rusenask/docker-registry-client/registry"
2017-07-03 08:06:56 +00:00
2018-03-03 11:32:00 +00:00
log "github.com/sirupsen/logrus"
2017-07-01 12:03:00 +00:00
)
2018-03-27 13:05:30 +00:00
// EnvInsecure - uses insecure registry client to skip cert verification
const EnvInsecure = "INSECURE_REGISTRY"
2017-07-01 12:03:00 +00:00
// errors
var (
ErrTagNotSupplied = errors.New("tag not supplied")
)
2017-07-02 07:29:26 +00:00
// Repository - holds repository related info
2017-07-01 12:03:00 +00:00
type Repository struct {
Name string
2017-07-02 07:29:26 +00:00
Tags []string // available tags
2017-07-01 12:03:00 +00:00
}
2017-08-08 20:47:29 +00:00
// Client - generic docker registry client
2017-07-01 12:03:00 +00:00
type Client interface {
2017-07-02 07:29:26 +00:00
Get(opts Opts) (*Repository, error)
Digest(opts Opts) (string, error)
2017-07-01 12:03:00 +00:00
}
2017-08-08 20:47:29 +00:00
// New - new registry client
2017-07-01 12:03:00 +00:00
func New() *DefaultClient {
2018-03-31 21:08:22 +00:00
return &DefaultClient{
mu: &sync.Mutex{},
registries: make(map[uint32]*registry.Registry),
}
2017-07-01 12:03:00 +00:00
}
2017-08-08 20:47:29 +00:00
// DefaultClient - default client implementation
2017-07-01 12:03:00 +00:00
type DefaultClient struct {
2018-03-31 21:08:22 +00:00
// a map of registries to reuse for polling
mu *sync.Mutex
registries map[uint32]*registry.Registry
2017-07-01 12:03:00 +00:00
}
2017-08-08 20:47:29 +00:00
// Opts - registry client opts. If username & password are not supplied
// it will try to authenticate as anonymous
2017-07-01 12:03:00 +00:00
type Opts struct {
Registry, Name, Tag string
Username, Password string // if "" - anonymous
}
2017-07-16 19:45:26 +00:00
// LogFormatter - formatter callback passed into registry client
func LogFormatter(format string, args ...interface{}) {
log.Debugf(format, args...)
}
2018-03-31 21:08:22 +00:00
func hash(s string) uint32 {
h := fnv.New32a()
h.Write([]byte(s))
return h.Sum32()
}
2017-07-01 12:03:00 +00:00
2018-03-31 21:08:22 +00:00
func (c *DefaultClient) getRegistryClient(registryAddress, username, password string) (*registry.Registry, error) {
c.mu.Lock()
defer c.mu.Unlock()
2018-03-27 13:05:30 +00:00
2018-03-31 21:08:22 +00:00
var r *registry.Registry
2018-03-27 13:05:30 +00:00
2018-03-31 21:08:22 +00:00
h := hash(registryAddress + username + password)
r, ok := c.registries[h]
if ok {
return r, nil
}
url := strings.TrimSuffix(registryAddress, "/")
2018-03-27 13:05:30 +00:00
if os.Getenv(EnvInsecure) == "true" {
2018-03-31 21:08:22 +00:00
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,
},
},
2018-03-27 13:05:30 +00:00
}
} else {
2018-03-31 21:08:22 +00:00
r = &registry.Registry{
URL: url,
Client: &http.Client{
Transport: &registry.BasicTransport{
Transport: http.DefaultTransport,
URL: url,
Username: username,
Password: password,
},
},
2018-03-27 13:05:30 +00:00
}
2017-07-01 12:03:00 +00:00
}
2018-03-27 13:05:30 +00:00
2018-03-31 21:08:22 +00:00
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
}
2017-07-01 12:03:00 +00:00
tags, err := hub.Tags(opts.Name)
if err != nil {
return nil, err
}
2018-03-31 21:08:22 +00:00
repo := &Repository{
Tags: tags,
}
2017-07-01 12:03:00 +00:00
return repo, nil
}
// Digest - get digest for repo
func (c *DefaultClient) Digest(opts Opts) (string, error) {
2017-07-01 12:03:00 +00:00
if opts.Tag == "" {
return "", ErrTagNotSupplied
}
2018-03-31 21:08:22 +00:00
hub, err := c.getRegistryClient(opts.Registry, opts.Username, opts.Password)
if err != nil {
return "", err
2017-07-01 12:03:00 +00:00
}
2017-07-01 12:03:00 +00:00
manifestDigest, err := hub.ManifestDigest(opts.Name, opts.Tag)
if err != nil {
return "", err
2017-07-01 12:03:00 +00:00
}
return manifestDigest.String(), nil
}