github.com/containers/podman/v4@v4.9.4/pkg/bindings/test/volumes_test.go (about) 1 package bindings_test 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "time" 8 9 "github.com/containers/podman/v4/pkg/bindings" 10 "github.com/containers/podman/v4/pkg/bindings/containers" 11 "github.com/containers/podman/v4/pkg/bindings/volumes" 12 "github.com/containers/podman/v4/pkg/domain/entities" 13 "github.com/containers/podman/v4/pkg/domain/entities/reports" 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("Podman volumes", func() { 20 var ( 21 bt *bindingTest 22 s *gexec.Session 23 connText context.Context 24 err error 25 ) 26 27 BeforeEach(func() { 28 bt = newBindingTest() 29 bt.RestoreImagesFromCache() 30 s = bt.startAPIService() 31 time.Sleep(1 * time.Second) 32 connText, err = bindings.NewConnection(context.Background(), bt.sock) 33 Expect(err).ToNot(HaveOccurred()) 34 }) 35 36 AfterEach(func() { 37 s.Kill() 38 bt.cleanup() 39 }) 40 41 It("create volume", func() { 42 // create a volume with blank config should work 43 _, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 44 Expect(err).ToNot(HaveOccurred()) 45 46 vcc := entities.VolumeCreateOptions{ 47 Name: "foobar", 48 Label: nil, 49 Options: nil, 50 } 51 vol, err := volumes.Create(connText, vcc, nil) 52 Expect(err).ToNot(HaveOccurred()) 53 Expect(vol.Name).To(Equal("foobar")) 54 55 // create volume with same name should 500 56 _, err = volumes.Create(connText, vcc, nil) 57 Expect(err).To(HaveOccurred()) 58 code, _ := bindings.CheckResponseCode(err) 59 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 60 }) 61 62 It("inspect volume", func() { 63 vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 64 Expect(err).ToNot(HaveOccurred()) 65 data, err := volumes.Inspect(connText, vol.Name, nil) 66 Expect(err).ToNot(HaveOccurred()) 67 Expect(data.Name).To(Equal(vol.Name)) 68 }) 69 70 It("remove volume", func() { 71 // removing a bogus volume should result in 404 72 err := volumes.Remove(connText, "foobar", nil) 73 code, err := bindings.CheckResponseCode(err) 74 Expect(err).ToNot(HaveOccurred()) 75 Expect(code).To(BeNumerically("==", http.StatusNotFound)) 76 77 // Removing an unused volume should work 78 vol, err := volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 79 Expect(err).ToNot(HaveOccurred()) 80 err = volumes.Remove(connText, vol.Name, nil) 81 Expect(err).ToNot(HaveOccurred()) 82 83 // Removing a volume that is being used without force should be 409 84 vol, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 85 Expect(err).ToNot(HaveOccurred()) 86 session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/foobar", vol.Name), "--name", "vtest", alpine.name, "top"}) 87 session.Wait(45) 88 Expect(session.ExitCode()).To(BeZero()) 89 90 err = volumes.Remove(connText, vol.Name, nil) 91 Expect(err).To(HaveOccurred()) 92 code, err = bindings.CheckResponseCode(err) 93 Expect(err).ToNot(HaveOccurred()) 94 Expect(code).To(BeNumerically("==", http.StatusConflict)) 95 96 // Removing with a volume in use with force should work with a stopped container 97 err = containers.Stop(connText, "vtest", new(containers.StopOptions).WithTimeout(0)) 98 Expect(err).ToNot(HaveOccurred()) 99 options := new(volumes.RemoveOptions).WithForce(true) 100 err = volumes.Remove(connText, vol.Name, options) 101 Expect(err).ToNot(HaveOccurred()) 102 }) 103 104 It("list volumes", func() { 105 // no volumes should be ok 106 vols, err := volumes.List(connText, nil) 107 Expect(err).ToNot(HaveOccurred()) 108 Expect(vols).To(BeEmpty()) 109 110 // create a bunch of named volumes and make verify with list 111 volNames := []string{"homer", "bart", "lisa", "maggie", "marge"} 112 for i := 0; i < 5; i++ { 113 _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: volNames[i]}, nil) 114 Expect(err).ToNot(HaveOccurred()) 115 } 116 vols, err = volumes.List(connText, nil) 117 Expect(err).ToNot(HaveOccurred()) 118 Expect(vols).To(HaveLen(5)) 119 for _, v := range vols { 120 Expect(StringInSlice(v.Name, volNames)).To(BeTrue()) 121 } 122 123 // list with bad filter should be 500 124 filters := make(map[string][]string) 125 filters["foobar"] = []string{"1234"} 126 options := new(volumes.ListOptions).WithFilters(filters) 127 _, err = volumes.List(connText, options) 128 Expect(err).To(HaveOccurred()) 129 code, _ := bindings.CheckResponseCode(err) 130 Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) 131 132 filters = make(map[string][]string) 133 filters["name"] = []string{"homer"} 134 options = new(volumes.ListOptions).WithFilters(filters) 135 vols, err = volumes.List(connText, options) 136 Expect(err).ToNot(HaveOccurred()) 137 Expect(vols).To(HaveLen(1)) 138 Expect(vols[0].Name).To(Equal("homer")) 139 }) 140 141 It("prune unused volume", func() { 142 // Pruning when no volumes present should be ok 143 _, err := volumes.Prune(connText, nil) 144 Expect(err).ToNot(HaveOccurred()) 145 146 // Removing an unused volume should work 147 _, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 148 Expect(err).ToNot(HaveOccurred()) 149 vols, err := volumes.Prune(connText, nil) 150 Expect(err).ToNot(HaveOccurred()) 151 Expect(vols).To(HaveLen(1)) 152 153 _, err = volumes.Create(connText, entities.VolumeCreateOptions{Name: "homer"}, nil) 154 Expect(err).ToNot(HaveOccurred()) 155 _, err = volumes.Create(connText, entities.VolumeCreateOptions{}, nil) 156 Expect(err).ToNot(HaveOccurred()) 157 session := bt.runPodman([]string{"run", "-dt", "-v", fmt.Sprintf("%s:/homer", "homer"), "--name", "vtest", alpine.name, "top"}) 158 session.Wait(45) 159 vols, err = volumes.Prune(connText, nil) 160 Expect(err).ToNot(HaveOccurred()) 161 Expect(reports.PruneReportsIds(vols)).To(HaveLen(1)) 162 _, err = volumes.Inspect(connText, "homer", nil) 163 Expect(err).ToNot(HaveOccurred()) 164 165 // Removing volume with non matching filter shouldn't prune any volumes 166 filters := make(map[string][]string) 167 filters["label"] = []string{"label1=idontmatch"} 168 _, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ 169 "label1": "value1", 170 }}, nil) 171 Expect(err).ToNot(HaveOccurred()) 172 options := new(volumes.PruneOptions).WithFilters(filters) 173 vols, err = volumes.Prune(connText, options) 174 Expect(err).ToNot(HaveOccurred()) 175 Expect(vols).To(BeEmpty()) 176 vol2, err := volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ 177 "label1": "value2", 178 }}, nil) 179 Expect(err).ToNot(HaveOccurred()) 180 _, err = volumes.Create(connText, entities.VolumeCreateOptions{Label: map[string]string{ 181 "label1": "value3", 182 }}, nil) 183 Expect(err).ToNot(HaveOccurred()) 184 185 // Removing volume with matching filter label and value should remove specific entry 186 filters = make(map[string][]string) 187 filters["label"] = []string{"label1=value2"} 188 options = new(volumes.PruneOptions).WithFilters(filters) 189 vols, err = volumes.Prune(connText, options) 190 Expect(err).ToNot(HaveOccurred()) 191 Expect(vols).To(HaveLen(1)) 192 Expect(vols[0].Id).To(Equal(vol2.Name)) 193 194 // Removing volumes with matching filter label should remove all matching volumes 195 filters = make(map[string][]string) 196 filters["label"] = []string{"label1"} 197 options = new(volumes.PruneOptions).WithFilters(filters) 198 vols, err = volumes.Prune(connText, options) 199 Expect(err).ToNot(HaveOccurred()) 200 Expect(vols).To(HaveLen(2)) 201 }) 202 203 })