From 0ca4af2d21eb567a6aa8018e18aaa1b8d5a943fc Mon Sep 17 00:00:00 2001 From: Aditya Rajan Date: Wed, 1 Sep 2021 12:44:58 +0530 Subject: [PATCH] remove-image: Add optional LookupManifest to RemoveImagesOptions. Following flag allows user to configure RemoveImages in a manner so that remove func becomes exclusive to removing manifests when needed and not removing underlying referenced images. Signed-off-by: Aditya Rajan --- libimage/manifest_list_test.go | 40 ++++++++++++++++++++++++++++++++++ libimage/runtime.go | 16 +++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/libimage/manifest_list_test.go b/libimage/manifest_list_test.go index 68779bf6a..9eb179892 100644 --- a/libimage/manifest_list_test.go +++ b/libimage/manifest_list_test.go @@ -75,3 +75,43 @@ func TestCreateAndTagManifestList(t *testing.T) { // Both origin list and newly tagged list should point to same image id require.Equal(t, image.ID(), taggedImage.ID()) } + +// Following test ensure that we test Removing a manifestList +// Test tags two manifestlist and deletes one of them and +// confirms if other one is not deleted. +func TestCreateAndRemoveManifestList(t *testing.T) { + + tagName := "manifestlisttagged" + listName := "manifestlist" + runtime, cleanup := testNewRuntime(t) + defer cleanup() + ctx := context.Background() + + list, err := runtime.CreateManifestList(listName) + require.NoError(t, err) + require.NotNil(t, list) + + manifestListOpts := &ManifestListAddOptions{All: true} + _, err = list.Add(ctx, "docker://busybox", manifestListOpts) + require.NoError(t, err) + + lookupOptions := &LookupImageOptions{ManifestList: true} + image, _, err := runtime.LookupImage(listName, lookupOptions) + require.NoError(t, err) + require.NotNil(t, image) + err = image.Tag(tagName) + require.NoError(t, err, "tag should have succeeded: %s", tagName) + + // Try deleting the manifestList with tag + rmReports, rmErrors := runtime.RemoveImages(ctx, []string{tagName}, &RemoveImagesOptions{Force: true, LookupManifest: true}) + require.Nil(t, rmErrors) + require.Equal(t, []string{"localhost/manifestlisttagged:latest"}, rmReports[0].Untagged) + + // Remove original listname as well + rmReports, rmErrors = runtime.RemoveImages(ctx, []string{listName}, &RemoveImagesOptions{Force: true, LookupManifest: true}) + require.Nil(t, rmErrors) + // output should contain log of untagging the original manifestlist + require.True(t, rmReports[0].Removed) + require.Equal(t, []string{"localhost/manifestlist:latest"}, rmReports[0].Untagged) + +} diff --git a/libimage/runtime.go b/libimage/runtime.go index 7d3fbf3f2..42461014d 100644 --- a/libimage/runtime.go +++ b/libimage/runtime.go @@ -541,6 +541,11 @@ type RemoveImagesOptions struct { // using a removed image. Use RemoveContainerFunc for a custom logic. // If set, all child images will be removed as well. Force bool + // LookupManifest will expect all specified names to be manifest lists (no instance look up). + // This allows for removing manifest lists. + // By default, RemoveImages will attempt to resolve to a manifest instance matching + // the local platform (i.e., os, architecture, variant). + LookupManifest bool // RemoveContainerFunc allows for a custom logic for removing // containers using a specific image. By default, all containers in // the local containers storage will be removed (if Force is set). @@ -600,13 +605,22 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem toDelete := []string{} // Look up images in the local containers storage and fill out // toDelete and the deleteMap. + switch { case len(names) > 0: + // prepare lookupOptions + var lookupOptions *LookupImageOptions + if options.LookupManifest { + // LookupManifest configured as true make sure we only remove manifests and no referenced images. + lookupOptions = &LookupImageOptions{lookupManifest: true} + } else { + lookupOptions = &LookupImageOptions{returnManifestIfNoInstance: true} + } // Look up the images one-by-one. That allows for removing // images that have been looked up successfully while reporting // lookup errors at the end. for _, name := range names { - img, resolvedName, err := r.LookupImage(name, &LookupImageOptions{returnManifestIfNoInstance: true}) + img, resolvedName, err := r.LookupImage(name, lookupOptions) if err != nil { appendError(err) continue