github.com/containers/podman/v4@v4.9.4/test/e2e/rmi_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	. "github.com/containers/podman/v4/test/utils"
     8  	. "github.com/onsi/ginkgo/v2"
     9  	. "github.com/onsi/gomega"
    10  	. "github.com/onsi/gomega/gexec"
    11  )
    12  
    13  var _ = Describe("Podman rmi", func() {
    14  
    15  	It("podman rmi bogus image", func() {
    16  		session := podmanTest.Podman([]string{"rmi", "debian:6.0.10"})
    17  		session.WaitWithDefaultTimeout()
    18  		Expect(session).Should(Exit(1))
    19  
    20  	})
    21  
    22  	It("podman rmi with fq name", func() {
    23  		podmanTest.AddImageToRWStore(ALPINE)
    24  		session := podmanTest.Podman([]string{"rmi", ALPINE})
    25  		session.WaitWithDefaultTimeout()
    26  		Expect(session).Should(ExitCleanly())
    27  
    28  	})
    29  
    30  	It("podman rmi with short name", func() {
    31  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
    32  		session := podmanTest.Podman([]string{"rmi", "cirros"})
    33  		session.WaitWithDefaultTimeout()
    34  		Expect(session).Should(ExitCleanly())
    35  
    36  	})
    37  
    38  	It("podman rmi all images", func() {
    39  		podmanTest.AddImageToRWStore(NGINX_IMAGE)
    40  		session := podmanTest.Podman([]string{"rmi", "-a"})
    41  		session.WaitWithDefaultTimeout()
    42  		images := podmanTest.Podman([]string{"images"})
    43  		images.WaitWithDefaultTimeout()
    44  		Expect(session).Should(ExitCleanly())
    45  
    46  	})
    47  
    48  	It("podman rmi all images forcibly with short options", func() {
    49  		podmanTest.AddImageToRWStore(NGINX_IMAGE)
    50  		session := podmanTest.Podman([]string{"rmi", "-fa"})
    51  		session.WaitWithDefaultTimeout()
    52  		Expect(session).Should(ExitCleanly())
    53  
    54  	})
    55  
    56  	It("podman rmi tagged image", func() {
    57  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
    58  		setup := podmanTest.Podman([]string{"images", "-q", CIRROS_IMAGE})
    59  		setup.WaitWithDefaultTimeout()
    60  		Expect(setup).Should(ExitCleanly())
    61  
    62  		session := podmanTest.Podman([]string{"tag", CIRROS_IMAGE, "foo:bar", "foo"})
    63  		session.WaitWithDefaultTimeout()
    64  		Expect(session).Should(ExitCleanly())
    65  
    66  		result := podmanTest.Podman([]string{"images", "-q", "foo"})
    67  		result.WaitWithDefaultTimeout()
    68  		Expect(result).Should(ExitCleanly())
    69  
    70  		Expect(result.OutputToString()).To(ContainSubstring(setup.OutputToString()))
    71  	})
    72  
    73  	It("podman rmi image with tags by ID cannot be done without force", func() {
    74  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
    75  		setup := podmanTest.Podman([]string{"images", "-q", CIRROS_IMAGE})
    76  		setup.WaitWithDefaultTimeout()
    77  		Expect(setup).Should(ExitCleanly())
    78  		cirrosID := setup.OutputToString()
    79  
    80  		session := podmanTest.Podman([]string{"tag", "cirros", "foo:bar", "foo"})
    81  		session.WaitWithDefaultTimeout()
    82  		Expect(session).Should(ExitCleanly())
    83  
    84  		// Trying without --force should fail
    85  		result := podmanTest.Podman([]string{"rmi", cirrosID})
    86  		result.WaitWithDefaultTimeout()
    87  		Expect(result).To(ExitWithError())
    88  
    89  		// With --force it should work
    90  		resultForce := podmanTest.Podman([]string{"rmi", "-f", cirrosID})
    91  		resultForce.WaitWithDefaultTimeout()
    92  		Expect(resultForce).Should(ExitCleanly())
    93  	})
    94  
    95  	It("podman rmi image that is a parent of another image", func() {
    96  		Skip("I need help with this one. i don't understand what is going on")
    97  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
    98  		session := podmanTest.Podman([]string{"run", "--name", "c_test", CIRROS_IMAGE, "true"})
    99  		session.WaitWithDefaultTimeout()
   100  		Expect(session).Should(ExitCleanly())
   101  
   102  		session = podmanTest.Podman([]string{"commit", "-q", "c_test", "test"})
   103  		session.WaitWithDefaultTimeout()
   104  		Expect(session).Should(ExitCleanly())
   105  
   106  		session = podmanTest.Podman([]string{"rm", "c_test"})
   107  		session.WaitWithDefaultTimeout()
   108  		Expect(session).Should(ExitCleanly())
   109  
   110  		session = podmanTest.Podman([]string{"rmi", CIRROS_IMAGE})
   111  		session.WaitWithDefaultTimeout()
   112  		Expect(session).Should(ExitCleanly())
   113  
   114  		session = podmanTest.Podman([]string{"images", "-q"})
   115  		session.WaitWithDefaultTimeout()
   116  		Expect(session).Should(ExitCleanly())
   117  		Expect(session.OutputToStringArray()).To(HaveLen(12))
   118  
   119  		session = podmanTest.Podman([]string{"images", "--sort", "created", "--format", "{{.Id}}", "--all"})
   120  		session.WaitWithDefaultTimeout()
   121  		Expect(session).Should(ExitCleanly())
   122  		Expect(session.OutputToStringArray()).To(HaveLen(13),
   123  			"Output from 'podman images -q -a'")
   124  		untaggedImg := session.OutputToStringArray()[1]
   125  
   126  		session = podmanTest.Podman([]string{"rmi", "-f", untaggedImg})
   127  		session.WaitWithDefaultTimeout()
   128  		Expect(session).Should(Exit(2), "UntaggedImg is '%s'", untaggedImg)
   129  	})
   130  
   131  	It("podman rmi image that is created from another named imaged", func() {
   132  		podmanTest.AddImageToRWStore(ALPINE)
   133  		session := podmanTest.Podman([]string{"create", "--name", "c_test1", ALPINE, "true"})
   134  		session.WaitWithDefaultTimeout()
   135  		Expect(session).Should(ExitCleanly())
   136  
   137  		session = podmanTest.Podman([]string{"commit", "-q", "c_test1", "test1"})
   138  		session.WaitWithDefaultTimeout()
   139  		Expect(session).Should(ExitCleanly())
   140  
   141  		session = podmanTest.Podman([]string{"create", "--name", "c_test2", "test1", "true"})
   142  		session.WaitWithDefaultTimeout()
   143  		Expect(session).Should(ExitCleanly())
   144  
   145  		session = podmanTest.Podman([]string{"commit", "-q", "c_test2", "test2"})
   146  		session.WaitWithDefaultTimeout()
   147  		Expect(session).Should(ExitCleanly())
   148  
   149  		session = podmanTest.Podman([]string{"rm", "-a"})
   150  		session.WaitWithDefaultTimeout()
   151  		Expect(session).Should(ExitCleanly())
   152  
   153  		session = podmanTest.Podman([]string{"rmi", "test2"})
   154  		session.WaitWithDefaultTimeout()
   155  		Expect(session).Should(ExitCleanly())
   156  
   157  		session = podmanTest.Podman([]string{"images", "-q"})
   158  		session.WaitWithDefaultTimeout()
   159  		Expect(session).Should(ExitCleanly())
   160  		Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 1))
   161  	})
   162  
   163  	It("podman rmi with cached images", func() {
   164  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
   165  		dockerfile := fmt.Sprintf(`FROM %s
   166  		RUN mkdir hello
   167  		RUN touch test.txt
   168  		ENV foo=bar
   169  		`, CIRROS_IMAGE)
   170  		podmanTest.BuildImage(dockerfile, "test", "true")
   171  
   172  		dockerfile = fmt.Sprintf(`FROM %s
   173  		RUN mkdir hello
   174  		RUN touch test.txt
   175  		RUN mkdir blah
   176  		ENV foo=bar
   177  		`, CIRROS_IMAGE)
   178  
   179  		podmanTest.BuildImage(dockerfile, "test2", "true")
   180  
   181  		session := podmanTest.Podman([]string{"images", "-q", "-a"})
   182  		session.WaitWithDefaultTimeout()
   183  		Expect(session).Should(ExitCleanly())
   184  		numOfImages := len(session.OutputToStringArray())
   185  
   186  		session = podmanTest.Podman([]string{"rmi", "test2"})
   187  		session.WaitWithDefaultTimeout()
   188  		Expect(session).Should(ExitCleanly())
   189  
   190  		session = podmanTest.Podman([]string{"images", "-q", "-a"})
   191  		session.WaitWithDefaultTimeout()
   192  		Expect(session).Should(ExitCleanly())
   193  		Expect(numOfImages - len(session.OutputToStringArray())).To(Equal(2))
   194  
   195  		session = podmanTest.Podman([]string{"rmi", "test"})
   196  		session.WaitWithDefaultTimeout()
   197  		Expect(session).Should(ExitCleanly())
   198  
   199  		session = podmanTest.Podman([]string{"images", "-q", "-a"})
   200  		session.WaitWithDefaultTimeout()
   201  		Expect(session).Should(ExitCleanly())
   202  		Expect(session.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES) + 1))
   203  
   204  		podmanTest.BuildImage(dockerfile, "test3", "true")
   205  
   206  		session = podmanTest.Podman([]string{"rmi", CIRROS_IMAGE})
   207  		session.WaitWithDefaultTimeout()
   208  		Expect(session).Should(ExitCleanly())
   209  
   210  		session = podmanTest.Podman([]string{"rmi", "test3"})
   211  		session.WaitWithDefaultTimeout()
   212  		Expect(session).Should(ExitCleanly())
   213  
   214  		session = podmanTest.Podman([]string{"images", "-q", "-a"})
   215  		session.WaitWithDefaultTimeout()
   216  		Expect(session).Should(ExitCleanly())
   217  		Expect(session.OutputToString()).To(HaveLen(142))
   218  	})
   219  
   220  	It("podman rmi -a with no images should be exit 0", func() {
   221  		session := podmanTest.Podman([]string{"rmi", "-fa"})
   222  		session.WaitWithDefaultTimeout()
   223  		Expect(session).Should(ExitCleanly())
   224  
   225  		session2 := podmanTest.Podman([]string{"rmi", "-fa"})
   226  		session2.WaitWithDefaultTimeout()
   227  		Expect(session2).Should(ExitCleanly())
   228  	})
   229  
   230  	It("podman rmi -a with parent|child images", func() {
   231  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
   232  		dockerfile := fmt.Sprintf(`FROM %s AS base
   233  RUN touch /1
   234  ENV LOCAL=/1
   235  RUN find $LOCAL
   236  FROM base
   237  RUN find $LOCAL
   238  
   239  `, CIRROS_IMAGE)
   240  		podmanTest.BuildImage(dockerfile, "test", "true")
   241  		session := podmanTest.Podman([]string{"rmi", "-a"})
   242  		session.WaitWithDefaultTimeout()
   243  		Expect(session).Should(ExitCleanly())
   244  
   245  		images := podmanTest.Podman([]string{"images", "-aq"})
   246  		images.WaitWithDefaultTimeout()
   247  		Expect(images).Should(ExitCleanly())
   248  		Expect(images.OutputToStringArray()).To(HaveLen(len(CACHE_IMAGES)))
   249  	})
   250  
   251  	// Don't rerun all tests; just assume that if we get that diagnostic,
   252  	// we're getting rmi
   253  	It("podman image rm is the same as rmi", func() {
   254  		session := podmanTest.Podman([]string{"image", "rm"})
   255  		session.WaitWithDefaultTimeout()
   256  		Expect(session).Should(Exit(125))
   257  		Expect(session.ErrorToString()).To(ContainSubstring("image name or ID must be specified"))
   258  	})
   259  
   260  	It("podman image rm - concurrent with shared layers", func() {
   261  		// #6510 has shown a fairly simple reproducer to force storage
   262  		// errors during parallel image removal.  Since it's subject to
   263  		// a race, we may not hit the condition a 100 percent of times
   264  		// but ocal reproducers hit it all the time.
   265  
   266  		podmanTest.AddImageToRWStore(CIRROS_IMAGE)
   267  		var wg sync.WaitGroup
   268  
   269  		// Prepare images
   270  		wg.Add(10)
   271  		for i := 0; i < 10; i++ {
   272  			go func(i int) {
   273  				defer GinkgoRecover()
   274  				defer wg.Done()
   275  				imageName := fmt.Sprintf("rmtest:%d", i)
   276  				containerfile := fmt.Sprintf(`FROM %s
   277  	RUN touch %s`, CIRROS_IMAGE, imageName)
   278  
   279  				podmanTest.BuildImage(containerfile, imageName, "false")
   280  			}(i)
   281  		}
   282  		wg.Wait()
   283  
   284  		// A herd of concurrent removals
   285  		wg.Add(10)
   286  		for i := 0; i < 10; i++ {
   287  			go func(i int) {
   288  				defer GinkgoRecover()
   289  				defer wg.Done()
   290  
   291  				imageName := fmt.Sprintf("rmtest:%d", i)
   292  				session := podmanTest.Podman([]string{"rmi", "-f", imageName})
   293  				session.WaitWithDefaultTimeout()
   294  				Expect(session).Should(ExitCleanly())
   295  			}(i)
   296  		}
   297  		wg.Wait()
   298  	})
   299  
   300  	It("podman rmi --no-prune with dangling parents", func() {
   301  		podmanTest.AddImageToRWStore(ALPINE)
   302  		session := podmanTest.Podman([]string{"create", "--name", "c_test1", ALPINE, "true"})
   303  		session.WaitWithDefaultTimeout()
   304  		Expect(session).Should(ExitCleanly())
   305  
   306  		session = podmanTest.Podman([]string{"commit", "-q", "c_test1", "test1"})
   307  		session.WaitWithDefaultTimeout()
   308  		Expect(session).Should(ExitCleanly())
   309  
   310  		session = podmanTest.Podman([]string{"create", "--name", "c_test2", "test1", "true"})
   311  		session.WaitWithDefaultTimeout()
   312  		Expect(session).Should(ExitCleanly())
   313  
   314  		session = podmanTest.Podman([]string{"commit", "-q", "c_test2", "test2"})
   315  		session.WaitWithDefaultTimeout()
   316  		Expect(session).Should(ExitCleanly())
   317  		imageID2 := session.OutputToString()
   318  
   319  		session = podmanTest.Podman([]string{"create", "--name", "c_test3", "test2", "true"})
   320  		session.WaitWithDefaultTimeout()
   321  		Expect(session).Should(ExitCleanly())
   322  
   323  		session = podmanTest.Podman([]string{"commit", "-q", "c_test3", "test3"})
   324  		session.WaitWithDefaultTimeout()
   325  		Expect(session).Should(ExitCleanly())
   326  		imageID3 := session.OutputToString()
   327  
   328  		session = podmanTest.Podman([]string{"untag", "test2"})
   329  		session.WaitWithDefaultTimeout()
   330  		Expect(session).Should(ExitCleanly())
   331  
   332  		session = podmanTest.Podman([]string{"untag", "test1"})
   333  		session.WaitWithDefaultTimeout()
   334  		Expect(session).Should(ExitCleanly())
   335  
   336  		session = podmanTest.Podman([]string{"rmi", "-f", "--no-prune", "test3"})
   337  		session.WaitWithDefaultTimeout()
   338  		Expect(session).Should(ExitCleanly())
   339  		Expect(session.OutputToString()).To(ContainSubstring(imageID3))
   340  		Expect(session.OutputToString()).NotTo(ContainSubstring(imageID2))
   341  	})
   342  
   343  	It("podman rmi --no-prune with undangling parents", func() {
   344  		podmanTest.AddImageToRWStore(ALPINE)
   345  		session := podmanTest.Podman([]string{"create", "--name", "c_test1", ALPINE, "true"})
   346  		session.WaitWithDefaultTimeout()
   347  		Expect(session).Should(ExitCleanly())
   348  
   349  		session = podmanTest.Podman([]string{"commit", "-q", "c_test1", "test1"})
   350  		session.WaitWithDefaultTimeout()
   351  		Expect(session).Should(ExitCleanly())
   352  
   353  		session = podmanTest.Podman([]string{"create", "--name", "c_test2", "test1", "true"})
   354  		session.WaitWithDefaultTimeout()
   355  		Expect(session).Should(ExitCleanly())
   356  
   357  		session = podmanTest.Podman([]string{"commit", "-q", "c_test2", "test2"})
   358  		session.WaitWithDefaultTimeout()
   359  		Expect(session).Should(ExitCleanly())
   360  		imageID2 := session.OutputToString()
   361  
   362  		session = podmanTest.Podman([]string{"create", "--name", "c_test3", "test2", "true"})
   363  		session.WaitWithDefaultTimeout()
   364  		Expect(session).Should(ExitCleanly())
   365  
   366  		session = podmanTest.Podman([]string{"commit", "-q", "c_test3", "test3"})
   367  		session.WaitWithDefaultTimeout()
   368  		Expect(session).Should(ExitCleanly())
   369  		imageID3 := session.OutputToString()
   370  
   371  		session = podmanTest.Podman([]string{"rmi", "-f", "--no-prune", "test3"})
   372  		session.WaitWithDefaultTimeout()
   373  		Expect(session).Should(ExitCleanly())
   374  		Expect(session.OutputToString()).To(ContainSubstring(imageID3))
   375  		Expect(session.OutputToString()).NotTo(ContainSubstring(imageID2))
   376  	})
   377  })