1717package image
1818
1919import (
20+ "encoding/json"
2021 "errors"
2122 "fmt"
2223 "net/http"
@@ -33,6 +34,11 @@ import (
3334 "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/registry"
3435)
3536
37+ type registryTagList struct {
38+ Name string `json:"name"`
39+ Tags []string `json:"tags"`
40+ }
41+
3642func TestPush (t * testing.T ) {
3743 nerdtest .Setup ()
3844
@@ -145,6 +151,79 @@ func TestPush(t *testing.T) {
145151 },
146152 Expected : test .Expects (0 , nil , nil ),
147153 },
154+ {
155+ Description : "all-tags pushes all tags for a repository" ,
156+ Require : require .Not (nerdtest .Docker ),
157+ Setup : func (data test.Data , helpers test.Helpers ) {
158+ helpers .Ensure ("pull" , "--quiet" , testutil .CommonImage )
159+
160+ repo := fmt .Sprintf ("%s:%d/%s" ,
161+ registryNoAuthHTTPRandom .IP .String (), registryNoAuthHTTPRandom .Port , data .Identifier ())
162+ data .Labels ().Set ("testImageRepo" , repo )
163+
164+ tag1 := repo + ":v1"
165+ tag2 := repo + ":v2"
166+ data .Labels ().Set ("testImageRefV1" , tag1 )
167+ data .Labels ().Set ("testImageRefV2" , tag2 )
168+
169+ helpers .Ensure ("tag" , testutil .CommonImage , tag1 )
170+ helpers .Ensure ("tag" , testutil .CommonImage , tag2 )
171+ },
172+ Cleanup : func (data test.Data , helpers test.Helpers ) {
173+ if v := data .Labels ().Get ("testImageRefV1" ); v != "" {
174+ helpers .Anyhow ("rmi" , "-f" , v )
175+ }
176+ if v := data .Labels ().Get ("testImageRefV2" ); v != "" {
177+ helpers .Anyhow ("rmi" , "-f" , v )
178+ }
179+ },
180+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
181+ return helpers .Command (
182+ "push" ,
183+ "--insecure-registry" ,
184+ "--all-tags" ,
185+ data .Labels ().Get ("testImageRepo" ),
186+ )
187+ },
188+ Expected : func (data test.Data , helpers test.Helpers ) * test.Expected {
189+ return & test.Expected {
190+ ExitCode : 0 ,
191+ Output : func (stdout string , t tig.T ) {
192+ tagsURL := fmt .Sprintf ("http://%s:%d/v2/%s/tags/list" ,
193+ registryNoAuthHTTPRandom .IP .String (),
194+ registryNoAuthHTTPRandom .Port ,
195+ data .Identifier (),
196+ )
197+ resp , err := http .Get (tagsURL )
198+ assert .NilError (t , err , "error making HTTP request for tag list" )
199+ defer func () {
200+ if resp .Body != nil {
201+ _ = resp .Body .Close ()
202+ }
203+ }()
204+
205+ assert .Equal (t , resp .StatusCode , http .StatusOK , "expected tag list endpoint to be available" )
206+
207+ var tl registryTagList
208+ err = json .NewDecoder (resp .Body ).Decode (& tl )
209+ assert .NilError (t , err , "failed to decode tag list JSON" )
210+
211+ foundV1 := false
212+ foundV2 := false
213+ for _ , tag := range tl .Tags {
214+ if tag == "v1" {
215+ foundV1 = true
216+ }
217+ if tag == "v2" {
218+ foundV2 = true
219+ }
220+ }
221+ assert .Assert (t , foundV1 , "expected tag v1 to be pushed" )
222+ assert .Assert (t , foundV2 , "expected tag v2 to be pushed" )
223+ },
224+ }
225+ },
226+ },
148227 {
149228 Description : "with insecure, with login" ,
150229 Require : require .Not (nerdtest .Docker ),
@@ -278,6 +357,81 @@ func TestPush(t *testing.T) {
278357 },
279358 Expected : test .Expects (0 , nil , nil ),
280359 },
360+ {
361+ Description : "soci with all-tags pushes multiple tags without duplicate index failure" ,
362+ Require : require .All (
363+ nerdtest .Soci ,
364+ require .Not (nerdtest .Docker ),
365+ ),
366+ Setup : func (data test.Data , helpers test.Helpers ) {
367+ helpers .Ensure ("pull" , "--quiet" , testutil .UbuntuImage )
368+
369+ repo := fmt .Sprintf ("%s:%d/%s" ,
370+ registryNoAuthHTTPRandom .IP .String (), registryNoAuthHTTPRandom .Port , data .Identifier ())
371+ data .Labels ().Set ("testImageRepo" , repo )
372+
373+ tag1 := repo + ":image_tag"
374+ tag2 := repo + ":latest"
375+ data .Labels ().Set ("testImageRef1" , tag1 )
376+ data .Labels ().Set ("testImageRef2" , tag2 )
377+
378+ helpers .Ensure ("tag" , testutil .UbuntuImage , tag1 )
379+ helpers .Ensure ("tag" , testutil .UbuntuImage , tag2 )
380+ },
381+ Cleanup : func (data test.Data , helpers test.Helpers ) {
382+ if v := data .Labels ().Get ("testImageRef1" ); v != "" {
383+ helpers .Anyhow ("rmi" , "-f" , v )
384+ }
385+ if v := data .Labels ().Get ("testImageRef2" ); v != "" {
386+ helpers .Anyhow ("rmi" , "-f" , v )
387+ }
388+ },
389+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
390+ return helpers .Command (
391+ "push" ,
392+ "--snapshotter=soci" ,
393+ "--insecure-registry" ,
394+ "--all-tags" ,
395+ "--soci-span-size=2097152" ,
396+ "--soci-min-layer-size=0" ,
397+ data .Labels ().Get ("testImageRepo" ),
398+ )
399+ },
400+ Expected : test .Expects (0 , nil , nil ),
401+ },
402+ {
403+ Description : "all-tags with explicit tag returns error" ,
404+ Require : require .Not (nerdtest .Docker ),
405+ Setup : func (data test.Data , helpers test.Helpers ) {
406+ helpers .Ensure ("pull" , "--quiet" , testutil .CommonImage )
407+ testImageRef := fmt .Sprintf ("%s:%d/%s:v1" ,
408+ registryNoAuthHTTPRandom .IP .String (),
409+ registryNoAuthHTTPRandom .Port ,
410+ data .Identifier (),
411+ )
412+ data .Labels ().Set ("testImageRef" , testImageRef )
413+
414+ helpers .Ensure ("tag" , testutil .CommonImage , testImageRef )
415+ },
416+ Cleanup : func (data test.Data , helpers test.Helpers ) {
417+ if ref := data .Labels ().Get ("testImageRef" ); ref != "" {
418+ helpers .Anyhow ("rmi" , "-f" , ref )
419+ }
420+ },
421+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
422+ return helpers .Command (
423+ "push" ,
424+ "--insecure-registry" ,
425+ "--all-tags" ,
426+ data .Labels ().Get ("testImageRef" ),
427+ )
428+ },
429+ Expected : test .Expects (
430+ 1 ,
431+ []error {errors .New ("tag can't be used with --all-tags/-a" )},
432+ nil ,
433+ ),
434+ },
281435 },
282436 }
283437 testCase .Run (t )
0 commit comments