Move registry client to a dedicated package

This commit is contained in:
CrazyMax
2020-01-08 14:20:25 +01:00
parent 883977b5d9
commit fbfc7a2690
13 changed files with 130 additions and 58 deletions

View File

@@ -6,8 +6,7 @@ import (
"time" "time"
"github.com/crazy-max/diun/internal/model" "github.com/crazy-max/diun/internal/model"
"github.com/crazy-max/diun/pkg/docker" "github.com/crazy-max/diun/pkg/registry"
"github.com/crazy-max/diun/pkg/docker/registry"
"github.com/crazy-max/diun/pkg/utl" "github.com/crazy-max/diun/pkg/utl"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@@ -75,7 +74,7 @@ func (di *Diun) createJob(job model.Job) {
} }
} }
job.Registry, err = docker.NewRegistryClient(docker.RegistryOptions{ job.Registry, err = registry.New(registry.Options{
Os: job.Image.Os, Os: job.Image.Os,
Arch: job.Image.Arch, Arch: job.Image.Arch,
Username: regUser, Username: regUser,
@@ -99,7 +98,7 @@ func (di *Diun) createJob(job model.Job) {
return return
} }
tags, err := job.Registry.Tags(docker.TagsOptions{ tags, err := job.Registry.Tags(registry.TagsOptions{
Image: job.RegImage, Image: job.RegImage,
Max: job.Image.MaxTags, Max: job.Image.MaxTags,
Include: job.Image.IncludeTags, Include: job.Image.IncludeTags,

View File

@@ -7,8 +7,7 @@ import (
"time" "time"
"github.com/crazy-max/diun/internal/model" "github.com/crazy-max/diun/internal/model"
"github.com/crazy-max/diun/pkg/docker" "github.com/crazy-max/diun/pkg/registry"
"github.com/crazy-max/diun/pkg/docker/registry"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
) )
@@ -72,8 +71,8 @@ func (c *Client) First(image registry.Image) (bool, error) {
} }
// GetManifest returns Docker image manifest // GetManifest returns Docker image manifest
func (c *Client) GetManifest(image registry.Image) (docker.Manifest, error) { func (c *Client) GetManifest(image registry.Image) (registry.Manifest, error) {
var manifest docker.Manifest var manifest registry.Manifest
err := c.View(func(tx *bolt.Tx) error { err := c.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(bucket)) b := tx.Bucket([]byte(bucket))
@@ -87,7 +86,7 @@ func (c *Client) GetManifest(image registry.Image) (docker.Manifest, error) {
} }
// PutManifest add Docker image manifest in db // PutManifest add Docker image manifest in db
func (c *Client) PutManifest(image registry.Image, manifest docker.Manifest) error { func (c *Client) PutManifest(image registry.Image, manifest registry.Manifest) error {
entryBytes, _ := json.Marshal(manifest) entryBytes, _ := json.Marshal(manifest)
err := c.Update(func(tx *bolt.Tx) error { err := c.Update(func(tx *bolt.Tx) error {

View File

@@ -1,8 +1,7 @@
package model package model
import ( import (
"github.com/crazy-max/diun/pkg/docker" "github.com/crazy-max/diun/pkg/registry"
"github.com/crazy-max/diun/pkg/docker/registry"
) )
// Job holds job configuration // Job holds job configuration
@@ -10,6 +9,6 @@ type Job struct {
Provider string Provider string
Image Image Image Image
RegImage registry.Image RegImage registry.Image
Registry *docker.RegistryClient Registry *registry.Client
FirstCheck bool FirstCheck bool
} }

View File

@@ -1,16 +1,15 @@
package model package model
import ( import (
"github.com/crazy-max/diun/pkg/docker" "github.com/crazy-max/diun/pkg/registry"
"github.com/crazy-max/diun/pkg/docker/registry"
) )
// NotifEntry represents a notification entry // NotifEntry represents a notification entry
type NotifEntry struct { type NotifEntry struct {
Status ImageStatus `json:"status,omitempty"` Status ImageStatus `json:"status,omitempty"`
Provider string `json:"provider,omitempty"` Provider string `json:"provider,omitempty"`
Image registry.Image `json:"image,omitempty"` Image registry.Image `json:"image,omitempty"`
Manifest docker.Manifest `json:"manifest,omitempty"` Manifest registry.Manifest `json:"manifest,omitempty"`
} }
// Notif holds data necessary for notification configuration // Notif holds data necessary for notification configuration

View File

@@ -16,7 +16,12 @@ func (c *Client) listContainerImage(id string, elt model.PrdDocker) []model.Imag
Str("provider", fmt.Sprintf("docker-%s", id)). Str("provider", fmt.Sprintf("docker-%s", id)).
Logger() Logger()
cli, err := docker.NewClient(elt.Endpoint, elt.APIVersion, elt.TLSCertsPath, elt.TLSVerify) cli, err := docker.New(docker.Options{
Endpoint: elt.Endpoint,
APIVersion: elt.APIVersion,
TLSCertPath: elt.TLSCertsPath,
TLSVerify: elt.TLSVerify,
})
if err != nil { if err != nil {
sublog.Error().Err(err).Msg("Cannot create Docker client") sublog.Error().Err(err).Msg("Cannot create Docker client")
return []model.Image{} return []model.Image{}

View File

@@ -16,7 +16,12 @@ func (c *Client) listServiceImage(id string, elt model.PrdSwarm) []model.Image {
Str("provider", fmt.Sprintf("swarm-%s", id)). Str("provider", fmt.Sprintf("swarm-%s", id)).
Logger() Logger()
cli, err := docker.NewClient(elt.Endpoint, elt.APIVersion, elt.TLSCertsPath, elt.TLSVerify) cli, err := docker.New(docker.Options{
Endpoint: elt.Endpoint,
APIVersion: elt.APIVersion,
TLSCertPath: elt.TLSCertsPath,
TLSVerify: elt.TLSVerify,
})
if err != nil { if err != nil {
sublog.Error().Err(err).Msg("Cannot create Docker client") sublog.Error().Err(err).Msg("Cannot create Docker client")
return []model.Image{} return []model.Image{}

View File

@@ -16,21 +16,29 @@ type Client struct {
API *client.Client API *client.Client
} }
// NewClient initializes a new Docker API client with default values // Options holds docker client object options
func NewClient(endpoint, apiVersion, tlsCertsPath string, tlsVerify bool) (*Client, error) { type Options struct {
var opts []client.Opt Endpoint string
if endpoint != "" { APIVersion string
opts = append(opts, client.WithHost(endpoint)) TLSCertPath string
TLSVerify bool
}
// New initializes a new Docker API client with default values
func New(opts Options) (*Client, error) {
var dockerOpts []client.Opt
if opts.Endpoint != "" {
dockerOpts = append(dockerOpts, client.WithHost(opts.Endpoint))
} }
if apiVersion != "" { if opts.APIVersion != "" {
opts = append(opts, client.WithVersion(apiVersion)) dockerOpts = append(dockerOpts, client.WithVersion(opts.APIVersion))
} }
if tlsCertsPath != "" { if opts.TLSCertPath != "" {
options := tlsconfig.Options{ options := tlsconfig.Options{
CAFile: filepath.Join(tlsCertsPath, "ca.pem"), CAFile: filepath.Join(opts.TLSCertPath, "ca.pem"),
CertFile: filepath.Join(tlsCertsPath, "cert.pem"), CertFile: filepath.Join(opts.TLSCertPath, "cert.pem"),
KeyFile: filepath.Join(tlsCertsPath, "key.pem"), KeyFile: filepath.Join(opts.TLSCertPath, "key.pem"),
InsecureSkipVerify: !tlsVerify, InsecureSkipVerify: !opts.TLSVerify,
} }
tlsc, err := tlsconfig.Client(options) tlsc, err := tlsconfig.Client(options)
if err != nil { if err != nil {
@@ -40,10 +48,10 @@ func NewClient(endpoint, apiVersion, tlsCertsPath string, tlsVerify bool) (*Clie
Transport: &http.Transport{TLSClientConfig: tlsc}, Transport: &http.Transport{TLSClientConfig: tlsc},
CheckRedirect: client.CheckRedirect, CheckRedirect: client.CheckRedirect,
} }
opts = append(opts, client.WithHTTPClient(httpCli)) dockerOpts = append(dockerOpts, client.WithHTTPClient(httpCli))
} }
cli, err := client.NewClientWithOpts(opts...) cli, err := client.NewClientWithOpts(dockerOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,6 +0,0 @@
package registry
// Name returns the full name representation of an image.
func (i Image) Name() string {
return i.named.Name()
}

61
pkg/kubernetes/client.go Normal file
View File

@@ -0,0 +1,61 @@
package kubernetes
import (
"context"
"net/http"
"path/filepath"
"github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
)
// Client represents an active docker object
type Client struct {
ctx context.Context
API *client.Client
}
// NewClient initializes a new Docker API client with default values
func NewClient(endpoint, apiVersion, tlsCertsPath string, tlsVerify bool) (*Client, error) {
var opts []client.Opt
if endpoint != "" {
opts = append(opts, client.WithHost(endpoint))
}
if apiVersion != "" {
opts = append(opts, client.WithVersion(apiVersion))
}
if tlsCertsPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(tlsCertsPath, "ca.pem"),
CertFile: filepath.Join(tlsCertsPath, "cert.pem"),
KeyFile: filepath.Join(tlsCertsPath, "key.pem"),
InsecureSkipVerify: !tlsVerify,
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return nil, errors.Wrap(err, "failed to create tls config")
}
httpCli := &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsc},
CheckRedirect: client.CheckRedirect,
}
opts = append(opts, client.WithHTTPClient(httpCli))
}
cli, err := client.NewClientWithOpts(opts...)
if err != nil {
return nil, err
}
ctx := context.Background()
_, err = cli.ServerVersion(ctx)
if err != nil {
return nil, err
}
return &Client{
ctx: ctx,
API: cli,
}, err
}

View File

@@ -17,6 +17,11 @@ type Image struct {
named reference.Named named reference.Named
} }
// Name returns the full name representation of an image.
func (i Image) Name() string {
return i.named.Name()
}
// String returns the string representation of an image. // String returns the string representation of an image.
func (i Image) String() string { func (i Image) String() string {
return i.named.String() return i.named.String()

View File

@@ -1,10 +1,9 @@
package docker package registry
import ( import (
"time" "time"
"github.com/containers/image/manifest" "github.com/containers/image/manifest"
"github.com/crazy-max/diun/pkg/docker/registry"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
@@ -22,7 +21,7 @@ type Manifest struct {
} }
// Manifest returns the manifest for a specific image // Manifest returns the manifest for a specific image
func (c *RegistryClient) Manifest(image registry.Image) (Manifest, error) { func (c *Client) Manifest(image Image) (Manifest, error) {
ctx, cancel := c.timeoutContext() ctx, cancel := c.timeoutContext()
defer cancel() defer cancel()

View File

@@ -1,4 +1,4 @@
package docker package registry
import ( import (
"context" "context"
@@ -10,14 +10,14 @@ import (
"github.com/containers/image/types" "github.com/containers/image/types"
) )
// RegistryClient represents an active docker registry object // Client represents an active docker registry object
type RegistryClient struct { type Client struct {
opts RegistryOptions opts Options
sysCtx *types.SystemContext sysCtx *types.SystemContext
} }
// RegistryOptions holds docker registry object options // Options holds docker registry object options
type RegistryOptions struct { type Options struct {
Os string Os string
Arch string Arch string
Username string Username string
@@ -27,8 +27,8 @@ type RegistryOptions struct {
UserAgent string UserAgent string
} }
// NewRegistryClient creates new docker registry client instance // New creates new docker registry client instance
func NewRegistryClient(opts RegistryOptions) (*RegistryClient, error) { func New(opts Options) (*Client, error) {
// Auth // Auth
auth := &types.DockerAuthConfig{} auth := &types.DockerAuthConfig{}
if opts.Username != "" { if opts.Username != "" {
@@ -48,12 +48,12 @@ func NewRegistryClient(opts RegistryOptions) (*RegistryClient, error) {
DockerRegistryUserAgent: opts.UserAgent, DockerRegistryUserAgent: opts.UserAgent,
} }
return &RegistryClient{ return &Client{
sysCtx: sysCtx, sysCtx: sysCtx,
}, nil }, nil
} }
func (c *RegistryClient) timeoutContext() (context.Context, context.CancelFunc) { func (c *Client) timeoutContext() (context.Context, context.CancelFunc) {
ctx := context.Background() ctx := context.Background()
var cancel context.CancelFunc = func() {} var cancel context.CancelFunc = func() {}
if c.opts.Timeout > 0 { if c.opts.Timeout > 0 {
@@ -62,7 +62,7 @@ func (c *RegistryClient) timeoutContext() (context.Context, context.CancelFunc)
return ctx, cancel return ctx, cancel
} }
func (c *RegistryClient) newImage(ctx context.Context, imageStr string) (types.ImageCloser, error) { func (c *Client) newImage(ctx context.Context, imageStr string) (types.ImageCloser, error) {
if !strings.HasPrefix(imageStr, "//") { if !strings.HasPrefix(imageStr, "//") {
imageStr = fmt.Sprintf("//%s", imageStr) imageStr = fmt.Sprintf("//%s", imageStr)
} }

View File

@@ -1,8 +1,7 @@
package docker package registry
import ( import (
"github.com/containers/image/docker" "github.com/containers/image/docker"
"github.com/crazy-max/diun/pkg/docker/registry"
"github.com/crazy-max/diun/pkg/utl" "github.com/crazy-max/diun/pkg/utl"
) )
@@ -14,14 +13,14 @@ type Tags struct {
} }
type TagsOptions struct { type TagsOptions struct {
Image registry.Image Image Image
Max int Max int
Include []string Include []string
Exclude []string Exclude []string
} }
// Tags returns tags of a Docker repository // Tags returns tags of a Docker repository
func (c *RegistryClient) Tags(opts TagsOptions) (*Tags, error) { func (c *Client) Tags(opts TagsOptions) (*Tags, error) {
ctx, cancel := c.timeoutContext() ctx, cancel := c.timeoutContext()
defer cancel() defer cancel()