diff --git a/local/local_test.go b/local/local_test.go index 134248fa..d09f781e 100644 --- a/local/local_test.go +++ b/local/local_test.go @@ -27,6 +27,14 @@ const someSHA = "sha256:aec070645fe53ee3b3763059376134f058cc337247c978add178b6cc var localTestRegistry *h.DockerRegistry +type TestLogger struct { + WarnCalled bool +} + +func (logger *TestLogger) Warn(msg string) { + logger.WarnCalled = true +} + func TestLocal(t *testing.T) { localTestRegistry = h.NewDockerRegistry() localTestRegistry.Start(t) @@ -2028,6 +2036,32 @@ func testImage(t *testing.T, when spec.G, it spec.S) { h.AssertError(t, err, "daemon response") }) }) + when("logger is set", func() { + when("containerd is used", func() { + testLogger := &TestLogger{} + dockerClient := h.DockerCli(t) + imgName := "test-image" + + img, err := local.NewImage(imgName, dockerClient, local.WithLogger(testLogger)) + if err != nil { + t.Fatalf("Failed to create image: %v", err) + } + err = img.Save() + if err != nil { + t.Fatalf("Failed to save image: %v", err) + } + + defer func() { + if err := h.DockerRmi(dockerClient, imgName); err != nil { + t.Errorf("Failed to remove image %s: %v", imgName, err) + } + }() + + if !testLogger.WarnCalled { + t.Error("Expected warning to be logged,but it was not.") + } + }) + }) }) when("#SaveFile", func() { diff --git a/local/new.go b/local/new.go index 72c636fd..dc9e0148 100644 --- a/local/new.go +++ b/local/new.go @@ -47,7 +47,11 @@ func NewImage(repoName string, dockerClient DockerClient, ops ...imgutil.ImageOp baseIdentifier = baseImage.identifier store = baseImage.layerStore } else { - store = NewStore(dockerClient) + if options.Logger != nil { + store = NewStore(dockerClient, WithStoreLogger(options.Logger)) + } else { + store = NewStore(dockerClient) + } } cnbImage, err := imgutil.NewCNBImage(*options) diff --git a/local/options.go b/local/options.go index 82740066..4b9b0ebe 100644 --- a/local/options.go +++ b/local/options.go @@ -38,3 +38,15 @@ func WithMediaTypes(m imgutil.MediaTypes) func(*imgutil.ImageOptions) { func WithPreviousImage(name string) func(*imgutil.ImageOptions) { return imgutil.WithPreviousImage(name) } + +func WithLogger(logger imgutil.Logger) func(*imgutil.ImageOptions) { + return imgutil.WithLogger(logger) +} + +type StoreOption func(*Store) + +func WithStoreLogger(logger imgutil.Logger) StoreOption { + return func(s *Store) { + s.Logger = logger + } +} diff --git a/local/store.go b/local/store.go index 106d3a93..f1e110c5 100644 --- a/local/store.go +++ b/local/store.go @@ -34,6 +34,7 @@ type Store struct { // optional downloadOnce *sync.Once onDiskLayersByDiffID map[v1.Hash]annotatedLayer + Logger imgutil.Logger } // DockerClient is subset of client.CommonAPIClient required by this package. @@ -53,12 +54,18 @@ type annotatedLayer struct { uncompressedSize int64 } -func NewStore(dockerClient DockerClient) *Store { - return &Store{ +func NewStore(dockerClient DockerClient, ops ...StoreOption) *Store { + store := &Store{ dockerClient: dockerClient, downloadOnce: &sync.Once{}, onDiskLayersByDiffID: make(map[v1.Hash]annotatedLayer), + Logger: nil, } + for _, op := range ops { + op(store) + } + + return store } // images @@ -95,6 +102,9 @@ func (s *Store) Save(image *Image, withName string, withAdditionalNames ...strin inspect, err = s.doSave(image, withName) } if !canOmitBaseLayers || err != nil { + if s.Logger != nil && !canOmitBaseLayers { + s.Logger.Warn("Containerd is enabled, which will make saving your work more expensive.") + } if err = image.ensureLayers(); err != nil { return "", err }