Skip to content

Commit aa90f38

Browse files
authored
Improve parsing of container platform (#810)
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
1 parent b234b8b commit aa90f38

File tree

7 files changed

+44
-20
lines changed

7 files changed

+44
-20
lines changed

src/main/groovy/io/seqera/wave/controller/ContainerController.groovy

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ class ContainerController {
251251
final generated = containerFileFromPackages(req.packages, req.formatSingularity())
252252
req = req.copyWith(containerFile: generated.bytes.encodeBase64().toString())
253253
}
254+
// make sure container platform is defined
255+
if( !req.containerPlatform )
256+
req.containerPlatform = ContainerPlatform.DEFAULT.toString()
254257

255258
final ip = addressResolver.resolve(httpRequest)
256259
// check the rate limit before continuing
@@ -322,7 +325,7 @@ class ContainerController {
322325
final containerSpec = decodeBase64OrFail(req.containerFile, 'containerFile')
323326
final condaContent = condaFileFromRequest(req)
324327
final format = req.formatSingularity() ? SINGULARITY : DOCKER
325-
final platform = ContainerPlatform.of(req.containerPlatform)
328+
final platform = ContainerPlatform.parseOrDefault(req.containerPlatform)
326329
final buildRepository = targetRepo( req.buildRepository ?: (req.freeze && buildConfig.defaultPublicRepository
327330
? buildConfig.defaultPublicRepository
328331
: buildConfig.defaultBuildRepository), req.nameStrategy)
@@ -405,8 +408,6 @@ class ContainerController {
405408
throw new BadRequestException("Container requests made using a SHA256 as tag does not support the 'containerConfig' attribute")
406409
if( req.formatSingularity() && !req.freeze )
407410
throw new BadRequestException("Singularity build is only allowed enabling freeze mode - see 'wave.freeze' setting")
408-
if( !req.containerPlatform )
409-
req.containerPlatform = ContainerPlatform.DEFAULT.toString()
410411

411412
// expand inclusions
412413
inclusionService.addContainerInclusions(req, identity)

src/main/groovy/io/seqera/wave/core/ContainerPlatform.groovy

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ class ContainerPlatform {
8080
return false
8181
}
8282

83+
static ContainerPlatform parseOrDefault(String value, ContainerPlatform defaultPlatform=DEFAULT) {
84+
return value ? of(value) : defaultPlatform
85+
}
86+
8387
static ContainerPlatform of(String value) {
8488
if( !value )
85-
return DEFAULT
89+
throw new BadRequestException("Missing container platform attribute")
8690

8791
final items= value.tokenize('/')
8892
if( items.size()==1 )

src/main/groovy/io/seqera/wave/service/builder/FreezeServiceImpl.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class FreezeServiceImpl implements FreezeService {
6868

6969
protected String appendEntrypoint(String containerFile, SubmitContainerTokenRequest req, PlatformId identity) {
7070
// get the container manifest
71-
final entry = inspectService.containerEntrypoint(containerFile, ContainerPlatform.of(req.containerPlatform), identity)
71+
final entry = inspectService.containerEntrypoint(containerFile, ContainerPlatform.parseOrDefault(req.containerPlatform), identity)
7272
if( entry ) {
7373
if( req.formatSingularity() ) {
7474
return containerFile + "%environment\n export WAVE_ENTRY_CHAIN=\"${entry.join(' ')}\"\n"

src/main/resources/application-postgres.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ wave:
22
db:
33
uri: "jdbc:postgresql://localhost:5432/postgres"
44
user: "postgres"
5-
password: "postgres"
5+
password: ""
66
datasources:
77
default:
88
db-type: postgres

src/test/groovy/io/seqera/wave/controller/ContainerControllerTest.groovy

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class ContainerControllerTest extends Specification {
116116
def controller = new ContainerController(inclusionService: Mock(ContainerInclusionService), registryProxyService: proxyRegistry)
117117

118118
when:
119-
def req = new SubmitContainerTokenRequest(containerImage: 'ubuntu:latest')
119+
def req = new SubmitContainerTokenRequest(containerImage: 'ubuntu:latest', containerPlatform: 'linux/amd64')
120120
def data = controller.makeRequestData(req, PlatformId.NULL, "")
121121
then:
122122
data.containerImage == 'docker.io/library/ubuntu:latest'
@@ -154,18 +154,16 @@ class ContainerControllerTest extends Specification {
154154
def controller = Spy(new ContainerController(freezeService: freeze, inclusionService: Mock(ContainerInclusionService)))
155155
and:
156156
def target = 'docker.io/repo/ubuntu:latest'
157-
def BUILD = Mock(BuildRequest) {
158-
getTargetImage() >> target
159-
}
157+
def build = Mock(BuildRequest) { getTargetImage() >> target }
160158
and:
161-
def req = new SubmitContainerTokenRequest(containerImage: containerImage, freeze: true, buildRepository: 'docker.io/foo/bar')
159+
def req = new SubmitContainerTokenRequest(containerImage: containerImage, containerPlatform: 'linux/amd64', freeze: true, buildRepository: 'docker.io/foo/bar')
162160

163161
when:
164162
def data = controller.makeRequestData(req, PlatformId.NULL, "")
165163
then:
166164
1 * freeze.freezeBuildRequest(req, _) >> req.copyWith(containerFile: 'FROM ubuntu:latest')
167-
1 * controller.makeBuildRequest(_,_,_) >> BUILD
168-
1 * controller.checkBuild(BUILD,false) >> new BuildTrack('1', target, false, false)
165+
1 * controller.makeBuildRequest(_,_,_) >> build
166+
1 * controller.checkBuild(build,false) >> new BuildTrack('1', target, false, false)
169167
1 * controller.getContainerDigest(containerImage, PlatformId.NULL) >> 'sha256:12345'
170168
and:
171169
data.containerImage == target
@@ -341,20 +339,17 @@ class ContainerControllerTest extends Specification {
341339
build.condaFile == 'some::conda-recipe'
342340
build.targetImage == 'wave/build:c6dac2e544419f71'
343341
build.platform == ContainerPlatform.of('arm64')
344-
345342
}
346343

347344
def 'should return a bad request exception when field is not encoded' () {
348345
given:
349346
def dockerAuth = Mock(ContainerInspectServiceImpl)
350347
def controller = new ContainerController(inspectService: dockerAuth, buildConfig: buildConfig)
348+
def request = new SubmitContainerTokenRequest(containerFile: 'FROM some:container', containerPlatform: 'linux/amd64')
351349

352350
// validate containerFile
353351
when:
354-
controller.makeBuildRequest(
355-
new SubmitContainerTokenRequest(containerFile: 'FROM some:container'),
356-
Mock(PlatformId),
357-
null)
352+
controller.makeBuildRequest(request, Mock(PlatformId), null)
358353
then:
359354
def e = thrown(BadRequestException)
360355
e.message == "Invalid 'containerFile' attribute - make sure it encoded as a base64 string"

src/test/groovy/io/seqera/wave/core/ContainerPlatformTest.groovy

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ package io.seqera.wave.core
2121
import spock.lang.Specification
2222
import spock.lang.Unroll
2323

24+
import io.seqera.wave.exception.BadRequestException
25+
2426
/**
2527
*
2628
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
@@ -35,7 +37,6 @@ class ContainerPlatformTest extends Specification {
3537

3638
where:
3739
PLATFORM | EXPECTED | STRING
38-
null | new ContainerPlatform('linux','amd64') | 'linux/amd64'
3940
'x86_64' | new ContainerPlatform('linux','amd64') | 'linux/amd64'
4041
'amd64' | new ContainerPlatform('linux','amd64') | 'linux/amd64'
4142
'linux/amd64' | new ContainerPlatform('linux','amd64') | 'linux/amd64'
@@ -53,7 +54,30 @@ class ContainerPlatformTest extends Specification {
5354
and:
5455
'linux/arm64/v8'| new ContainerPlatform('linux','arm64') | 'linux/arm64'
5556
'linux/arm64/v7'| new ContainerPlatform('linux','arm64','v7') | 'linux/arm64/v7'
57+
}
58+
59+
def 'should return an exception' () {
60+
when:
61+
ContainerPlatform.of(null)
62+
then:
63+
thrown(BadRequestException)
5664

65+
when:
66+
ContainerPlatform.of('foo')
67+
then:
68+
thrown(BadRequestException)
69+
}
70+
71+
def 'should parse the platform or return default' () {
72+
expect:
73+
ContainerPlatform.parseOrDefault(PLATFORM) == EXPECTED
74+
ContainerPlatform.parseOrDefault(PLATFORM).toString() == STRING
75+
76+
where:
77+
PLATFORM | EXPECTED | STRING
78+
null | new ContainerPlatform('linux','amd64') | 'linux/amd64'
79+
'x86_64' | new ContainerPlatform('linux','amd64') | 'linux/amd64'
80+
'arm64' | new ContainerPlatform('linux','arm64') | 'linux/arm64'
5781
}
5882

5983
@Unroll

src/test/groovy/io/seqera/wave/service/builder/FreezeServiceImplTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class FreezeServiceImplTest extends Specification {
103103

104104
def 'should create build file given a container image for singularity' () {
105105
when:
106-
def req = new SubmitContainerTokenRequest(containerImage: 'ubuntu:latest', freeze: true, format: 'sif')
106+
def req = new SubmitContainerTokenRequest(containerImage: 'ubuntu:latest', containerPlatform: 'linux/amd64', freeze: true, format: 'sif')
107107
def result = freezeService.createBuildFile(req, Mock(PlatformId))
108108
then:
109109
result == '''\

0 commit comments

Comments
 (0)