1
1
package test
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
6
+ "debug/elf"
5
7
"errors"
6
8
"fmt"
7
9
"os"
@@ -10,9 +12,16 @@ import (
10
12
11
13
"github.com/Azure/dalec"
12
14
"github.com/Azure/dalec/frontend/azlinux"
15
+ "github.com/containerd/platforms"
13
16
"github.com/moby/buildkit/client/llb"
14
17
gwclient "github.com/moby/buildkit/frontend/gateway/client"
15
18
moby_buildkit_v1_frontend "github.com/moby/buildkit/frontend/gateway/pb"
19
+ ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
20
+ )
21
+
22
+ var (
23
+ linuxAmd64 = ocispecs.Platform {OS : "linux" , Architecture : "amd64" }
24
+ linuxArm64 = ocispecs.Platform {OS : "linux" , Architecture : "arm64" }
16
25
)
17
26
18
27
func TestMariner2 (t * testing.T ) {
@@ -41,6 +50,7 @@ func TestMariner2(t *testing.T) {
41
50
ID : "mariner" ,
42
51
VersionID : "2.0" ,
43
52
},
53
+ SupportedPlatforms : platforms .Any (linuxAmd64 , linuxArm64 ),
44
54
})
45
55
}
46
56
@@ -70,6 +80,7 @@ func TestAzlinux3(t *testing.T) {
70
80
ID : "azurelinux" ,
71
81
VersionID : "3.0" ,
72
82
},
83
+ SupportedPlatforms : platforms .Any (linuxAmd64 , linuxArm64 ),
73
84
})
74
85
}
75
86
@@ -124,8 +135,9 @@ type testLinuxConfig struct {
124
135
Units string
125
136
Targets string
126
137
}
127
- Worker workerConfig
128
- Release OSRelease
138
+ Worker workerConfig
139
+ Release OSRelease
140
+ SupportedPlatforms platforms.Matcher
129
141
}
130
142
131
143
type OSRelease struct {
@@ -603,6 +615,7 @@ WantedBy=multi-user.target
603
615
Dir : & dalec.SourceInlineDir {
604
616
605
617
Files : map [string ]* dalec.SourceInlineFile {
618
+
606
619
"foo.service" : {
607
620
Contents : `
608
621
# simple-socket.service
@@ -1144,6 +1157,11 @@ Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/boot
1144
1157
})
1145
1158
})
1146
1159
1160
+ t .Run ("platform" , func (t * testing.T ) {
1161
+ ctx := startTestSpan (ctx , t )
1162
+ testPlatforms (ctx , t , testConfig )
1163
+ })
1164
+
1147
1165
t .Run ("custom worker" , func (t * testing.T ) {
1148
1166
t .Parallel ()
1149
1167
ctx := startTestSpan (baseCtx , t )
@@ -1246,6 +1264,128 @@ func testCustomLinuxWorker(ctx context.Context, t *testing.T, targetCfg targetCo
1246
1264
// Unfortunately it seems like there is an issue with the gateway client passing
1247
1265
// in source policies.
1248
1266
})
1267
+
1268
+ }
1269
+
1270
+ func testPlatforms (ctx context.Context , t * testing.T , testConfig testLinuxConfig ) {
1271
+ t .Run ("build against different platform" , func (t * testing.T ) {
1272
+ t .Parallel ()
1273
+
1274
+ ls , err := testEnv .Platforms (ctx )
1275
+ if err != nil {
1276
+ t .Fatal (err )
1277
+ }
1278
+ if len (ls ) <= 1 {
1279
+ t .Skipf ("builder does not support multiple platforms: %s" , platformsAsStringer (ls ))
1280
+ }
1281
+
1282
+ testEnv .RunTest (ctx , t , func (ctx context.Context , client gwclient.Client ) {
1283
+ p := readDefaultPlatform (ctx , t , client )
1284
+
1285
+ matcher := platforms .OnlyStrict (p )
1286
+ var testPlatform * ocispecs.Platform
1287
+ for _ , p2 := range ls {
1288
+ // Get the first platform that is not the host platform that matches a supported distro platform
1289
+ if ! matcher .Match (p2 ) && testConfig .SupportedPlatforms .Match (p2 ) {
1290
+ testPlatform = & p2
1291
+ break
1292
+ }
1293
+ }
1294
+
1295
+ if testPlatform == nil {
1296
+ msg := "could not find a platform suitable for testing, host platform: %s, available: %s"
1297
+ ps := platformStringer (p )
1298
+ workerPlatforms := platformsAsStringer (ls )
1299
+ if os .Getenv ("DALEC_CI" ) != "" {
1300
+ t .Fatalf (msg , ps , workerPlatforms )
1301
+ }
1302
+ t .Skipf (msg , ps , workerPlatforms )
1303
+ }
1304
+
1305
+ spec := & dalec.Spec {
1306
+ Name : "test-platforms" ,
1307
+ Version : "0.0.1" ,
1308
+ Revision : "1" ,
1309
+ Description : "Testing building on platform different from host platform" ,
1310
+ License : "MIT" ,
1311
+ Dependencies : & dalec.PackageDependencies {
1312
+ Build : map [string ]dalec.PackageConstraints {
1313
+ "golang" : {},
1314
+ },
1315
+ },
1316
+ Sources : map [string ]dalec.Source {
1317
+ "src" : {
1318
+ Inline : & dalec.SourceInline {
1319
+ Dir : & dalec.SourceInlineDir {
1320
+ Files : map [string ]* dalec.SourceInlineFile {
1321
+ "go.mod" : {
1322
+ Contents : "module test\n \n go 1.21.6" ,
1323
+ },
1324
+ "main.go" : {
1325
+ Contents : "package main\n \n func main() {}\n " ,
1326
+ },
1327
+ },
1328
+ },
1329
+ },
1330
+ },
1331
+ },
1332
+ Build : dalec.ArtifactBuild {
1333
+ Steps : []dalec.BuildStep {
1334
+ {Command : "cd src; go build -o /tmp/test" },
1335
+ },
1336
+ },
1337
+ Artifacts : dalec.Artifacts {
1338
+ Binaries : map [string ]dalec.ArtifactConfig {
1339
+ "/tmp/test" : {},
1340
+ },
1341
+ },
1342
+ }
1343
+
1344
+ tp := * testPlatform
1345
+ req := newSolveRequest (withPlatform (tp ), withSpec (ctx , t , spec ), withBuildTarget (testConfig .Target .Container ))
1346
+ res := solveT (ctx , t , client , req )
1347
+
1348
+ imgPlatforms := readResultPlatforms (t , res )
1349
+ if len (imgPlatforms ) != 1 {
1350
+ t .Fatal ("expected image output to contain 1 platform" )
1351
+ }
1352
+
1353
+ if ! platforms .OnlyStrict (tp ).Match (imgPlatforms [0 ]) {
1354
+ t .Errorf ("Expected image platform %q, got: %q" , platformStringer (tp ), platformStringer (imgPlatforms [0 ]))
1355
+ }
1356
+
1357
+ ref , err := res .SingleRef ()
1358
+ if err != nil {
1359
+ t .Fatal (err )
1360
+ }
1361
+ if ref == nil {
1362
+ t .Fatal ("got empty reference -- most likely an empty (scratch) state was returned" )
1363
+ }
1364
+
1365
+ // Read the ELF header so we can determine what the target architecture is.
1366
+ dt , err := ref .ReadFile (ctx , gwclient.ReadRequest {
1367
+ Filename : "/usr/bin/test" ,
1368
+ })
1369
+ if err != nil {
1370
+ t .Fatal (err )
1371
+ }
1372
+
1373
+ f , err := elf .NewFile (bytes .NewReader (dt ))
1374
+ if err != nil {
1375
+ t .Fatal (err )
1376
+ }
1377
+
1378
+ check := ocispecs.Platform {
1379
+ OS : "linux" ,
1380
+ }
1381
+ elfToPlatform (f , & check )
1382
+
1383
+ if ! platforms .OnlyStrict (* testPlatform ).Match (check ) {
1384
+ t .Fatalf ("output binary has unexpected platform, expected: %s, got: %s" , platformStringer (* testPlatform ), platformStringer (check ))
1385
+ }
1386
+ })
1387
+ })
1388
+
1249
1389
}
1250
1390
1251
1391
func testPinnedBuildDeps (ctx context.Context , t * testing.T , targetCfg targetConfig , workerCfg workerConfig ) {
0 commit comments