Skip to content

Commit a28b775

Browse files
committed
feat: move cache layer into registry interface
One central place to handle caching
1 parent e168a0b commit a28b775

File tree

7 files changed

+79
-71
lines changed

7 files changed

+79
-71
lines changed

Makefile

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ TEST_OPTIONS?=
88
export GO111MODULE := on
99
export GOPROXY = https://proxy.golang.org,direct
1010
export GOFLAGS ?= -tags=containers_image_openpgp,exclude_graphdriver_btrfs,btrfs_noversion,exclude_graphdriver_devicemapper
11-
export CGO_ENABLED ?=0
1211

1312
help: ## List targets & descriptions
1413
@cat Makefile* | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

pkg/backend/cached.go

-44
This file was deleted.

pkg/backend/native.go

-3
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ func (n *Native) newContext(creds Credentials) *ctypes.SystemContext {
4141
return &ctypes.SystemContext{
4242
AuthFilePath: creds.AuthFile,
4343
DockerAuthConfig: dockerAuth,
44-
45-
// It actually defaults to the current runtime, so we may not need to override it
46-
// OSChoice: "linux",
4744
}
4845
}
4946

pkg/backend/skopeo.go

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ func (s *Skopeo) Copy(ctx context.Context, srcRef ctypes.ImageReference, srcCred
6565
dest := destRef.DockerReference().String()
6666
app := "skopeo"
6767
args := []string{
68-
"--override-os", "linux",
6968
"copy",
7069
"--multi-arch", "all",
7170
"--retry-times", "3",

pkg/registry/cache.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package registry
2+
3+
import (
4+
"context"
5+
6+
ctypes "github.com/containers/image/v5/types"
7+
"github.com/dgraph-io/ristretto"
8+
"github.com/rs/zerolog/log"
9+
)
10+
11+
// Cached registry cache requests
12+
type Cached struct {
13+
Cache *ristretto.Cache
14+
Registry Client
15+
}
16+
17+
func NewCachedClient(cache *ristretto.Cache, registry Client) (*Cached, error) {
18+
return &Cached{
19+
Registry: registry,
20+
Cache: cache,
21+
}, nil
22+
}
23+
24+
func (c *Cached) CreateRepository(ctx context.Context, name string) error {
25+
if _, found := c.Cache.Get(name); found {
26+
log.Ctx(ctx).Trace().Str("name", name).Str("method", "CreateRepository").Msg("found in cache")
27+
return nil
28+
}
29+
30+
err := c.Registry.CreateRepository(ctx, name)
31+
32+
if err == nil {
33+
c.Cache.Set(name, "", 1)
34+
}
35+
36+
return err
37+
}
38+
39+
func (c *Cached) ImageExists(ctx context.Context, imageRef ctypes.ImageReference) bool {
40+
ref := imageRef.DockerReference().String()
41+
if _, found := c.Cache.Get(ref); found {
42+
log.Ctx(ctx).Trace().Str("ref", ref).Str("method", "ImageExists").Msg("found in cache")
43+
return true
44+
}
45+
46+
exists := c.Registry.ImageExists(ctx, imageRef)
47+
48+
if exists {
49+
c.Cache.Set(ref, "", 1)
50+
}
51+
return exists
52+
}
53+
54+
func (c *Cached) CopyImage(ctx context.Context, src ctypes.ImageReference, srcCreds string, dest ctypes.ImageReference, destCreds string) error {
55+
return c.Registry.CopyImage(ctx, src, srcCreds, dest, destCreds)
56+
}
57+
58+
func (c *Cached) Endpoint() string {
59+
return c.Registry.Endpoint()
60+
}
61+
62+
func (c *Cached) Credentials() string {
63+
return c.Registry.Credentials()
64+
}
65+
66+
func (c *Cached) IsOrigin(imageRef ctypes.ImageReference) bool {
67+
return c.Registry.IsOrigin(imageRef)
68+
}

pkg/registry/client.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
// Client provides methods required to be implemented by the various target registry clients, e.g. ECR, Docker, Quay.
1818
type Client interface {
1919
CreateRepository(ctx context.Context, name string) error
20-
RepositoryExists() bool
2120
CopyImage(ctx context.Context, src ctypes.ImageReference, srcCreds string, dest ctypes.ImageReference, destCreds string) error
2221
ImageExists(ctx context.Context, ref ctypes.ImageReference) bool
2322

@@ -48,6 +47,7 @@ func NewClient(r config.Registry, imageBackend backend.Backend) (Client, error)
4847
return nil, err
4948
}
5049

50+
// TODO: reduce cache size and/or make it configurable
5151
cache, err := ristretto.NewCache(&ristretto.Config{
5252
NumCounters: 1e7, // number of keys to track frequency of (10M).
5353
MaxCost: 1 << 30, // maximum cost of cache (1GB).
@@ -57,16 +57,21 @@ func NewClient(r config.Registry, imageBackend backend.Backend) (Client, error)
5757
return nil, err
5858
}
5959

60-
cachedBackend := backend.NewCached(cache, imageBackend)
61-
60+
var registryClient Client
6261
switch registry {
6362
case types.RegistryAWS:
64-
return NewECRClient(r.AWS, cachedBackend, cache)
63+
if registryClient, err = NewECRClient(r.AWS, imageBackend); err != nil {
64+
return nil, err
65+
}
6566
case types.RegistryGCP:
66-
return NewGARClient(r.GCP, cachedBackend)
67+
if registryClient, err = NewGARClient(r.GCP, imageBackend); err != nil {
68+
return nil, err
69+
}
6770
default:
6871
return nil, fmt.Errorf(`registry of type "%s" is not supported`, r.Type)
6972
}
73+
74+
return NewCachedClient(cache, registryClient)
7075
}
7176

7277
func GenerateDockerConfig(c Client) ([]byte, error) {

pkg/registry/ecr.go

+1-17
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/aws/aws-sdk-go/service/ecr"
1717
"github.com/aws/aws-sdk-go/service/ecr/ecriface"
1818
ctypes "github.com/containers/image/v5/types"
19-
"github.com/dgraph-io/ristretto"
2019
"github.com/estahn/k8s-image-swapper/pkg/backend"
2120
"github.com/estahn/k8s-image-swapper/pkg/config"
2221
"github.com/go-co-op/gocron"
@@ -27,7 +26,6 @@ type ECRClient struct {
2726
client ecriface.ECRAPI
2827
ecrDomain string
2928
authToken []byte
30-
cache *ristretto.Cache
3129
scheduler *gocron.Scheduler
3230
targetAccount string
3331
accessPolicy string
@@ -36,7 +34,7 @@ type ECRClient struct {
3634
backend backend.Backend
3735
}
3836

39-
func NewECRClient(clientConfig config.AWS, imageBackend backend.Backend, cache *ristretto.Cache) (*ECRClient, error) {
37+
func NewECRClient(clientConfig config.AWS, imageBackend backend.Backend) (*ECRClient, error) {
4038
ecrDomain := clientConfig.EcrDomain()
4139

4240
var sess *session.Session
@@ -73,7 +71,6 @@ func NewECRClient(clientConfig config.AWS, imageBackend backend.Backend, cache *
7371
client := &ECRClient{
7472
client: ecrClient,
7573
ecrDomain: ecrDomain,
76-
cache: cache,
7774
scheduler: scheduler,
7875
targetAccount: clientConfig.AccountID,
7976
accessPolicy: clientConfig.ECROptions.AccessPolicy,
@@ -94,10 +91,6 @@ func (e *ECRClient) Credentials() string {
9491
}
9592

9693
func (e *ECRClient) CreateRepository(ctx context.Context, name string) error {
97-
if _, found := e.cache.Get(name); found {
98-
return nil
99-
}
100-
10194
log.Ctx(ctx).Debug().Str("repository", name).Msg("create repository")
10295

10396
_, err := e.client.CreateRepositoryWithContext(ctx, &ecr.CreateRepositoryInput{
@@ -153,8 +146,6 @@ func (e *ECRClient) CreateRepository(ctx context.Context, name string) error {
153146
}
154147
}
155148

156-
e.cache.Set(name, "", 1)
157-
158149
return nil
159150
}
160151

@@ -189,12 +180,6 @@ func (e *ECRClient) ImageExists(ctx context.Context, imageRef ctypes.ImageRefere
189180
Creds: e.Credentials(),
190181
}
191182

192-
ref := imageRef.DockerReference().String()
193-
if _, found := e.cache.Get(ref); found {
194-
log.Ctx(ctx).Trace().Str("ref", ref).Msg("found in cache")
195-
return true
196-
}
197-
198183
exists, err := e.backend.Exists(ctx, imageRef, creds)
199184
if err != nil {
200185
log.Error().Err(err).Msg("unable to check existence of image")
@@ -266,7 +251,6 @@ func NewMockECRClient(ecrClient ecriface.ECRAPI, region string, ecrDomain string
266251
client := &ECRClient{
267252
client: ecrClient,
268253
ecrDomain: ecrDomain,
269-
cache: nil,
270254
scheduler: nil,
271255
targetAccount: targetAccount,
272256
authToken: []byte("mock-ecr-client-fake-auth-token"),

0 commit comments

Comments
 (0)