@@ -179,6 +179,39 @@ func runPushTest(containerManager container.ContainerManagerType, imageName, mod
179179 validateContainerBuild (tests .DockerBuildName , buildNumber , imagePath , module , 7 , 5 , 7 , t )
180180}
181181
182+ func loginToArtifactory (t * testing.T , container * tests.TestContainer ) {
183+ password := * tests .JfrogPassword
184+ user := * tests .JfrogUser
185+ if * tests .JfrogAccessToken != "" {
186+ user = auth .ExtractUsernameFromAccessToken (* tests .JfrogAccessToken )
187+ password = * tests .JfrogAccessToken
188+ }
189+ assert .NoError (t , container .Exec (
190+ context .Background (),
191+ "docker" ,
192+ "login" ,
193+ tests .RtContainerHostName ,
194+ "--username=" + user ,
195+ "--password=" + password ,
196+ ))
197+ }
198+
199+ func buildBuilderImage (t * testing.T , workspace , dockerfile , containerName string ) * tests.TestContainer {
200+ ctx := context .Background ()
201+ testContainer , err := tests .NewContainerRequest ().
202+ SetDockerfile (workspace , dockerfile , nil ).
203+ Privileged ().
204+ Networks (rtNetwork ).
205+ Name (containerName ).
206+ Mount (mount.Mount {Type : mount .TypeBind , Source : workspace , Target : "/workspace" , ReadOnly : false }).
207+ Cmd ("--insecure-registry" , tests .RtContainerHostName ).
208+ WaitFor (wait .ForLog ("API listen on /var/run/docker.sock" ).WithStartupTimeout (5 * time .Minute )).
209+ Remove ().
210+ Build (ctx , true )
211+ assert .NoError (t , err , "Couldn't create builder image." )
212+ return testContainer
213+ }
214+
182215// This test validate the collect build-info flow for fat-manifest images.
183216// The way we build the fat manifest and push it to Artifactory is not important.
184217// Therefore, this test runs only with docker.
@@ -194,53 +227,30 @@ func TestPushFatManifestImage(t *testing.T) {
194227 assert .NoError (t , fileutils .CreateDirIfNotExist (workspace ))
195228 testDataDir := filepath .Join (filepath .FromSlash (tests .GetTestResourcesPath ()), "docker" )
196229 files , err := os .ReadDir (testDataDir )
197-
198230 assert .NoError (t , err )
199231 for _ , file := range files {
200232 if ! file .IsDir () {
201233 _ , err := tests .ReplaceTemplateVariables (filepath .Join (testDataDir , file .Name ()), tests .Out )
202234 assert .NoError (t , err )
203235 }
204236 }
237+
205238 // Build the builder image locally.
206- ctx := context .Background ()
207- testContainer , err := tests .NewContainerRequest ().
208- SetDockerfile (workspace , "Dockerfile.Buildx.Fatmanifest" , nil ).
209- Privileged ().
210- Networks (rtNetwork ).
211- Name ("buildx_container" ).
212- Mount (mount.Mount {Type : mount .TypeBind , Source : workspace , Target : "/workspace" , ReadOnly : false }).
213- Cmd ("--insecure-registry" , tests .RtContainerHostName ).
214- // Docker daemon take times to load. In order to check if it's available we wait for a log message to indications that the Docker daemon has finished initializing.
215- WaitFor (wait .ForLog ("API listen on /var/run/docker.sock" ).WithStartupTimeout (5 * time .Minute )).
216- Remove ().
217- Build (ctx , true )
218- assert .NoError (t , err , "Couldn't run create buildx image." )
219- defer func () { assert .NoError (t , testContainer .Terminate (ctx )) }()
239+ testContainer := buildBuilderImage (t , workspace , "Dockerfile.Buildx.Fatmanifest" , "buildx_container" )
240+ defer func () { assert .NoError (t , testContainer .Terminate (context .Background ())) }()
220241
221242 // Enable the builder util in the container.
222- err = testContainer .Exec (ctx , "sh" , "script.sh" )
243+ err = testContainer .Exec (context . Background () , "sh" , "script.sh" )
223244 assert .NoError (t , err )
224245
225- // login from the builder container toward the Artifactory.
226- password := * tests .JfrogPassword
227- user := * tests .JfrogUser
228- if * tests .JfrogAccessToken != "" {
229- user = auth .ExtractUsernameFromAccessToken (* tests .JfrogAccessToken )
230- password = * tests .JfrogAccessToken
231- }
232- assert .NoError (t , testContainer .Exec (
233- ctx ,
234- "docker" ,
235- "login" ,
236- tests .RtContainerHostName ,
237- "--username=" + user ,
238- "--password=" + password ))
246+ // Login to Artifactory
247+ loginToArtifactory (t , testContainer )
248+
239249 buildxOutputFile := "buildmetadata"
240250
241- // Run the builder in the container and push the fat-manifest image to artifactory
251+ // Run the builder in the container and push the fat-manifest image to Artifactory
242252 assert .NoError (t , testContainer .Exec (
243- ctx ,
253+ context . Background () ,
244254 "docker" ,
245255 "buildx" ,
246256 "build" ,
@@ -263,20 +273,83 @@ func TestPushFatManifestImage(t *testing.T) {
263273 assert .NoError (t , artifactoryCli .Exec ("build-docker-create" , tests .DockerLocalRepo , "--image-file=" + buildxOutput , "--build-name=" + buildName , "--build-number=" + buildNumber ))
264274 assert .NoError (t , artifactoryCli .Exec ("build-publish" , buildName , buildNumber ))
265275
266- // Validate the published build-info exits
276+ // Validate the published build-info exists
267277 publishedBuildInfo , found , err := tests .GetBuildInfo (serverDetails , buildName , buildNumber )
268- if err != nil {
269- assert .NoError (t , err )
270- return
278+ assert .NoError (t , err )
279+ assert .True (t , found , "build info was expected to be found" )
280+ assert .True (t , len (publishedBuildInfo .BuildInfo .Modules ) > 1 )
281+
282+ // Validate build-name & build-number properties in all image layers
283+ searchSpec := spec .NewBuilder ().Pattern (tests .DockerLocalRepo + "/*" ).Build (buildName ).Recursive (true ).BuildSpec ()
284+ searchCmd := generic .NewSearchCommand ()
285+ searchCmd .SetServerDetails (serverDetails ).SetSpec (searchSpec )
286+ reader , err := searchCmd .Search ()
287+ assert .NoError (t , err )
288+ totalResults , err := reader .Length ()
289+ assert .NoError (t , err )
290+ assert .True (t , totalResults > 1 )
291+ }
292+
293+ func TestPushMultiTaggedImage (t * testing.T ) {
294+ if ! * tests .TestDocker {
295+ t .Skip ("Skipping test. To run it, add the '-test.docker=true' option." )
271296 }
272- if ! found {
273- assert .True (t , found , "build info was expected to be found" )
274- return
297+
298+ buildName := "push-multi-tagged" + tests .DockerBuildName
299+ buildNumber := "1"
300+
301+ // Setup workspace
302+ workspace , err := filepath .Abs (tests .Out )
303+ assert .NoError (t , err )
304+ assert .NoError (t , fileutils .CreateDirIfNotExist (workspace ))
305+ testDataDir := filepath .Join (filepath .FromSlash (tests .GetTestResourcesPath ()), "docker" )
306+ files , err := os .ReadDir (testDataDir )
307+ assert .NoError (t , err )
308+ for _ , file := range files {
309+ if ! file .IsDir () {
310+ _ , err := tests .ReplaceTemplateVariables (filepath .Join (testDataDir , file .Name ()), tests .Out )
311+ assert .NoError (t , err )
312+ }
275313 }
276314
277- assert .True (t , len (publishedBuildInfo .BuildInfo .Modules ) > 1 )
315+ // Build the builder image locally
316+ testContainer := buildBuilderImage (t , workspace , "Dockerfile.Buildx.Fatmanifest" , "buildx_multi_tag_container" )
317+ defer func () { assert .NoError (t , testContainer .Terminate (context .Background ())) }()
278318
279- // Validate build-name & build-number properties in all image layers
319+ // Enable builder
320+ assert .NoError (t , testContainer .Exec (context .Background (), "sh" , "script.sh" ))
321+
322+ // Login to Artifactory
323+ loginToArtifactory (t , testContainer )
324+
325+ // Build & push image with multiple tags
326+ imageName1 := path .Join (tests .RtContainerHostName , tests .DockerLocalRepo , tests .DockerImageName + "-multi:v1" )
327+ imageName2 := path .Join (tests .RtContainerHostName , tests .DockerLocalRepo , tests .DockerImageName + "-multi:latest" )
328+ buildxOutputFile := "multi-build-metadata"
329+
330+ assert .NoError (t , testContainer .Exec (
331+ context .Background (),
332+ "docker" , "buildx" , "build" ,
333+ "--platform" , "linux/amd64,linux/arm64" ,
334+ "-t" , imageName1 ,
335+ "-t" , imageName2 ,
336+ "-f" , "Dockerfile.Fatmanifest" ,
337+ "--metadata-file" , "/workspace/" + buildxOutputFile ,
338+ "--push" , "." ,
339+ ))
340+
341+ // Run build-docker-create & publish
342+ buildxOutput := filepath .Join (workspace , buildxOutputFile )
343+ assert .NoError (t , artifactoryCli .Exec ("build-docker-create" , tests .DockerLocalRepo , "--image-file=" + buildxOutput , "--build-name=" + buildName , "--build-number=" + buildNumber ))
344+ assert .NoError (t , artifactoryCli .Exec ("build-publish" , buildName , buildNumber ))
345+
346+ // Validate build-info is published
347+ publishedBuildInfo , found , err := tests .GetBuildInfo (serverDetails , buildName , buildNumber )
348+ assert .NoError (t , err )
349+ assert .True (t , found , "build info was expected to be found" )
350+ assert .True (t , len (publishedBuildInfo .BuildInfo .Modules ) >= 1 )
351+
352+ // Validate build-name & build-number properties in all layers
280353 searchSpec := spec .NewBuilder ().Pattern (tests .DockerLocalRepo + "/*" ).Build (buildName ).Recursive (true ).BuildSpec ()
281354 searchCmd := generic .NewSearchCommand ()
282355 searchCmd .SetServerDetails (serverDetails ).SetSpec (searchSpec )
0 commit comments