@@ -215,6 +215,7 @@ var allTests = integration.TestFuncs(
215215 testStepNames ,
216216 testPowershellInDefaultPathOnWindows ,
217217 testOCILayoutMultiname ,
218+ testPlatformWithOSVersion ,
218219)
219220
220221// Tests that depend on the `security.*` entitlements
@@ -9425,6 +9426,158 @@ COPY Dockerfile /foo
94259426 }
94269427}
94279428
9429+ func testPlatformWithOSVersion (t * testing.T , sb integration.Sandbox ) {
9430+ // This test cannot be run on Windows currently due to `FROM scratch` and
9431+ // layer formatting not being supported on Windows.
9432+ integration .SkipOnPlatform (t , "windows" )
9433+
9434+ ctx := sb .Context ()
9435+
9436+ c , err := client .New (ctx , sb .Address ())
9437+ require .NoError (t , err )
9438+ defer c .Close ()
9439+
9440+ f := getFrontend (t , sb )
9441+
9442+ // NOTE: currently "OS" *must* be set to "windows" for this to work.
9443+ // The platform matchers only do OSVersion comparisons when the OS is set to "windows".
9444+ p1 := ocispecs.Platform {
9445+ OS : "windows" ,
9446+ OSVersion : "1.2.3" ,
9447+ Architecture : "bar" ,
9448+ }
9449+ p2 := ocispecs.Platform {
9450+ OS : "windows" ,
9451+ OSVersion : "1.1.0" ,
9452+ Architecture : "bar" ,
9453+ }
9454+
9455+ p1Str := platforms .FormatAll (p1 )
9456+ p2Str := platforms .FormatAll (p2 )
9457+
9458+ registry , err := sb .NewRegistry ()
9459+ if errors .Is (err , integration .ErrRequirements ) {
9460+ t .Skip (err .Error ())
9461+ }
9462+ require .NoError (t , err )
9463+ target := registry + "/buildkit/testplatformwithosversion:latest"
9464+
9465+ dockerfile := []byte (`
9466+ FROM ` + target + ` AS reg
9467+
9468+ FROM scratch AS base
9469+ ARG TARGETOSVERSION
9470+ COPY <<EOF /osversion
9471+ ${TARGETOSVERSION}
9472+ EOF
9473+ ARG TARGETPLATFORM
9474+ COPY <<EOF /targetplatform
9475+ ${TARGETPLATFORM}
9476+ EOF
9477+ ` )
9478+
9479+ destDir := t .TempDir ()
9480+ dir := integration .Tmpdir (
9481+ t ,
9482+ fstest .CreateFile ("Dockerfile" , dockerfile , 0600 ),
9483+ )
9484+
9485+ // build the base target as a multi-platform image and push to the registry
9486+ _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
9487+ FrontendAttrs : map [string ]string {
9488+ "platform" : p1Str + "," + p2Str ,
9489+ "target" : "base" ,
9490+ },
9491+ Exports : []client.ExportEntry {
9492+ {
9493+ Type : client .ExporterLocal ,
9494+ OutputDir : destDir ,
9495+ },
9496+ {
9497+ Type : client .ExporterImage ,
9498+ Attrs : map [string ]string {
9499+ "name" : target ,
9500+ "push" : "true" ,
9501+ },
9502+ },
9503+ },
9504+
9505+ LocalMounts : map [string ]fsutil.FS {
9506+ dockerui .DefaultLocalNameDockerfile : dir ,
9507+ dockerui .DefaultLocalNameContext : dir ,
9508+ },
9509+ }, nil )
9510+
9511+ require .NoError (t , err )
9512+
9513+ dt , err := os .ReadFile (filepath .Join (destDir , strings .Replace (p1Str , "/" , "_" , 1 ), "osversion" ))
9514+ require .NoError (t , err )
9515+ require .Equal (t , p1 .OSVersion + "\n " , string (dt ))
9516+
9517+ dt , err = os .ReadFile (filepath .Join (destDir , strings .Replace (p1Str , "/" , "_" , 1 ), "targetplatform" ))
9518+ require .NoError (t , err )
9519+ require .Equal (t , p1Str + "\n " , string (dt ))
9520+
9521+ dt , err = os .ReadFile (filepath .Join (destDir , strings .Replace (p2Str , "/" , "_" , 1 ), "osversion" ))
9522+ require .NoError (t , err )
9523+ require .Equal (t , p2 .OSVersion + "\n " , string (dt ))
9524+
9525+ dt , err = os .ReadFile (filepath .Join (destDir , strings .Replace (p2Str , "/" , "_" , 1 ), "targetplatform" ))
9526+ require .NoError (t , err )
9527+ require .Equal (t , p2Str + "\n " , string (dt ))
9528+
9529+ // Now build the "reg" target, which should pull the base image from the registry
9530+ // This should select the image with the requested os version.
9531+ destDir = t .TempDir ()
9532+ _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
9533+ FrontendAttrs : map [string ]string {
9534+ "platform" : p1Str ,
9535+ "target" : "reg" ,
9536+ },
9537+ Exports : []client.ExportEntry {
9538+ {
9539+ Type : client .ExporterLocal ,
9540+ OutputDir : destDir ,
9541+ },
9542+ },
9543+
9544+ LocalMounts : map [string ]fsutil.FS {
9545+ dockerui .DefaultLocalNameDockerfile : dir ,
9546+ dockerui .DefaultLocalNameContext : dir ,
9547+ },
9548+ }, nil )
9549+ require .NoError (t , err )
9550+
9551+ dt , err = os .ReadFile (filepath .Join (destDir , "osversion" ))
9552+ require .NoError (t , err )
9553+ require .Equal (t , p1 .OSVersion + "\n " , string (dt ))
9554+
9555+ // And again with the other os version
9556+ destDir = t .TempDir ()
9557+ _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
9558+ FrontendAttrs : map [string ]string {
9559+ "platform" : p2Str ,
9560+ "target" : "reg" ,
9561+ },
9562+ Exports : []client.ExportEntry {
9563+ {
9564+ Type : client .ExporterLocal ,
9565+ OutputDir : destDir ,
9566+ },
9567+ },
9568+
9569+ LocalMounts : map [string ]fsutil.FS {
9570+ dockerui .DefaultLocalNameDockerfile : dir ,
9571+ dockerui .DefaultLocalNameContext : dir ,
9572+ },
9573+ }, nil )
9574+ require .NoError (t , err )
9575+
9576+ dt , err = os .ReadFile (filepath .Join (destDir , "osversion" ))
9577+ require .NoError (t , err )
9578+ require .Equal (t , p2 .OSVersion + "\n " , string (dt ))
9579+ }
9580+
94289581func runShell (dir string , cmds ... string ) error {
94299582 for _ , args := range cmds {
94309583 var cmd * exec.Cmd
0 commit comments