Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Spack target architecture - Wave #391

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ The endpoint returns the name of the container request made available by Wave.
| `containerFile` | Dockerfile used for building a new container encoded in base64 (optional). When provided, the attribute `containerImage` should be omitted. |
| `condaFile` | Conda environment file encoded as base64 string. |
| `spackFile` | Spack recipe file encoded as base64 string. |
| `containerPlatform` | Target container architecture of the built container e.g. `linux/amd64` (optional). Currently only supporting amd64 and arm64. |
| `spackTarget` | Target CPU architecture for Spack builds e.g. `x86_64_v3` (optional). |
| `containerPlatform` | Target container platform of the built container e.g. `linux/amd64` (optional). Currently only supporting amd64 and arm64. |
| `buildRepository` | Container repository where container builds should be pushed e.g. `docker.io/user/my-image` (optional). |
| `cacheRepository` | Container repository used to cache build layers `docker.io/user/my-cache` (optional). |
| `timestamp` | Request submission timestap using ISO-8601. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class ContainerTokenController {
final containerSpec = new String(req.containerFile.decodeBase64())
final condaContent = req.condaFile ? new String(req.condaFile.decodeBase64()) : null as String
final spackContent = req.spackFile ? new String(req.spackFile.decodeBase64()) : null as String
final spackTarget = req.spackFile ? req.spackTarget : null as String
final format = req.formatSingularity() ? SINGULARITY : DOCKER
final platform = ContainerPlatform.of(req.containerPlatform)
final build = req.buildRepository ?: (req.freeze && buildConfig.defaultPublicRepository ? buildConfig.defaultPublicRepository : buildConfig.defaultBuildRepository)
Expand All @@ -207,6 +208,7 @@ class ContainerTokenController {
build,
condaContent,
spackContent,
spackTarget,
format,
user,
containerConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ViewController {
binding.build_containerfile = result.dockerFile ?: '-'
binding.build_condafile = result.condaFile
binding.build_spackfile = result.spackFile
binding.build_spacktarget = result.spackTarget
binding.put('server_url', serverUrl)
binding.scan_url = result.scanId && result.succeeded() ? "$serverUrl/view/scans/${result.scanId}" : null
binding.scan_id = result.scanId
Expand Down
19 changes: 15 additions & 4 deletions src/main/groovy/io/seqera/wave/service/builder/BuildRequest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,15 @@ class BuildRequest {
final String condaFile

/**
* The spock file recipe associated with this request
* The spack file recipe associated with this request
*/
final String spackFile

/**
* Target architecture for Spack builds
*/
final String spackTarget

/**
* The build context work directory
*/
Expand Down Expand Up @@ -146,13 +151,14 @@ class BuildRequest {
*/
volatile boolean uncached

BuildRequest(String containerFile, Path workspace, String repo, String condaFile, String spackFile, BuildFormat format, User user, ContainerConfig containerConfig, BuildContext buildContext, ContainerPlatform platform, String configJson, String cacheRepo, String scanId, String ip, String offsetId) {
this.id = computeDigest(containerFile, condaFile, spackFile, platform, repo, buildContext)
BuildRequest(String containerFile, Path workspace, String repo, String condaFile, String spackFile, String spackTarget, BuildFormat format, User user, ContainerConfig containerConfig, BuildContext buildContext, ContainerPlatform platform, String configJson, String cacheRepo, String scanId, String ip, String offsetId) {
this.id = computeDigest(containerFile, condaFile, spackFile, spackTarget, platform, repo, buildContext)
this.containerFile = containerFile
this.containerConfig = containerConfig
this.buildContext = buildContext
this.condaFile = condaFile
this.spackFile = spackFile
this.spackTarget = spackTarget
this.targetImage = makeTarget(format, repo, id, condaFile, spackFile)
this.format = format
this.user = user
Expand Down Expand Up @@ -214,13 +220,14 @@ class BuildRequest {
return tag ?: null
}

static private String computeDigest(String containerFile, String condaFile, String spackFile, ContainerPlatform platform, String repository, BuildContext buildContext) {
static private String computeDigest(String containerFile, String condaFile, String spackFile, String spackTarget, ContainerPlatform platform, String repository, BuildContext buildContext) {
final attrs = new LinkedHashMap<String,String>(10)
attrs.containerFile = containerFile
attrs.condaFile = condaFile
attrs.platform = platform?.toString()
attrs.repository = repository
if( spackFile ) attrs.spackFile = spackFile
if( spackFile && spackTarget ) attrs.spackTarget = spackTarget
if( buildContext ) attrs.buildContext = buildContext.tarDigest
return RegHelper.sipHash(attrs)
}
Expand Down Expand Up @@ -251,6 +258,10 @@ class BuildRequest {
return spackFile
}

String getSpackTarget() {
return spackTarget
}

Path getWorkDir() {
return workDir
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class ContainerBuildServiceImpl implements ContainerBuildService {
final binding = new HashMap(2)
binding.spack_builder_image = config.builderImage
binding.spack_runner_image = config.runnerImage
binding.spack_arch = SpackHelper.toSpackArch(req.getPlatform())
binding.spack_target = req.getSpackTarget()
binding.spack_cache_bucket = config.cacheBucket
binding.spack_key_file = config.secretMountPath
return new TemplateRenderer().render(containerFile, binding)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class MailServiceImpl implements MailService {
binding.build_containerfile = req.containerFile ?: '-'
binding.build_condafile = req.condaFile
binding.build_spackfile = req.spackFile
binding.build_spacktarget = req.spackTarget
binding.put('build_log_data', result.logs)
binding.build_url = "$serverUrl/view/builds/${result.id}"
binding.scan_url = req.scanId && result.succeeded() ? "$serverUrl/view/scans/${req.scanId}" : null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class WaveBuildRecord {
String dockerFile
String condaFile
String spackFile
String spackTarget
String targetImage
String userName
String userEmail
Expand All @@ -65,6 +66,7 @@ class WaveBuildRecord {
dockerFile: event.request.containerFile,
condaFile: event.request.condaFile,
spackFile: event.request.spackFile,
spackTarget: event.request.spackTarget,
targetImage: event.request.targetImage,
userName: event.request.user?.userName,
userEmail: event.request.user?.email,
Expand Down
11 changes: 0 additions & 11 deletions src/main/groovy/io/seqera/wave/util/SpackHelper.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,4 @@ class SpackHelper {
throw new IllegalStateException("Unexpected build format: $buildFormat")
}

static String toSpackArch(ContainerPlatform platform) {
if( !platform )
throw new IllegalArgumentException("Missing container platform argument")
final value = platform.toString()
if( value=='linux/amd64' )
return 'x86_64'
if( value=='linux/arm64' )
return 'aarch64'
throw new IllegalArgumentException("Unable to map container platform '${platform}' to Spack architecture")
}

}
2 changes: 2 additions & 0 deletions src/main/resources/io/seqera/wave/build-notification.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ <h3>Conda file</h3>
<% } %>

<% if (build_spackfile) { %>
<h3>Spack target architecture</h3>
<pre style="white-space: pre-wrap; overflow: visible; background-color: #ededed; padding: 15px; border-radius: 4px; margin-bottom:30px;">${build_spacktarget}</pre>
<h3>Spack file</h3>
<pre style="white-space: pre-wrap; overflow: visible; background-color: #ededed; padding: 15px; border-radius: 4px; margin-bottom:30px;">${build_spackfile}</pre>
<% } %>
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/io/seqera/wave/build-view.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
{{/if}}

{{#if build_spackfile}}
<h3>Spack target architecture</h3>
<pre style="white-space: pre-wrap; overflow: visible; background-color: #ededed; padding: 15px; border-radius: 4px; margin-bottom:30px;">${build_spacktarget}</pre>
<h3>Spack file</h3>
<pre style="white-space: pre-wrap; overflow: visible; background-color: #ededed; padding: 15px; border-radius: 4px; margin-bottom:30px;">{{build_spackfile}}</pre>
{{/if}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN mkdir -p /opt/spack-env \
&& spack config add config:install_tree:/opt/software \
&& spack config add concretizer:unify:true \
&& spack config add concretizer:reuse:true \
&& spack config add packages:all:target:[{{spack_arch}}] \
&& spack config add packages:all:target:[{{spack_target}}] \
&& printf " view: /opt/view\n" >> /opt/spack-env/spack.yaml

# Install packages, clean afterward, finally strip binaries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ EOF
spack config add config:install_tree:/opt/software
spack config add concretizer:unify:true
spack config add concretizer:reuse:true
spack config add packages:all:target:[{{spack_arch}}]
spack config add packages:all:target:[{{spack_target}}]
printf " view: /opt/view\n" >> /opt/spack-env/spack.yaml

# Install packages, clean afterward, finally strip binaries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class ContainerBuildControllerTest extends Specification {
"buildrepo",
'conda::recipe',
'some-spack-recipe',
'zen3',
BuildFormat.DOCKER,
null,
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,16 @@ class ContainerTokenControllerTest extends Specification {
build.platform == ContainerPlatform.of('arm64')

when:
submit = new SubmitContainerTokenRequest(containerFile: encode('FROM foo'), spackFile: encode('some::spack-recipe'), containerPlatform: 'arm64')
submit = new SubmitContainerTokenRequest(containerFile: encode('FROM foo'), spackFile: encode('some::spack-recipe'), spackTarget: 'neoverse_v1', containerPlatform: 'arm64')
build = controller.makeBuildRequest(submit, null, "")
then:
build.id == 'b7d730d274d1e057'
build.id == '55f13a399562dfa9'
build.containerFile.endsWith('\nFROM foo')
build.containerFile.startsWith('# Builder image\n')
build.condaFile == null
build.spackFile == 'some::spack-recipe'
build.targetImage == 'wave/build:b7d730d274d1e057'
build.spackTarget == 'neoverse_v1'
build.targetImage == 'wave/build:55f13a399562dfa9'
build.workDir == Path.of('/some/wsp').resolve(build.id)
build.platform == ContainerPlatform.of('arm64')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class ViewControllerTest extends Specification {
dockerFile: 'FROM foo',
condaFile: 'conda::foo',
spackFile: 'some-spack-recipe',
spackTarget: 'zen3',
targetImage: 'docker.io/some:image',
userName: 'paolo',
userEmail: '[email protected]',
Expand All @@ -97,6 +98,7 @@ class ViewControllerTest extends Specification {
binding.build_containerfile == 'FROM foo'
binding.build_condafile == 'conda::foo'
binding.build_spackfile == 'some-spack-recipe'
binding.build_spacktarget == 'zen3'
binding.build_format == 'Docker'
binding.build_log_data == 'log content'
binding.build_log_truncated == false
Expand Down Expand Up @@ -130,6 +132,7 @@ class ViewControllerTest extends Specification {
and:
!response.body().contains('Conda file')
!response.body().contains('Spack file')
!response.body().contains('Spack target architecture')
}

def 'should render a build page with conda file' () {
Expand Down Expand Up @@ -161,13 +164,15 @@ class ViewControllerTest extends Specification {
response.body().contains('conda::foo')
and:
!response.body().contains('Spack file')
!response.body().contains('Spack target architecture')
}

def 'should render a build page with spack file' () {
given:
def record1 = new WaveBuildRecord(
buildId: 'test',
spackFile: 'foo/conda/recipe',
spackFile: 'foo/spack/recipe',
spackTarget: 'zen3',
targetImage: 'test',
userName: 'test',
userEmail: 'test',
Expand All @@ -191,7 +196,8 @@ class ViewControllerTest extends Specification {
!response.body().contains('Conda file')
and:
response.body().contains('Spack file')
response.body().contains('foo/conda/recipe')
response.body().contains('Spack target architecture')
response.body().contains('foo/spack/recipe')
}

def 'should render container view page' () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class BuildServiceRateLimitTest extends Specification{
RUN echo hi > hello.txt
""".stripIndent()
and:
def REQ = new BuildRequest(dockerfile, folder, buildRepo, null, null, BuildFormat.DOCKER, Mock(User), null, null, ContainerPlatform.of('amd64'),'{auth}', cacheRepo, null, "127.0.0.1", null)
def REQ = new BuildRequest(dockerfile, folder, buildRepo, null, null, null, BuildFormat.DOCKER, Mock(User), null, null, ContainerPlatform.of('amd64'),'{auth}', cacheRepo, null, "127.0.0.1", null)

when:
(0..configuration.build.authenticated.max).each {
Expand All @@ -93,7 +93,7 @@ class BuildServiceRateLimitTest extends Specification{
RUN echo hi > hello.txt
""".stripIndent()
and:
def REQ = new BuildRequest(dockerfile, folder, buildRepo, null, null, BuildFormat.DOCKER, Mock(User), null, null, ContainerPlatform.of('amd64'),'{auth}', cacheRepo, null, "127.0.0.1", null)
def REQ = new BuildRequest(dockerfile, folder, buildRepo, null, null, null, BuildFormat.DOCKER, Mock(User), null, null, ContainerPlatform.of('amd64'),'{auth}', cacheRepo, null, "127.0.0.1", null)

when:
(0..configuration.build.anonymous.max).each {
Expand Down
Loading
Loading