diff --git a/internal/app/job.go b/internal/app/job.go index c213867f..04274c2a 100644 --- a/internal/app/job.go +++ b/internal/app/job.go @@ -6,8 +6,7 @@ import ( "time" "github.com/crazy-max/diun/internal/model" - "github.com/crazy-max/diun/pkg/docker" - "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/registry" "github.com/crazy-max/diun/pkg/utl" "github.com/imdario/mergo" "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, Arch: job.Image.Arch, Username: regUser, @@ -99,7 +98,7 @@ func (di *Diun) createJob(job model.Job) { return } - tags, err := job.Registry.Tags(docker.TagsOptions{ + tags, err := job.Registry.Tags(registry.TagsOptions{ Image: job.RegImage, Max: job.Image.MaxTags, Include: job.Image.IncludeTags, diff --git a/internal/db/client.go b/internal/db/client.go index 6efe4d89..d8c0722f 100644 --- a/internal/db/client.go +++ b/internal/db/client.go @@ -7,8 +7,7 @@ import ( "time" "github.com/crazy-max/diun/internal/model" - "github.com/crazy-max/diun/pkg/docker" - "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/registry" "github.com/rs/zerolog/log" bolt "go.etcd.io/bbolt" ) @@ -72,8 +71,8 @@ func (c *Client) First(image registry.Image) (bool, error) { } // GetManifest returns Docker image manifest -func (c *Client) GetManifest(image registry.Image) (docker.Manifest, error) { - var manifest docker.Manifest +func (c *Client) GetManifest(image registry.Image) (registry.Manifest, error) { + var manifest registry.Manifest err := c.View(func(tx *bolt.Tx) error { 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 -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) err := c.Update(func(tx *bolt.Tx) error { diff --git a/internal/model/job.go b/internal/model/job.go index 4d19107c..1bf10485 100644 --- a/internal/model/job.go +++ b/internal/model/job.go @@ -1,8 +1,7 @@ package model import ( - "github.com/crazy-max/diun/pkg/docker" - "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/registry" ) // Job holds job configuration @@ -10,6 +9,6 @@ type Job struct { Provider string Image Image RegImage registry.Image - Registry *docker.RegistryClient + Registry *registry.Client FirstCheck bool } diff --git a/internal/model/notif.go b/internal/model/notif.go index 0d136755..80714e27 100644 --- a/internal/model/notif.go +++ b/internal/model/notif.go @@ -1,16 +1,15 @@ package model import ( - "github.com/crazy-max/diun/pkg/docker" - "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/registry" ) // NotifEntry represents a notification entry type NotifEntry struct { - Status ImageStatus `json:"status,omitempty"` - Provider string `json:"provider,omitempty"` - Image registry.Image `json:"image,omitempty"` - Manifest docker.Manifest `json:"manifest,omitempty"` + Status ImageStatus `json:"status,omitempty"` + Provider string `json:"provider,omitempty"` + Image registry.Image `json:"image,omitempty"` + Manifest registry.Manifest `json:"manifest,omitempty"` } // Notif holds data necessary for notification configuration diff --git a/internal/provider/docker/container.go b/internal/provider/docker/container.go index 5f74be9d..6bd9f746 100644 --- a/internal/provider/docker/container.go +++ b/internal/provider/docker/container.go @@ -16,7 +16,12 @@ func (c *Client) listContainerImage(id string, elt model.PrdDocker) []model.Imag Str("provider", fmt.Sprintf("docker-%s", id)). 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 { sublog.Error().Err(err).Msg("Cannot create Docker client") return []model.Image{} diff --git a/internal/provider/swarm/service.go b/internal/provider/swarm/service.go index edbdfc56..a15fb476 100644 --- a/internal/provider/swarm/service.go +++ b/internal/provider/swarm/service.go @@ -16,7 +16,12 @@ func (c *Client) listServiceImage(id string, elt model.PrdSwarm) []model.Image { Str("provider", fmt.Sprintf("swarm-%s", id)). 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 { sublog.Error().Err(err).Msg("Cannot create Docker client") return []model.Image{} diff --git a/pkg/docker/client.go b/pkg/docker/client.go index 3c80be4b..294f7034 100644 --- a/pkg/docker/client.go +++ b/pkg/docker/client.go @@ -16,21 +16,29 @@ type Client struct { 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)) +// Options holds docker client object options +type Options struct { + Endpoint string + APIVersion string + 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 != "" { - opts = append(opts, client.WithVersion(apiVersion)) + if opts.APIVersion != "" { + dockerOpts = append(dockerOpts, client.WithVersion(opts.APIVersion)) } - if tlsCertsPath != "" { + if opts.TLSCertPath != "" { options := tlsconfig.Options{ - CAFile: filepath.Join(tlsCertsPath, "ca.pem"), - CertFile: filepath.Join(tlsCertsPath, "cert.pem"), - KeyFile: filepath.Join(tlsCertsPath, "key.pem"), - InsecureSkipVerify: !tlsVerify, + CAFile: filepath.Join(opts.TLSCertPath, "ca.pem"), + CertFile: filepath.Join(opts.TLSCertPath, "cert.pem"), + KeyFile: filepath.Join(opts.TLSCertPath, "key.pem"), + InsecureSkipVerify: !opts.TLSVerify, } tlsc, err := tlsconfig.Client(options) if err != nil { @@ -40,10 +48,10 @@ func NewClient(endpoint, apiVersion, tlsCertsPath string, tlsVerify bool) (*Clie Transport: &http.Transport{TLSClientConfig: tlsc}, 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 { return nil, err } diff --git a/pkg/docker/registry/name.go b/pkg/docker/registry/name.go deleted file mode 100644 index e0ee2c22..00000000 --- a/pkg/docker/registry/name.go +++ /dev/null @@ -1,6 +0,0 @@ -package registry - -// Name returns the full name representation of an image. -func (i Image) Name() string { - return i.named.Name() -} diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go new file mode 100644 index 00000000..2ffa851a --- /dev/null +++ b/pkg/kubernetes/client.go @@ -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 +} diff --git a/pkg/docker/registry/image.go b/pkg/registry/image.go similarity index 93% rename from pkg/docker/registry/image.go rename to pkg/registry/image.go index a842f677..67cc1c3e 100644 --- a/pkg/docker/registry/image.go +++ b/pkg/registry/image.go @@ -17,6 +17,11 @@ type Image struct { 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. func (i Image) String() string { return i.named.String() diff --git a/pkg/docker/manifest.go b/pkg/registry/manifest.go similarity index 90% rename from pkg/docker/manifest.go rename to pkg/registry/manifest.go index a9358c7c..b6d90380 100644 --- a/pkg/docker/manifest.go +++ b/pkg/registry/manifest.go @@ -1,10 +1,9 @@ -package docker +package registry import ( "time" "github.com/containers/image/manifest" - "github.com/crazy-max/diun/pkg/docker/registry" "github.com/opencontainers/go-digest" ) @@ -22,7 +21,7 @@ type Manifest struct { } // 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() defer cancel() diff --git a/pkg/docker/registry.go b/pkg/registry/registry.go similarity index 71% rename from pkg/docker/registry.go rename to pkg/registry/registry.go index e6df7301..b606df92 100644 --- a/pkg/docker/registry.go +++ b/pkg/registry/registry.go @@ -1,4 +1,4 @@ -package docker +package registry import ( "context" @@ -10,14 +10,14 @@ import ( "github.com/containers/image/types" ) -// RegistryClient represents an active docker registry object -type RegistryClient struct { - opts RegistryOptions +// Client represents an active docker registry object +type Client struct { + opts Options sysCtx *types.SystemContext } -// RegistryOptions holds docker registry object options -type RegistryOptions struct { +// Options holds docker registry object options +type Options struct { Os string Arch string Username string @@ -27,8 +27,8 @@ type RegistryOptions struct { UserAgent string } -// NewRegistryClient creates new docker registry client instance -func NewRegistryClient(opts RegistryOptions) (*RegistryClient, error) { +// New creates new docker registry client instance +func New(opts Options) (*Client, error) { // Auth auth := &types.DockerAuthConfig{} if opts.Username != "" { @@ -48,12 +48,12 @@ func NewRegistryClient(opts RegistryOptions) (*RegistryClient, error) { DockerRegistryUserAgent: opts.UserAgent, } - return &RegistryClient{ + return &Client{ sysCtx: sysCtx, }, nil } -func (c *RegistryClient) timeoutContext() (context.Context, context.CancelFunc) { +func (c *Client) timeoutContext() (context.Context, context.CancelFunc) { ctx := context.Background() var cancel context.CancelFunc = func() {} if c.opts.Timeout > 0 { @@ -62,7 +62,7 @@ func (c *RegistryClient) timeoutContext() (context.Context, context.CancelFunc) 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, "//") { imageStr = fmt.Sprintf("//%s", imageStr) } diff --git a/pkg/docker/tags.go b/pkg/registry/tags.go similarity index 88% rename from pkg/docker/tags.go rename to pkg/registry/tags.go index a1453431..918500ef 100644 --- a/pkg/docker/tags.go +++ b/pkg/registry/tags.go @@ -1,8 +1,7 @@ -package docker +package registry import ( "github.com/containers/image/docker" - "github.com/crazy-max/diun/pkg/docker/registry" "github.com/crazy-max/diun/pkg/utl" ) @@ -14,14 +13,14 @@ type Tags struct { } type TagsOptions struct { - Image registry.Image + Image Image Max int Include []string Exclude []string } // 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() defer cancel()