diff --git a/README.md b/README.md
index cbbe3e5f6..10d853924 100644
--- a/README.md
+++ b/README.md
@@ -14,10 +14,9 @@ images.
* Augment container images i.e. dynamically add one or more container layers to existing images;
* Build container images on-demand for a given container file (aka Dockerfile);
* Build container images on-demand based on one or more Conda packages;
-* Build container images on-demand based on one or more Spack packages, Spack support will be removed in future releases;
* Build container images for a specified target platform (currently linux/amd64 and linux/arm64);
* Push and cache built containers to a user-provided container repository;
-* Build Singularity native containers both using a Singularity spec file, Conda package(s) and Spack package(s);
+* Build Singularity native containers both using a Singularity spec file, Conda package(s);
* Push Singularity native container images to OCI-compliant registries;
diff --git a/configuration.md b/configuration.md
index b7523b17c..d162a98b5 100644
--- a/configuration.md
+++ b/configuration.md
@@ -107,20 +107,6 @@ Below are the standard format for known registries, but you can change registry
- **`wave.build.force-compression`**: determines whether to force the compression for each cache layers produced by the build process. The default is `false`, enabling compression for more efficient storage. *Optional*.
-### Spack configuration for wave build process
-
-**Note**: Spack support will be removed in future releases.
-
-Spack configuration consists of the path of its secret file, the mount path for the secret file in the spack container, and the optional S3 bucket name for the spack binary cache.
-
-**Note**: these configuration are mandatory to support Spack in a wave installation.
-
-- **`wave.build.spack.secretKeyFile`**: the path to the file containing the PGP private key used to [sign Spack packages built by Wave](https://spack.readthedocs.io/en/latest/binary_caches.html#build-cache-signing). For example, `/efs/wave/spack/key`. *Mandatory*.
-
-- **`wave.build.spack.secretMountPath`**: sets the mount path inside the Spack Docker image for the PGP private key specified by `wave.build.spack.secretKeyFile`. For instance `/var/seqera/spack/key`. Indicating where the PGP private key should be mounted inside the Spack Docker image. *Mandatory*.
-
-- **`wave.build.spack.cacheBucket`**: specifies the S3 bucket for the Spack binary cache, for example, `s3://spack-binarycache`. *Optional*.
-
### Build process logs configuration
This configuration specifies attributes for the persistence of the logs fetched from containers or k8s pods used for building requested images, which can be accessed later and also attached to the build completion email.
diff --git a/docs/api.mdx b/docs/api.mdx
index 0d646c0b3..ca52843f3 100644
--- a/docs/api.mdx
+++ b/docs/api.mdx
@@ -52,7 +52,6 @@ This API endpoint is deprecated in current versions of Wave.
]
},
condaFile: string,
- spackFile: string,
containerPlatform: string,
buildRepository: string,
cacheRepository: string,
@@ -81,7 +80,6 @@ This API endpoint is deprecated in current versions of Wave.
| `containerConfig.layers.gzipSize` | The size in bytes of the the provided layer tar gzip file. |
| `containerFile` | Dockerfile used for building a new container encoded in base64 (optional). When provided, the attribute `containerImage` must be omitted. |
| `condaFile` | Conda environment file encoded as base64 string. |
-| `spackFile` | `Deprecated` Spack recipe file encoded as base64 string. Spack support will be removed in future releases. |
| `containerPlatform` | Target container architecture 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). |
@@ -136,7 +134,6 @@ The endpoint returns the name of the container request made available by Wave.
]
},
condaFile: string,
- spackFile: string,
containerPlatform: string,
buildRepository: string,
cacheRepository: string,
@@ -157,10 +154,6 @@ The endpoint returns the name of the container request made available by Wave.
commands: string[],
basePackages: string
}
- spackOpts:{
- commands: string[],
- basePackages: string
- }
},
nameStrategy: string
@@ -182,7 +175,6 @@ The endpoint returns the name of the container request made available by Wave.
| `containerConfig.layers.gzipSize` | The size in bytes of the the provided layer tar gzip file. |
| `containerFile` | Dockerfile used for building a new container encoded in base64 (optional). When provided, the attribute `containerImage` must be omitted. |
| `condaFile` | Conda environment file encoded as base64 string. |
-| `spackFile` | `Deprecated` Spack recipe file encoded as base64 string. Spack support will be removed in future releases. |
| `containerPlatform` | Target container architecture 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). |
diff --git a/src/main/groovy/io/seqera/wave/configuration/SpackConfig.groovy b/src/main/groovy/io/seqera/wave/configuration/SpackConfig.groovy
deleted file mode 100644
index 0b81d6299..000000000
--- a/src/main/groovy/io/seqera/wave/configuration/SpackConfig.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Wave, containers provisioning service
- * Copyright (c) 2023-2024, Seqera Labs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package io.seqera.wave.configuration
-
-import java.nio.file.Path
-
-import groovy.transform.CompileStatic
-import groovy.transform.EqualsAndHashCode
-import groovy.transform.ToString
-import io.micronaut.context.annotation.Value
-import io.micronaut.core.annotation.Nullable
-import jakarta.inject.Singleton
-/**
- * Model Spack configuration
- *
- * @author Paolo Di Tommaso
- */
-@ToString
-@EqualsAndHashCode
-@Singleton
-@CompileStatic
-@Deprecated
-class SpackConfig {
-
- /**
- * The s3 bucket where Spack cached binaries are stored
- */
- @Nullable
- @Value('${wave.build.spack.cacheBucket}')
- private String cacheBucket
-
- /**
- * The host path where the GPG key required by the Spack "buildcache" is located
- */
- @Nullable
- @Value('${wave.build.spack.secretKeyFile}')
- private String secretKeyFile
-
- /**
- * The container path where the GPG key required by the Spack "buildcache" is located
- */
- @Nullable
- @Value('${wave.build.spack.secretMountPath}')
- private String secretMountPath
-
- /**
- * The container image used for Spack builds
- */
- @Value('${wave.build.spack.builderImage:`spack/ubuntu-jammy:v0.20.0`}')
- private String builderImage
-
- /**
- * The container image used for Spack container
- */
- @Value('${wave.build.spack.runnerImage:`ubuntu:22.04`}')
- private String runnerImage
-
- String getCacheBucket() {
- if( !cacheBucket )
- throw new IllegalStateException("Missing Spack 'cacheBucket' configuration setting")
- return cacheBucket
- }
-
- Path getSecretKeyFile() {
- if( !secretKeyFile )
- throw new IllegalStateException("Missing Spack 'secretKeyFile' configuration setting")
- return Path.of(secretKeyFile).toAbsolutePath().normalize()
- }
-
- String getSecretMountPath() {
- if( !secretMountPath )
- throw new IllegalStateException("Missing Spack 'secretMountPath' configuration setting")
- return secretMountPath
- }
-
- String getBuilderImage() {
- return builderImage
- }
-
- String getRunnerImage() {
- return runnerImage
- }
-}
diff --git a/src/main/groovy/io/seqera/wave/controller/ContainerController.groovy b/src/main/groovy/io/seqera/wave/controller/ContainerController.groovy
index 2499bf925..6fcd84dd8 100644
--- a/src/main/groovy/io/seqera/wave/controller/ContainerController.groovy
+++ b/src/main/groovy/io/seqera/wave/controller/ContainerController.groovy
@@ -86,8 +86,6 @@ import static io.seqera.wave.util.ContainerHelper.makeResponseV1
import static io.seqera.wave.util.ContainerHelper.makeResponseV2
import static io.seqera.wave.util.ContainerHelper.makeTargetImage
import static io.seqera.wave.util.ContainerHelper.patchPlatformEndpoint
-import static io.seqera.wave.util.ContainerHelper.spackFileFromRequest
-import static io.seqera.wave.util.SpackHelper.prependBuilderTemplate
import static java.util.concurrent.CompletableFuture.completedFuture
/**
* Implement a controller to receive container token requests
@@ -237,6 +235,10 @@ class ContainerController {
req = req.copyWith(containerFile: generated.bytes.encodeBase64().toString())
}
+ if( req.spackFile ) {
+ throw new BadRequestException("Spack packages are not supported any more")
+ }
+
final ip = addressResolver.resolve(httpRequest)
// check the rate limit before continuing
if( rateLimiterService )
@@ -317,7 +319,6 @@ class ContainerController {
final containerSpec = decodeBase64OrFail(req.containerFile, 'containerFile')
final condaContent = condaFileFromRequest(req)
- final spackContent = spackFileFromRequest(req)
final format = req.formatSingularity() ? SINGULARITY : DOCKER
final platform = ContainerPlatform.of(req.containerPlatform)
final buildRepository = targetRepo( req.buildRepository ?: (req.freeze && buildConfig.defaultPublicRepository
@@ -328,7 +329,6 @@ class ContainerController {
final containerConfig = req.freeze ? req.containerConfig : null
final offset = DataTimeUtils.offsetId(req.timestamp)
final scanId = scanEnabled && format==DOCKER ? LongRndKey.rndHex() : null
- final containerFile = spackContent ? prependBuilderTemplate(containerSpec,format) : containerSpec
// use 'imageSuffix' strategy by default for public repo images
final nameStrategy = req.nameStrategy==null
&& buildRepository
@@ -338,14 +338,13 @@ class ContainerController {
checkContainerSpec(containerSpec)
// create a unique digest to identify the build request
- final containerId = makeContainerId(containerFile, condaContent, spackContent, platform, buildRepository, req.buildContext)
- final targetImage = makeTargetImage(format, buildRepository, containerId, condaContent, spackContent, nameStrategy)
+ final containerId = makeContainerId(containerSpec, condaContent, platform, buildRepository, req.buildContext)
+ final targetImage = makeTargetImage(format, buildRepository, containerId, condaContent, nameStrategy)
final maxDuration = buildConfig.buildMaxDuration(req)
return new BuildRequest(
containerId,
- containerFile,
+ containerSpec,
condaContent,
- spackContent,
Path.of(buildConfig.buildWorkspace),
targetImage,
identity,
diff --git a/src/main/groovy/io/seqera/wave/controller/ViewController.groovy b/src/main/groovy/io/seqera/wave/controller/ViewController.groovy
index 7ebf43e0c..441239a9e 100644
--- a/src/main/groovy/io/seqera/wave/controller/ViewController.groovy
+++ b/src/main/groovy/io/seqera/wave/controller/ViewController.groovy
@@ -129,7 +129,6 @@ class ViewController {
binding.build_platform = result.platform
binding.build_containerfile = result.dockerFile ?: '-'
binding.build_condafile = result.condaFile
- binding.build_spackfile = result.spackFile
binding.build_digest = result.digest ?: '-'
binding.put('server_url', serverUrl)
binding.scan_url = result.scanId && result.succeeded() ? "$serverUrl/view/scans/${result.scanId}" : null
diff --git a/src/main/groovy/io/seqera/wave/service/builder/BuildCacheStore.groovy b/src/main/groovy/io/seqera/wave/service/builder/BuildCacheStore.groovy
index cdd914598..dbc4085c7 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/BuildCacheStore.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/BuildCacheStore.groovy
@@ -60,7 +60,7 @@ class BuildCacheStore extends AbstractCacheStore implements Bui
protected Duration getDuration() {
return buildConfig.statusDuration
}
-
+
@Override
BuildStoreEntry getBuild(String imageName) {
return get(imageName)
diff --git a/src/main/groovy/io/seqera/wave/service/builder/BuildRequest.groovy b/src/main/groovy/io/seqera/wave/service/builder/BuildRequest.groovy
index 98b51b82b..9682fb536 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/BuildRequest.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/BuildRequest.groovy
@@ -60,11 +60,6 @@ class BuildRequest {
*/
final String condaFile
- /**
- * The spock file recipe associated with this request
- */
- final String spackFile
-
/**
* The build context work directory
*/
@@ -116,11 +111,6 @@ class BuildRequest {
final ContainerConfig containerConfig
/**
- * Whenever is a spack build
- */
- final boolean isSpackBuild
-
- /**
* The ID of the security scan triggered by this build
*/
final String scanId
@@ -147,7 +137,6 @@ class BuildRequest {
BuildRequest(String containerId,
String containerFile,
String condaFile,
- String spackFile,
Path workspace,
String targetImage,
PlatformId identity,
@@ -166,7 +155,6 @@ class BuildRequest {
this.containerId = containerId
this.containerFile = containerFile
this.condaFile = condaFile
- this.spackFile = spackFile
this.workspace = workspace
this.targetImage = targetImage
this.identity = identity
@@ -177,7 +165,6 @@ class BuildRequest {
this.configJson = configJson
this.offsetId = offsetId ?: OffsetDateTime.now().offset.id
this.containerConfig = containerConfig
- this.isSpackBuild = spackFile
this.scanId = scanId
this.buildContext = buildContext
this.format = format
@@ -188,7 +175,6 @@ class BuildRequest {
this.containerId = opts.containerId
this.containerFile = opts.containerFile
this.condaFile = opts.condaFile
- this.spackFile = opts.spackFile
this.workspace = opts.workspace as Path
this.targetImage = opts.targetImage
this.identity = opts.identity as PlatformId
@@ -199,7 +185,6 @@ class BuildRequest {
this.configJson = opts.configJson
this.offsetId = opts.offesetId
this.containerConfig = opts.containerConfig as ContainerConfig
- this.isSpackBuild = opts.isSpackBuild
this.scanId = opts.scanId
this.buildContext = opts.buildContext as BuildContext
this.format = opts.format as BuildFormat
@@ -210,7 +195,7 @@ class BuildRequest {
@Override
String toString() {
- return "BuildRequest[containerId=$containerId; targetImage=$targetImage; identity=$identity; dockerFile=${trunc(containerFile)}; condaFile=${trunc(condaFile)}; spackFile=${trunc(spackFile)}; buildId=$buildId, maxDuration=$maxDuration]"
+ return "BuildRequest[containerId=$containerId; targetImage=$targetImage; identity=$identity; dockerFile=${trunc(containerFile)}; condaFile=${trunc(condaFile)}; buildId=$buildId, maxDuration=$maxDuration]"
}
String getContainerId() {
@@ -230,10 +215,6 @@ class BuildRequest {
return condaFile
}
- String getSpackFile() {
- return spackFile
- }
-
Path getWorkDir() {
return workDir
}
diff --git a/src/main/groovy/io/seqera/wave/service/builder/BuildStrategy.groovy b/src/main/groovy/io/seqera/wave/service/builder/BuildStrategy.groovy
index fb5a25cb4..c061c30e5 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/BuildStrategy.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/BuildStrategy.groovy
@@ -84,19 +84,6 @@ abstract class BuildStrategy {
result << "type=registry,ref=$req.cacheRepository:$req.containerId".toString()
}
- if(req.spackFile){
- result << '--opt'
- result << 'build-arg:AWS_STS_REGIONAL_ENDPOINTS=$(AWS_STS_REGIONAL_ENDPOINTS)'
- result << '--opt'
- result << 'build-arg:AWS_REGION=$(AWS_REGION)'
- result << '--opt'
- result << 'build-arg:AWS_DEFAULT_REGION=$(AWS_DEFAULT_REGION)'
- result << '--opt'
- result << 'build-arg:AWS_ROLE_ARN=$(AWS_ROLE_ARN)'
- result << '--opt'
- result << 'build-arg:AWS_WEB_IDENTITY_TOKEN_FILE=$(AWS_WEB_IDENTITY_TOKEN_FILE)'
- }
-
return result
}
diff --git a/src/main/groovy/io/seqera/wave/service/builder/ContainerBuildServiceImpl.groovy b/src/main/groovy/io/seqera/wave/service/builder/ContainerBuildServiceImpl.groovy
index 767ff9894..0579a992d 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/ContainerBuildServiceImpl.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/ContainerBuildServiceImpl.groovy
@@ -36,7 +36,6 @@ import io.seqera.wave.auth.RegistryCredentialsProvider
import io.seqera.wave.auth.RegistryLookupService
import io.seqera.wave.configuration.BuildConfig
import io.seqera.wave.configuration.HttpClientConfig
-import io.seqera.wave.configuration.SpackConfig
import io.seqera.wave.core.RegistryProxyService
import io.seqera.wave.exception.HttpServerRetryableErrorException
import io.seqera.wave.ratelimit.AcquireRequest
@@ -52,9 +51,7 @@ import io.seqera.wave.service.persistence.WaveBuildRecord
import io.seqera.wave.service.stream.StreamService
import io.seqera.wave.tower.PlatformId
import io.seqera.wave.util.Retryable
-import io.seqera.wave.util.SpackHelper
import io.seqera.wave.util.TarUtils
-import io.seqera.wave.util.TemplateRenderer
import jakarta.inject.Inject
import jakarta.inject.Named
import jakarta.inject.Singleton
@@ -100,9 +97,6 @@ class ContainerBuildServiceImpl implements ContainerBuildService, JobHandler buildCmd(String jobName, BuildRequest req, Path credsFile) {
- final spack = req.isSpackBuild ? spackConfig : null
final dockerCmd = req.formatDocker()
- ? cmdForBuildkit(jobName, req.workDir, credsFile, spack, req.platform)
- : cmdForSingularity(jobName, req.workDir, credsFile, spack, req.platform)
+ ? cmdForBuildkit(jobName, req.workDir, credsFile, req.platform)
+ : cmdForSingularity(jobName, req.workDir, credsFile, req.platform)
return dockerCmd + launchCmd(req)
}
- protected List cmdForBuildkit(String name, Path workDir, Path credsFile, SpackConfig spackConfig, ContainerPlatform platform ) {
+ protected List cmdForBuildkit(String name, Path workDir, Path credsFile, ContainerPlatform platform ) {
//checkout the documentation here to know more about these options https://github.com/moby/buildkit/blob/master/docs/rootless.md#docker
final wrapper = ['docker',
'run',
@@ -125,12 +120,6 @@ class DockerBuildStrategy extends BuildStrategy {
wrapper.add("$credsFile:/home/user/.docker/config.json:ro".toString())
}
- if( spackConfig ) {
- // secret file
- wrapper.add('-v')
- wrapper.add("${spackConfig.secretKeyFile}:${spackConfig.secretMountPath}:ro".toString())
- }
-
if( platform ) {
wrapper.add('--platform')
wrapper.add(platform.toString())
@@ -142,7 +131,7 @@ class DockerBuildStrategy extends BuildStrategy {
return wrapper
}
- protected List cmdForSingularity(String name, Path workDir, Path credsFile, SpackConfig spackConfig, ContainerPlatform platform) {
+ protected List cmdForSingularity(String name, Path workDir, Path credsFile, ContainerPlatform platform) {
final wrapper = ['docker',
'run',
'--detach',
@@ -159,12 +148,6 @@ class DockerBuildStrategy extends BuildStrategy {
wrapper.add("${credsFile.resolveSibling('singularity-remote.yaml')}:/root/.singularity/remote.yaml:ro".toString())
}
- if( spackConfig ) {
- // secret file
- wrapper.add('-v')
- wrapper.add("${spackConfig.secretKeyFile}:${spackConfig.secretMountPath}:ro".toString())
- }
-
if( platform ) {
wrapper.add('--platform')
wrapper.add(platform.toString())
diff --git a/src/main/groovy/io/seqera/wave/service/builder/KubeBuildStrategy.groovy b/src/main/groovy/io/seqera/wave/service/builder/KubeBuildStrategy.groovy
index 4d4e9fa06..f6ba6e041 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/KubeBuildStrategy.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/KubeBuildStrategy.groovy
@@ -30,7 +30,6 @@ import io.micronaut.context.annotation.Property
import io.micronaut.context.annotation.Requires
import io.micronaut.core.annotation.Nullable
import io.seqera.wave.configuration.BuildConfig
-import io.seqera.wave.configuration.SpackConfig
import io.seqera.wave.core.RegistryProxyService
import io.seqera.wave.exception.BadRequestException
import io.seqera.wave.service.k8s.K8sService
@@ -65,9 +64,6 @@ class KubeBuildStrategy extends BuildStrategy {
@Inject
private BuildConfig buildConfig
- @Inject
- private SpackConfig spackConfig
-
@Inject
private RegistryProxyService proxyService
@@ -95,8 +91,7 @@ class KubeBuildStrategy extends BuildStrategy {
final buildCmd = launchCmd(req)
final timeout = req.maxDuration ?: buildConfig.defaultTimeout
final selector= getSelectorLabel(req.platform, nodeSelectorMap)
- final spackCfg0 = req.isSpackBuild ? spackConfig : null
- k8sService.launchBuildJob(jobName, buildImage, buildCmd, req.workDir, configFile, timeout, spackCfg0, selector)
+ k8sService.launchBuildJob(jobName, buildImage, buildCmd, req.workDir, configFile, timeout, selector)
}
catch (ApiException e) {
throw new BadRequestException("Unexpected build failure - ${e.responseBody}", e)
diff --git a/src/main/groovy/io/seqera/wave/service/builder/store/BuildRecordCacheStore.groovy b/src/main/groovy/io/seqera/wave/service/builder/store/BuildRecordCacheStore.groovy
index 0f9884cfd..f820f080e 100644
--- a/src/main/groovy/io/seqera/wave/service/builder/store/BuildRecordCacheStore.groovy
+++ b/src/main/groovy/io/seqera/wave/service/builder/store/BuildRecordCacheStore.groovy
@@ -23,6 +23,7 @@ import java.time.Duration
import groovy.transform.CompileStatic
import io.seqera.wave.configuration.BuildConfig
import io.seqera.wave.encoder.MoshiEncodeStrategy
+import io.seqera.wave.service.builder.BuildStoreEntry
import io.seqera.wave.service.cache.AbstractCacheStore
import io.seqera.wave.service.cache.impl.CacheProvider
import io.seqera.wave.service.persistence.WaveBuildRecord
diff --git a/src/main/groovy/io/seqera/wave/service/cache/AbstractCacheStore.groovy b/src/main/groovy/io/seqera/wave/service/cache/AbstractCacheStore.groovy
index b78e4f535..e1b142766 100644
--- a/src/main/groovy/io/seqera/wave/service/cache/AbstractCacheStore.groovy
+++ b/src/main/groovy/io/seqera/wave/service/cache/AbstractCacheStore.groovy
@@ -28,7 +28,7 @@ import io.seqera.wave.service.cache.impl.CacheProvider
*
* @author Paolo Di Tommaso
*/
-abstract class AbstractCacheStore implements CacheStore, BiCacheStore {
+abstract class AbstractCacheStore implements CacheStore {
private EncodingStrategy encodingStrategy
@@ -101,25 +101,4 @@ abstract class AbstractCacheStore implements CacheStore, BiCacheSto
delegate.clear()
}
- @Override
- void biPut(String key, V value, Duration ttl) {
- delegate.biPut(key0(key), serialize(value), ttl)
- }
-
- @Override
- void biRemove(String key) {
- delegate.biRemove(key0(key))
- }
-
- @Override
- Set biKeysFor(V value) {
- final keys = delegate.biKeysFor(serialize(value))
- return keys.collect( (it) -> it.replace(getPrefix(),'') )
- }
-
- @Override
- String biKeyFind(V value, boolean sorted) {
- final result = delegate.biKeyFind(serialize(value), sorted)
- result ? result.replace(getPrefix(),'') : null
- }
}
diff --git a/src/main/groovy/io/seqera/wave/service/cache/BiCacheStore.groovy b/src/main/groovy/io/seqera/wave/service/cache/BiCacheStore.groovy
deleted file mode 100644
index 546c2166d..000000000
--- a/src/main/groovy/io/seqera/wave/service/cache/BiCacheStore.groovy
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Wave, containers provisioning service
- * Copyright (c) 2023-2024, Seqera Labs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package io.seqera.wave.service.cache
-
-import java.time.Duration
-
-/**
- * A cache store implementing a bi-direction key-value access,
- * it allows retrieving all keys for a given value in time O(2)
- *
- * @author Paolo Di Tommaso
- */
-interface BiCacheStore {
-
- /**
- * Add a bi-directional key-value
- *
- * @param key The entry key
- * @param value The entry value
- * @param ttl The entry time-to-live.
- */
- void biPut(K key, V value, Duration ttl)
-
- /**
- * Remove an entry for the given value.
- *
- * @param key The key of entry to be removed
- */
- void biRemove(K key)
-
- /**
- * Get all key for the given value.
- *
- * @param value The value for which find corresponding keys
- * @return A set of keys associated with the specified value or an empty set otherwise.
- */
- Set biKeysFor(V value)
-
- /**
- * Find a key in the cache for the given value.
- *
- * @param value The value for which find corresponding key
- * @param sorted When true, the list of keys is sorted before getting the first value
- * @return A key associated with the specified value or null if not key is found
- */
- K biKeyFind(V value, boolean sorted)
-
-}
diff --git a/src/main/groovy/io/seqera/wave/service/cache/impl/CacheProvider.groovy b/src/main/groovy/io/seqera/wave/service/cache/impl/CacheProvider.groovy
index 3b8dcb80a..0e458c75b 100644
--- a/src/main/groovy/io/seqera/wave/service/cache/impl/CacheProvider.groovy
+++ b/src/main/groovy/io/seqera/wave/service/cache/impl/CacheProvider.groovy
@@ -18,7 +18,6 @@
package io.seqera.wave.service.cache.impl
-import io.seqera.wave.service.cache.BiCacheStore
import io.seqera.wave.service.cache.CacheStore
/**
@@ -26,5 +25,5 @@ import io.seqera.wave.service.cache.CacheStore
*
* @author Paolo Di Tommaso
*/
-interface CacheProvider extends CacheStore, BiCacheStore {
+interface CacheProvider extends CacheStore {
}
diff --git a/src/main/groovy/io/seqera/wave/service/cache/impl/LocalCacheProvider.groovy b/src/main/groovy/io/seqera/wave/service/cache/impl/LocalCacheProvider.groovy
index 09f0c0cfa..0659f7335 100644
--- a/src/main/groovy/io/seqera/wave/service/cache/impl/LocalCacheProvider.groovy
+++ b/src/main/groovy/io/seqera/wave/service/cache/impl/LocalCacheProvider.groovy
@@ -99,57 +99,4 @@ class LocalCacheProvider implements CacheProvider {
store.clear()
}
- // =============== bi-cache store implementation ===============
-
- private Map> index = new HashMap<>()
-
- @Override
- void biPut(String key, String value, Duration ttl) {
- synchronized (this) {
- this.put(key, value, ttl)
- final id = value.hashCode()
- def set = index.get(id)
- if( set==null ) {
- set=new HashSet()
- index.put(id, set)
- }
- set.add(key)
- }
- }
-
- @Override
- void biRemove(String key) {
- synchronized (this) {
- final entry = store.remove(key)
- if( !entry )
- return
- final id = entry.value.hashCode()
- final set = index.get(id)
- if( set ) {
- set.remove(key)
- }
- }
- }
-
- @Override
- Set biKeysFor(String value) {
- final id = value.hashCode()
- return index.get(id) ?: Set.of()
- }
-
- String biKeyFind(String value, boolean sorted) {
- final id = value.hashCode()
- final list = biKeysFor(value).toList()
- final keys = sorted ? list.toSorted() : list.shuffled()
- final itr = keys.iterator()
- while( itr.hasNext() ) {
- final result = itr.next()
- // verify the key still exists
- if( get(result)!=null )
- return result
- // if not exist, remove it from the set
- index.get(id)?.remove(result)
- }
- return null
- }
}
diff --git a/src/main/groovy/io/seqera/wave/service/cache/impl/RedisCacheProvider.groovy b/src/main/groovy/io/seqera/wave/service/cache/impl/RedisCacheProvider.groovy
index e597a96f8..a551f5083 100644
--- a/src/main/groovy/io/seqera/wave/service/cache/impl/RedisCacheProvider.groovy
+++ b/src/main/groovy/io/seqera/wave/service/cache/impl/RedisCacheProvider.groovy
@@ -24,7 +24,6 @@ import groovy.transform.CompileStatic
import io.micronaut.context.annotation.Requires
import jakarta.inject.Inject
import jakarta.inject.Singleton
-import org.apache.commons.codec.digest.DigestUtils
import redis.clients.jedis.Jedis
import redis.clients.jedis.JedisPool
import redis.clients.jedis.params.SetParams
@@ -90,58 +89,4 @@ class RedisCacheProvider implements CacheProvider {
}
}
- // =============== bi-cache store implementation ===============
-
- @Override
- void biPut(String key, String value, Duration ttl) {
- final id = DigestUtils.sha256Hex(value)
- try( Jedis conn=pool.getResource() ) {
- final params = new SetParams().nx().ex(ttl.toSeconds())
- final tx = conn.multi()
- tx.set(key, value, params)
- tx.sadd(id, key)
- tx.exec()
- }
- }
-
- @Override
- void biRemove(String key) {
- try( Jedis conn=pool.getResource() ) {
- final value = conn.get(key)
- final tx = conn.multi()
- tx.del(key)
- if( value ) {
- final id = DigestUtils.sha256Hex(value)
- tx.srem(id, key)
- }
- tx.exec()
- }
- }
-
- @Override
- Set biKeysFor(String value) {
- final id = DigestUtils.sha256Hex(value)
- try( Jedis conn=pool.getResource() ) {
- return conn.smembers(id)
- }
- }
-
- @Override
- String biKeyFind(String value, boolean sorted) {
- final id = DigestUtils.sha256Hex(value)
- final list = biKeysFor(value).toList()
- final keys = sorted ? list.toSorted() : list.shuffled()
- final itr = keys.iterator()
- while( itr.hasNext() ) {
- final key = itr.next()
- // verify the key still exists
- if( get(key)!=null )
- return key
- // if the key is not found, remove it from the set
- try( Jedis conn=pool.getResource() ) {
- conn.srem(id, key)
- }
- }
- return null
- }
}
diff --git a/src/main/groovy/io/seqera/wave/service/k8s/K8sService.groovy b/src/main/groovy/io/seqera/wave/service/k8s/K8sService.groovy
index 6817caffd..bb042d86a 100644
--- a/src/main/groovy/io/seqera/wave/service/k8s/K8sService.groovy
+++ b/src/main/groovy/io/seqera/wave/service/k8s/K8sService.groovy
@@ -26,7 +26,6 @@ import io.kubernetes.client.openapi.models.V1Pod
import io.kubernetes.client.openapi.models.V1PodList
import io.seqera.wave.configuration.BlobCacheConfig
import io.seqera.wave.configuration.ScanConfig
-import io.seqera.wave.configuration.SpackConfig
/**
* Defines Kubernetes operations
*
@@ -43,7 +42,7 @@ interface K8sService {
void deletePod(String name)
@Deprecated
- V1Pod buildContainer(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, SpackConfig spackConfig, Map nodeSelector)
+ V1Pod buildContainer(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, Map nodeSelector)
@Deprecated
V1Pod scanContainer(String name, String containerImage, List args, Path workDir, Path creds, ScanConfig scanConfig, Map nodeSelector)
@@ -65,7 +64,7 @@ interface K8sService {
V1Job launchTransferJob(String name, String containerImage, List args, BlobCacheConfig blobConfig)
- V1Job launchBuildJob(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, SpackConfig spackConfig, Map nodeSelector)
+ V1Job launchBuildJob(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, Map nodeSelector)
V1Job launchScanJob(String name, String containerImage, List args, Path workDir, Path creds, ScanConfig scanConfig, Map nodeSelector)
diff --git a/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy b/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy
index 77fe61b6b..cad5ec9ea 100644
--- a/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy
+++ b/src/main/groovy/io/seqera/wave/service/k8s/K8sServiceImpl.groovy
@@ -47,7 +47,6 @@ import io.micronaut.core.annotation.Nullable
import io.seqera.wave.configuration.BlobCacheConfig
import io.seqera.wave.configuration.BuildConfig
import io.seqera.wave.configuration.ScanConfig
-import io.seqera.wave.configuration.SpackConfig
import io.seqera.wave.core.ContainerPlatform
import io.seqera.wave.service.scan.Trivy
import jakarta.inject.Inject
@@ -98,9 +97,6 @@ class K8sServiceImpl implements K8sService {
@Nullable
private String requestsMemory
- @Inject
- private SpackConfig spackConfig
-
@Inject
private K8sClient k8sClient
@@ -300,27 +296,6 @@ class K8sServiceImpl implements K8sService {
.readOnly(true)
}
- protected V1VolumeMount mountSpackCacheDir(Path spackCacheDir, String storageMountPath, String containerPath) {
- final rel = Path.of(storageMountPath).relativize(spackCacheDir).toString()
- if( !rel || rel.startsWith('../') )
- throw new IllegalArgumentException("Spack cacheDirectory '$spackCacheDir' must be a sub-directory of storage path '$storageMountPath'")
- return new V1VolumeMount()
- .name('build-data')
- .mountPath(containerPath)
- .subPath(rel)
- }
-
- protected V1VolumeMount mountSpackSecretFile(Path secretFile, String storageMountPath, String containerPath) {
- final rel = Path.of(storageMountPath).relativize(secretFile).toString()
- if( !rel || rel.startsWith('../') )
- throw new IllegalArgumentException("Spack secretKeyFile '$secretFile' must be a sub-directory of storage path '$storageMountPath'")
- return new V1VolumeMount()
- .name('build-data')
- .readOnly(true)
- .mountPath(containerPath)
- .subPath(rel)
- }
-
protected V1VolumeMount mountScanCacheDir(Path scanCacheDir, String storageMountPath) {
final rel = Path.of(storageMountPath).relativize(scanCacheDir).toString()
if( !rel || rel.startsWith('../') )
@@ -349,14 +324,14 @@ class K8sServiceImpl implements K8sService {
*/
@Override
@Deprecated
- V1Pod buildContainer(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, SpackConfig spackConfig, Map nodeSelector) {
- final spec = buildSpec(name, containerImage, args, workDir, creds, timeout, spackConfig, nodeSelector)
+ V1Pod buildContainer(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, Map nodeSelector) {
+ final spec = buildSpec(name, containerImage, args, workDir, creds, timeout, nodeSelector)
return k8sClient
.coreV1Api()
.createNamespacedPod(namespace, spec, null, null, null,null)
}
- V1Pod buildSpec(String name, String containerImage, List args, Path workDir, Path credsFile, Duration timeout, SpackConfig spackConfig, Map nodeSelector) {
+ V1Pod buildSpec(String name, String containerImage, List args, Path workDir, Path credsFile, Duration timeout, Map nodeSelector) {
// dirty dependency to avoid introducing another parameter
final singularity = containerImage.contains('singularity')
@@ -379,10 +354,6 @@ class K8sServiceImpl implements K8sService {
}
}
- if( spackConfig ) {
- mounts.add(mountSpackSecretFile(spackConfig.secretKeyFile, storageMountPath, spackConfig.secretMountPath))
- }
-
V1PodBuilder builder = new V1PodBuilder()
//metadata section
@@ -670,14 +641,14 @@ class K8sServiceImpl implements K8sService {
* The {@link V1Pod} description the submitted pod
*/
@Override
- V1Job launchBuildJob(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, SpackConfig spackConfig, Map nodeSelector) {
- final spec = buildJobSpec(name, containerImage, args, workDir, creds, timeout, spackConfig, nodeSelector)
+ V1Job launchBuildJob(String name, String containerImage, List args, Path workDir, Path creds, Duration timeout, Map nodeSelector) {
+ final spec = buildJobSpec(name, containerImage, args, workDir, creds, timeout, nodeSelector)
return k8sClient
.batchV1Api()
.createNamespacedJob(namespace, spec, null, null, null,null)
}
- V1Job buildJobSpec(String name, String containerImage, List args, Path workDir, Path credsFile, Duration timeout, SpackConfig spackConfig, Map nodeSelector) {
+ V1Job buildJobSpec(String name, String containerImage, List args, Path workDir, Path credsFile, Duration timeout, Map nodeSelector) {
// dirty dependency to avoid introducing another parameter
final singularity = containerImage.contains('singularity')
@@ -693,10 +664,6 @@ class K8sServiceImpl implements K8sService {
mounts.add(0, mountHostPath(credsFile, storageMountPath, '/home/user/.docker/config.json'))
}
- if( spackConfig ) {
- mounts.add(mountSpackSecretFile(spackConfig.secretKeyFile, storageMountPath, spackConfig.secretMountPath))
- }
-
V1JobBuilder builder = new V1JobBuilder()
//metadata section
diff --git a/src/main/groovy/io/seqera/wave/service/mail/impl/MailServiceImpl.groovy b/src/main/groovy/io/seqera/wave/service/mail/impl/MailServiceImpl.groovy
index 6e73804aa..259183d25 100644
--- a/src/main/groovy/io/seqera/wave/service/mail/impl/MailServiceImpl.groovy
+++ b/src/main/groovy/io/seqera/wave/service/mail/impl/MailServiceImpl.groovy
@@ -97,7 +97,6 @@ class MailServiceImpl implements MailService {
binding.build_platform = req.platform
binding.build_containerfile = req.containerFile ?: '-'
binding.build_condafile = req.condaFile
- binding.build_spackfile = req.spackFile
binding.build_digest = result.digest ?: '-'
binding.put('build_log_data', result.logs)
binding.build_url = "$serverUrl/view/builds/${result.id}"
diff --git a/src/main/groovy/io/seqera/wave/service/persistence/WaveBuildRecord.groovy b/src/main/groovy/io/seqera/wave/service/persistence/WaveBuildRecord.groovy
index 10107f5d0..ba5225b34 100644
--- a/src/main/groovy/io/seqera/wave/service/persistence/WaveBuildRecord.groovy
+++ b/src/main/groovy/io/seqera/wave/service/persistence/WaveBuildRecord.groovy
@@ -42,7 +42,6 @@ class WaveBuildRecord {
String buildId
String dockerFile
String condaFile
- String spackFile
String targetImage
String userName
String userEmail
@@ -66,7 +65,6 @@ class WaveBuildRecord {
buildId: event.request.buildId,
dockerFile: event.request.containerFile,
condaFile: event.request.condaFile,
- spackFile: event.request.spackFile,
targetImage: event.request.targetImage,
userName: event.request.identity.user?.userName,
userEmail: event.request.identity.user?.email,
diff --git a/src/main/groovy/io/seqera/wave/util/ContainerHelper.groovy b/src/main/groovy/io/seqera/wave/util/ContainerHelper.groovy
index 39dd5ae35..ae90a0578 100644
--- a/src/main/groovy/io/seqera/wave/util/ContainerHelper.groovy
+++ b/src/main/groovy/io/seqera/wave/util/ContainerHelper.groovy
@@ -27,7 +27,6 @@ import io.seqera.wave.api.PackagesSpec
import io.seqera.wave.api.SubmitContainerTokenRequest
import io.seqera.wave.api.SubmitContainerTokenResponse
import io.seqera.wave.config.CondaOpts
-import io.seqera.wave.config.SpackOpts
import io.seqera.wave.core.ContainerPlatform
import io.seqera.wave.exception.BadRequestException
import io.seqera.wave.service.ContainerRequestData
@@ -35,16 +34,12 @@ import io.seqera.wave.service.builder.BuildFormat
import io.seqera.wave.service.token.TokenData
import org.yaml.snakeyaml.Yaml
import static io.seqera.wave.service.builder.BuildFormat.SINGULARITY
-import static io.seqera.wave.util.DockerHelper.addPackagesToSpackYaml
import static io.seqera.wave.util.DockerHelper.condaEnvironmentToCondaYaml
import static io.seqera.wave.util.DockerHelper.condaFileToDockerFile
import static io.seqera.wave.util.DockerHelper.condaFileToSingularityFile
import static io.seqera.wave.util.DockerHelper.condaPackagesToCondaYaml
import static io.seqera.wave.util.DockerHelper.condaPackagesToDockerFile
import static io.seqera.wave.util.DockerHelper.condaPackagesToSingularityFile
-import static io.seqera.wave.util.DockerHelper.spackFileToDockerFile
-import static io.seqera.wave.util.DockerHelper.spackFileToSingularityFile
-import static io.seqera.wave.util.DockerHelper.spackPackagesToSpackYaml
/**
* Container helper methods
*
@@ -82,16 +77,7 @@ class ContainerHelper {
return result
}
- if( spec.type == PackagesSpec.Type.SPACK ) {
- if( !spec.spackOpts )
- spec.spackOpts = new SpackOpts()
- final result = formatSingularity
- ? spackFileToSingularityFile(spec.spackOpts)
- : spackFileToDockerFile(spec.spackOpts)
- return result
- }
-
- throw new IllegalArgumentException("Unexpected packages spec type: $spec.type")
+ throw new BadRequestException("Unexpected packages spec type: $spec.type")
}
static String condaFileFromRequest(SubmitContainerTokenRequest req) {
@@ -129,26 +115,6 @@ class ContainerHelper {
return result[0]
}
- static String spackFileFromRequest(SubmitContainerTokenRequest req) {
- if( !req.packages )
- return decodeBase64OrFail(req.spackFile,'spackFile')
-
- if( req.packages.type != PackagesSpec.Type.SPACK )
- return null
-
- if( req.packages.environment ) {
- final decoded = decodeBase64OrFail(req.packages.environment,'packages.envFile')
- return addPackagesToSpackYaml(decoded, req.packages.spackOpts)
- }
-
- if( req.packages.entries ) {
- final String packages = req.packages.entries.join(' ')
- return spackPackagesToSpackYaml(packages, req.packages.spackOpts)
- }
-
- return null
- }
-
static String decodeBase64OrFail(String value, String field) {
if( !value )
return null
@@ -268,56 +234,7 @@ class ContainerHelper {
return new Tuple2(parts[0], parts[1])
}
- static NameVersionPair guessSpackRecipeName(String spackFileContent, boolean split=false) {
- if( !spackFileContent )
- return null
- try {
- final yaml = new Yaml().load(spackFileContent) as Map
- final spack = yaml.spack as Map
-
- if( !spack ){
- throw new BadRequestException('Malformed Spack environment file - missing "spack:" section')
- }
- if( !spack.specs ){
- throw new BadRequestException('Malformed Spack environment file - missing "spack.specs:" section')
- }
-
- if( spack.specs instanceof List ) {
- final LinkedHashSet result = new LinkedHashSet()
- final LinkedHashSet versions = new LinkedHashSet()
- for( String it : spack.specs ) {
- final p = it.indexOf(' ')
- // remove everything after the first blank because they are supposed package directives
- if( p!=-1 )
- it = it.substring(0,p)
- if( split ) {
- final pair = splitVersion(it, '@')
- it = pair.v1
- versions.add(pair.v2)
- }
- else {
- // replaces '@' version separator with `-`
- it = it.replace('@','-')
- }
- if( it )
- result.add(it)
- }
- return split
- ? new NameVersionPair(result, versions)
- : new NameVersionPair(result)
- }
- return null
- }
- catch (BadRequestException e) {
- throw e
- }
- catch (Throwable e) {
- log.warn "Unable to infer spack recipe name - cause: ${e.message}", e
- return null
- }
- }
-
- static String makeTargetImage(BuildFormat format, String repo, String id, @Nullable String condaFile, @Nullable String spackFile, @Nullable ImageNameStrategy nameStrategy) {
+ static String makeTargetImage(BuildFormat format, String repo, String id, @Nullable String condaFile, @Nullable ImageNameStrategy nameStrategy) {
assert id, "Argument 'id' cannot be null or empty"
assert repo, "Argument 'repo' cannot be null or empty"
assert format, "Argument 'format' cannot be null"
@@ -328,9 +245,6 @@ class ContainerHelper {
if( condaFile && (tools=guessCondaRecipeName(condaFile,false)) ) {
tag = "${normaliseTag(tools.qualifiedNames())}--${id}"
}
- else if( spackFile && (tools=guessSpackRecipeName(spackFile,false)) ) {
- tag = "${normaliseTag(tools.qualifiedNames())}--${id}"
- }
}
else if( nameStrategy==ImageNameStrategy.imageSuffix ) {
if( condaFile && (tools=guessCondaRecipeName(condaFile,true)) ) {
@@ -338,11 +252,6 @@ class ContainerHelper {
if( tools.versions?.size()==1 && tools.versions[0] )
tag = "${normaliseTag(tools.versions[0])}--${id}"
}
- else if( spackFile && (tools=guessSpackRecipeName(spackFile, true)) ) {
- repo = StringUtils.pathConcat(repo, normaliseName(tools.friendlyNames()))
- if( tools.versions?.size()==1 && tools.versions[0] )
- tag = "${normaliseTag(tools.versions[0])}--${id}"
- }
}
else if( nameStrategy!=ImageNameStrategy.none ) {
throw new BadRequestException("Unsupported image naming strategy: '${nameStrategy}'")
@@ -387,13 +296,12 @@ class ContainerHelper {
value ? normalise0(value.toLowerCase(), maxLength, /[^a-z0-9_.\-\/]/) : null
}
- static String makeContainerId(String containerFile, String condaFile, String spackFile, ContainerPlatform platform, String repository, BuildContext buildContext) {
+ static String makeContainerId(String containerFile, String condaFile, ContainerPlatform platform, String repository, BuildContext buildContext) {
final attrs = new LinkedHashMap(10)
attrs.containerFile = containerFile
attrs.condaFile = condaFile
attrs.platform = platform?.toString()
attrs.repository = repository
- if( spackFile ) attrs.spackFile = spackFile
if( buildContext ) attrs.buildContext = buildContext.tarDigest
return RegHelper.sipHash(attrs)
}
diff --git a/src/main/groovy/io/seqera/wave/util/SpackHelper.groovy b/src/main/groovy/io/seqera/wave/util/SpackHelper.groovy
deleted file mode 100644
index 82a324a98..000000000
--- a/src/main/groovy/io/seqera/wave/util/SpackHelper.groovy
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Wave, containers provisioning service
- * Copyright (c) 2023-2024, Seqera Labs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package io.seqera.wave.util
-
-
-import groovy.transform.CompileStatic
-import io.seqera.wave.core.ContainerPlatform
-import io.seqera.wave.service.builder.BuildFormat
-
-/**
- * Helper class for Spack package manager
- *
- * @author Paolo Di Tommaso
- */
-@CompileStatic
-@Deprecated
-class SpackHelper {
-
- static String builderDockerTemplate() {
- SpackHelper.class
- .getResourceAsStream('/io/seqera/wave/spack/spack-builder-dockerfile.txt')
- .getText()
- }
-
- static String builderSingularityTemplate() {
- SpackHelper.class
- .getResourceAsStream('/io/seqera/wave/spack/spack-builder-singularityfile.txt')
- .getText()
- }
-
- static String prependBuilderTemplate(String dockerContent, BuildFormat buildFormat) {
- if(buildFormat == BuildFormat.SINGULARITY){
- return builderSingularityTemplate() + dockerContent
- }
- else if( buildFormat == BuildFormat.DOCKER ) {
- return builderDockerTemplate() + dockerContent
- }
- else
- 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")
- }
-
-}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 297fe0279..f9dc8c18f 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -4,8 +4,6 @@ wave:
enabled: true
build:
workspace: 'build-workspace'
- spack:
- cacheDirectory: 'spack-cache'
metrics:
enabled: true
accounts:
diff --git a/src/main/resources/io/seqera/wave/build-notification.html b/src/main/resources/io/seqera/wave/build-notification.html
index 61d14fb04..0c3a96c3a 100644
--- a/src/main/resources/io/seqera/wave/build-notification.html
+++ b/src/main/resources/io/seqera/wave/build-notification.html
@@ -111,11 +111,6 @@ Conda file
${build_condafile}
<% } %>
- <% if (build_spackfile) { %>
- Spack file
- ${build_spackfile}
- <% } %>
-
Build logs
${build_log_data}
diff --git a/src/main/resources/io/seqera/wave/build-view.hbs b/src/main/resources/io/seqera/wave/build-view.hbs
index acceacc55..821050224 100644
--- a/src/main/resources/io/seqera/wave/build-view.hbs
+++ b/src/main/resources/io/seqera/wave/build-view.hbs
@@ -127,11 +127,6 @@
{{build_condafile}}
{{/if}}
- {{#if build_spackfile}}
- Spack file
- {{build_spackfile}}
- {{/if}}
-
{{#if build_log_data}}
Build logs
{{build_log_data}}
diff --git a/src/main/resources/io/seqera/wave/spack/spack-builder-dockerfile.txt b/src/main/resources/io/seqera/wave/spack/spack-builder-dockerfile.txt
deleted file mode 100644
index 5637b1533..000000000
--- a/src/main/resources/io/seqera/wave/spack/spack-builder-dockerfile.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-# Builder image
-FROM {{spack_builder_image}} as builder
-COPY spack.yaml /opt/spack-env/spack.yaml
-
-# Assume the values from the environment
-ARG AWS_STS_REGIONAL_ENDPOINTS
-ARG AWS_REGION
-ARG AWS_DEFAULT_REGION
-ARG AWS_ROLE_ARN
-ARG AWS_WEB_IDENTITY_TOKEN_FILE
-
-ENV \
- AWS_STS_REGIONAL_ENDPOINTS=${AWS_STS_REGIONAL_ENDPOINTS} \
- AWS_REGION=${AWS_REGION} \
- AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION} \
- AWS_ROLE_ARN=${AWS_ROLE_ARN} \
- AWS_WEB_IDENTITY_TOKEN_FILE=${AWS_WEB_IDENTITY_TOKEN_FILE}
-
-RUN mkdir -p /opt/spack-env \
-&& sed -i -e 's;compilers:;compilers::;' \
- -e 's;^ *flags: *{}; flags:\n cflags: -O3\n cxxflags: -O3\n fflags: -O3;' \
- /root/.spack/linux/compilers.yaml \
-&& cd /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}}] \
-&& printf " view: /opt/view\n" >> /opt/spack-env/spack.yaml
-
-# Install packages, clean afterward, finally strip binaries
-RUN cd /opt/spack-env \
-&& fingerprint="$(spack gpg trust {{spack_key_file}} 2>&1 | tee /dev/stderr | sed -nr "s/^gpg: key ([0-9A-F]{16}): secret key imported$/\1/p")" \
-&& spack mirror add seqera-spack {{spack_cache_bucket}} \
-&& spack mirror add binary_mirror https://binaries.spack.io/releases/v0.20 \
-&& spack buildcache keys --install --trust \
-&& spack -e . concretize -f \
-&& spack --env . install \
-&& spack -e . buildcache push --allow-root --key "$fingerprint" {{spack_cache_bucket}} \
-&& spack gc -y \
-&& ( find -L /opt/._view/* -type f -exec readlink -f '{}' \; | \
- xargs file -i | \
- grep 'charset=binary' | \
- grep 'x-executable\|x-archive\|x-sharedlib' | \
- awk -F: '{print $1}' | xargs strip -s ) || true
-
-RUN cd /opt/spack-env && \
- spack env activate --sh -d . >> /opt/spack-env/z10_spack_environment.sh && \
- original_view=$( cd /opt ; ls -1d ._view/* ) && \
- sed -i "s;/view/;/$original_view/;" /opt/spack-env/z10_spack_environment.sh && \
- echo "# Needed for Perl applications" >>/opt/spack-env/z10_spack_environment.sh && \
- echo "export PERL5LIB=$(eval ls -d /opt/._view/*/lib/5.*):$PERL5LIB" >>/opt/spack-env/z10_spack_environment.sh && \
- rm -rf /opt/view
-
diff --git a/src/main/resources/io/seqera/wave/spack/spack-builder-singularityfile.txt b/src/main/resources/io/seqera/wave/spack/spack-builder-singularityfile.txt
deleted file mode 100644
index 5500cd652..000000000
--- a/src/main/resources/io/seqera/wave/spack/spack-builder-singularityfile.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-Bootstrap: docker
-From: {{spack_builder_image}}
-Stage: build
-
-%setup
-cat < ${SINGULARITY_ROOTFS}/aws-env.sh
-export AWS_STS_REGIONAL_ENDPOINTS=${AWS_STS_REGIONAL_ENDPOINTS}
-export AWS_REGION=${AWS_REGION}
-export AWS_DEFAULT_REGION=${AWS_REGION}
-export AWS_ROLE_ARN=${AWS_ROLE_ARN}
-export AWS_WEB_IDENTITY_TOKEN_FILE=${AWS_WEB_IDENTITY_TOKEN_FILE}
-EOF
-
-%files
- {{wave_context_dir}}/spack.yaml /opt/spack-env/spack.yaml
- {{spack_key_file}} {{spack_key_file}}
- /var/run/secrets /var/run/secrets
-
-%post
- # import AWS environment
- . /aws-env.sh
-
- # Copy and modify spack.yaml
- sed -i -e 's;compilers:;compilers::;' \
- -e 's;^ *flags: *{}; flags:\n cflags: -O3\n cxxflags: -O3\n fflags: -O3;' \
- /root/.spack/linux/compilers.yaml
-
- # Set up Spack environment
- export PATH=/opt/spack/bin:$PATH
- cd /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}}]
- printf " view: /opt/view\n" >> /opt/spack-env/spack.yaml
-
- # Install packages, clean afterward, finally strip binaries
- fingerprint="$(spack gpg trust {{spack_key_file}} 2>&1 | tee /dev/stderr | sed -nr "s/^gpg: key ([0-9A-F]{16}): secret key imported$/\1/p")"
- spack mirror add seqera-spack {{spack_cache_bucket}}
- spack mirror add binary_mirror https://binaries.spack.io/releases/v0.20
- spack buildcache keys --install --trust
- spack -e . concretize -f
- spack --env . install
- spack -e . buildcache push --allow-root --key "$fingerprint" {{spack_cache_bucket}}
- spack gc -y
- ( find -L /opt/._view/* -type f -exec readlink -f '{}' \; | \
- xargs file -i | \
- grep 'charset=binary' | \
- grep 'x-executable\|x-archive\|x-sharedlib' | \
- awk -F: '{print $1}' | xargs strip -s ) || true
-
- # Set up environment variables
- spack env activate --sh -d . >> /opt/spack-env/z10_spack_environment.sh
- original_view=$( cd /opt ; ls -1d ._view/* )
- sed -i "s;/view/;/$original_view/;" /opt/spack-env/z10_spack_environment.sh
- echo "# Needed for Perl applications" >>/opt/spack-env/z10_spack_environment.sh
- echo "export PERL5LIB=$(set +f; ls -d /opt/._view/*/lib/5.*):\$PERL5LIB" >>/opt/spack-env/z10_spack_environment.sh
- rm -rf /opt/view
-
diff --git a/src/test/groovy/io/seqera/wave/controller/BuildConfigTest.groovy b/src/test/groovy/io/seqera/wave/controller/BuildConfigTest.groovy
index aacb51586..74d2db23d 100644
--- a/src/test/groovy/io/seqera/wave/controller/BuildConfigTest.groovy
+++ b/src/test/groovy/io/seqera/wave/controller/BuildConfigTest.groovy
@@ -56,7 +56,6 @@ class BuildConfigTest extends Specification {
config.singularityImage( ContainerPlatform.of('arm64') ) == 'bar'
}
-
@Unroll
def 'should validate build max duration' () {
given:
@@ -72,6 +71,5 @@ class BuildConfigTest extends Specification {
'xyz' | false | 5 | 10 | 5
'xtz' | true | 5 | 10 | 10 // <-- pick "trusted" because both "freeze" and "token" are provided
'xtz' | true | 20 | 10 | 20 // <-- pick "default" when it's greater than "trusted"
-
}
}
diff --git a/src/test/groovy/io/seqera/wave/controller/BuildControllerTest.groovy b/src/test/groovy/io/seqera/wave/controller/BuildControllerTest.groovy
index fc69fc7b2..5809d680e 100644
--- a/src/test/groovy/io/seqera/wave/controller/BuildControllerTest.groovy
+++ b/src/test/groovy/io/seqera/wave/controller/BuildControllerTest.groovy
@@ -75,8 +75,8 @@ class BuildControllerTest extends Specification {
final containerFile = 'FROM foo:latest'
final format = BuildFormat.DOCKER
final platform = ContainerPlatform.of('amd64')
- final containerId = ContainerHelper.makeContainerId(containerFile, null, null, platform, 'buildrepo', null)
- final targetImage = ContainerHelper.makeTargetImage(format, repo, containerId, null, null, null)
+ final containerId = ContainerHelper.makeContainerId(containerFile, null, platform, 'buildrepo', null)
+ final targetImage = ContainerHelper.makeTargetImage(format, repo, containerId, null, null)
final build = new BuildRequest(
containerId: containerId,
containerFile: containerFile,
diff --git a/src/test/groovy/io/seqera/wave/controller/ContainerControllerTest.groovy b/src/test/groovy/io/seqera/wave/controller/ContainerControllerTest.groovy
index 0d707d001..aaf737ab9 100644
--- a/src/test/groovy/io/seqera/wave/controller/ContainerControllerTest.groovy
+++ b/src/test/groovy/io/seqera/wave/controller/ContainerControllerTest.groovy
@@ -37,7 +37,6 @@ import io.seqera.wave.api.PackagesSpec
import io.seqera.wave.api.SubmitContainerTokenRequest
import io.seqera.wave.api.SubmitContainerTokenResponse
import io.seqera.wave.config.CondaOpts
-import io.seqera.wave.config.SpackOpts
import io.seqera.wave.configuration.BuildConfig
import io.seqera.wave.core.ContainerPlatform
import io.seqera.wave.core.RegistryProxyService
@@ -280,17 +279,6 @@ class ContainerControllerTest extends Specification {
build.targetImage == 'wave/build:c6dac2e544419f71'
build.platform == ContainerPlatform.of('arm64')
- when:
- submit = new SubmitContainerTokenRequest(containerFile: encode('FROM foo'), spackFile: encode('some::spack-recipe'), containerPlatform: 'arm64')
- build = controller.makeBuildRequest(submit, PlatformId.NULL, "")
- then:
- build.containerId =~ /b7d730d274d1e057/
- 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.platform == ContainerPlatform.of('arm64')
}
def 'should return a bad request exception when field is not encoded' () {
@@ -318,16 +306,6 @@ class ContainerControllerTest extends Specification {
e = thrown(BadRequestException)
e.message == "Invalid 'condaFile' attribute - make sure it encoded as a base64 string"
- // validate spackFile
- when:
- controller.makeBuildRequest(
- new SubmitContainerTokenRequest(containerFile: encode('FROM foo'), spackFile: 'spack@123'),
- Mock(PlatformId),
- null)
- then:
- e = thrown(BadRequestException)
- e.message == "Invalid 'spackFile' attribute - make sure it encoded as a base64 string"
-
}
def 'should add library prefix' () {
@@ -459,42 +437,6 @@ class ContainerControllerTest extends Specification {
}
}
- def 'should create response with spack packages' () {
- given:
- def dockerAuth = Mock(ContainerInspectServiceImpl)
- def freeze = new FreezeServiceImpl( inspectService: dockerAuth)
- def builder = Mock(ContainerBuildService)
- def proxyRegistry = Mock(RegistryProxyService)
- def addressResolver = Mock(HttpClientAddressResolver)
- def tokenService = Mock(ContainerTokenService)
- def persistence = Mock(PersistenceService)
- def controller = new ContainerController(freezeService: freeze, buildService: builder, dockerAuthService: dockerAuth,
- registryProxyService: proxyRegistry, buildConfig: buildConfig, inclusionService: Mock(ContainerInclusionService),
- addressResolver: addressResolver, tokenService: tokenService, persistenceService: persistence, serverUrl: 'https://wave.seqera.io')
-
- when:'packages with spack'
- def SPACK_OPTS = new SpackOpts([
- basePackages: 'foo bar',
- commands: ['run','--this','--that']
- ])
- def packages = new PackagesSpec(type: PackagesSpec.Type.SPACK, spackOpts: SPACK_OPTS)
- def req = new SubmitContainerTokenRequest(format: 'docker', packages: packages)
- def response = controller.handleRequest(null, req, new PlatformId(new User(id: 100), 10), true)
-
- then:
- 1 * builder.buildImage(_) >> new BuildTrack('build123', 'foo:1234', true)
- and:
- 1 * tokenService.computeToken(_) >> new TokenData('wavetoken123', Instant.now().plus(1, ChronoUnit.HOURS))
- and:
- response.status.code == 200
- verifyAll(response.body.get() as SubmitContainerTokenResponse) {
- targetImage == 'wave.seqera.io/wt/wavetoken123/library/foo:1234'
- buildId == 'build123'
- containerToken == 'wavetoken123'
- cached == true
- }
- }
-
def 'should throw BadRequestException when more than one artifact (container image, container file or packages) is provided in the request' () {
given:
def controller = new ContainerController(inclusionService: Mock(ContainerInclusionService), allowAnonymous: false)
diff --git a/src/test/groovy/io/seqera/wave/controller/ViewControllerTest.groovy b/src/test/groovy/io/seqera/wave/controller/ViewControllerTest.groovy
index d69aa8f5f..330edcff1 100644
--- a/src/test/groovy/io/seqera/wave/controller/ViewControllerTest.groovy
+++ b/src/test/groovy/io/seqera/wave/controller/ViewControllerTest.groovy
@@ -84,7 +84,6 @@ class ViewControllerTest extends Specification {
buildId: '12345',
dockerFile: 'FROM foo',
condaFile: 'conda::foo',
- spackFile: 'some-spack-recipe',
targetImage: 'docker.io/some:image',
userName: 'paolo',
userEmail: 'paolo@seqera.io',
@@ -110,7 +109,6 @@ class ViewControllerTest extends Specification {
binding.build_platform == 'linux/amd64'
binding.build_containerfile == 'FROM foo'
binding.build_condafile == 'conda::foo'
- binding.build_spackfile == 'some-spack-recipe'
binding.build_format == 'Docker'
binding.build_log_data == 'log content'
binding.build_log_truncated == false
@@ -146,7 +144,6 @@ class ViewControllerTest extends Specification {
response.body().contains('FROM docker.io/test:foo')
and:
!response.body().contains('Conda file')
- !response.body().contains('Spack file')
}
def 'should render a build page with conda file' () {
@@ -176,39 +173,6 @@ class ViewControllerTest extends Specification {
and:
response.body().contains('Conda file')
response.body().contains('conda::foo')
- and:
- !response.body().contains('Spack file')
- }
-
- def 'should render a build page with spack file' () {
- given:
- def record1 = new WaveBuildRecord(
- buildId: 'test',
- spackFile: 'foo/conda/recipe',
- targetImage: 'test',
- userName: 'test',
- userEmail: 'test',
- userId: 1,
- requestIp: '127.0.0.1',
- startTime: Instant.now(),
- duration: Duration.ofSeconds(1),
- exitStatus: 0 )
-
- when:
- persistenceService.saveBuild(record1)
- and:
- def request = HttpRequest.GET("/view/builds/${record1.buildId}")
- def response = client.toBlocking().exchange(request, String)
- then:
- response.body().contains(record1.buildId)
- and:
- response.body().contains('Container file')
- response.body().contains('-')
- and:
- !response.body().contains('Conda file')
- and:
- response.body().contains('Spack file')
- response.body().contains('foo/conda/recipe')
}
def 'should render container view page' () {
@@ -247,7 +211,7 @@ class ViewControllerTest extends Specification {
def 'should render inspect view'() {
when:
- def request = HttpRequest.GET('/view/inspects/ubuntu')
+ def request = HttpRequest.GET('/view/inspect?image=ubuntu')
def response = client.toBlocking().exchange(request, String)
then:
@@ -265,7 +229,6 @@ class ViewControllerTest extends Specification {
buildId: '12345',
dockerFile: 'FROM foo',
condaFile: 'conda::foo',
- spackFile: 'some-spack-recipe',
targetImage: 'docker.io/some:image',
userName: 'paolo',
userEmail: 'paolo@seqera.io',
@@ -290,7 +253,6 @@ class ViewControllerTest extends Specification {
binding.build_platform == 'linux/amd64'
binding.build_containerfile == 'FROM foo'
binding.build_condafile == 'conda::foo'
- binding.build_spackfile == 'some-spack-recipe'
binding.build_format == 'Docker'
binding.build_log_data == 'log content'
binding.build_log_truncated == false
@@ -308,7 +270,6 @@ class ViewControllerTest extends Specification {
buildId: '12345',
dockerFile: 'FROM foo',
condaFile: 'conda::foo',
- spackFile: 'some-spack-recipe',
targetImage: 'docker.io/some:image',
userName: 'paolo',
userEmail: 'paolo@seqera.io',
@@ -334,7 +295,6 @@ class ViewControllerTest extends Specification {
binding.build_platform == 'linux/amd64'
binding.build_containerfile == 'FROM foo'
binding.build_condafile == 'conda::foo'
- binding.build_spackfile == 'some-spack-recipe'
binding.build_format == 'Docker'
binding.build_log_data == 'log content'
binding.build_log_truncated == false
diff --git a/src/test/groovy/io/seqera/wave/encoder/MoshiEncodingStrategyTest.groovy b/src/test/groovy/io/seqera/wave/encoder/MoshiEncodingStrategyTest.groovy
index 9cee2c36f..361fa3c79 100644
--- a/src/test/groovy/io/seqera/wave/encoder/MoshiEncodingStrategyTest.groovy
+++ b/src/test/groovy/io/seqera/wave/encoder/MoshiEncodingStrategyTest.groovy
@@ -329,7 +329,6 @@ class MoshiEncodingStrategyTest extends Specification {
containerId: '12345',
containerFile: 'from foo',
condaFile: 'conda spec',
- spackFile: 'spack spec',
workspace: Path.of("/some/path"),
targetImage: 'docker.io/some:image:12345',
identity: PlatformId.NULL,
@@ -356,6 +355,21 @@ class MoshiEncodingStrategyTest extends Specification {
copy == record1
}
+ def 'should decode legacy record with spack config' () {
+ given:
+ def legacy = '{"buildId":"12345_1","condaFile":"conda spec","dockerFile":"from foo","duration":"3000000000","exitStatus":-1,"platform":"linux/amd64","requestIp":"1.2.3.4","scanId":"scan12345","spackFile":"spack spec","targetImage":"docker.io/some:image:12345"}\n'
+ and:
+ def encoder = new MoshiEncodeStrategy() { }
+
+ // verify decoding is OK when the payload contains `spackFile` not existing anymore in the WaveBuildRecord
+ when:
+ def rec = encoder.decode(legacy)
+ then:
+ rec.buildId == '12345_1'
+ rec.condaFile == 'conda spec'
+ rec.dockerFile == 'from foo'
+ }
+
def 'should encode and decode registry info' () {
given:
def encoder = new MoshiEncodeStrategy() { }
@@ -405,7 +419,6 @@ class MoshiEncodingStrategyTest extends Specification {
containerId: '12345',
containerFile: 'from foo',
condaFile: 'conda spec',
- spackFile: 'spack spec',
workspace: Path.of("/some/path"),
targetImage: 'docker.io/some:image:12345',
identity: PlatformId.NULL,
diff --git a/src/test/groovy/io/seqera/wave/ratelimit/BuildServiceRateLimitTest.groovy b/src/test/groovy/io/seqera/wave/ratelimit/BuildServiceRateLimitTest.groovy
index 6bff0952a..e8e05f867 100644
--- a/src/test/groovy/io/seqera/wave/ratelimit/BuildServiceRateLimitTest.groovy
+++ b/src/test/groovy/io/seqera/wave/ratelimit/BuildServiceRateLimitTest.groovy
@@ -72,8 +72,8 @@ class BuildServiceRateLimitTest extends Specification {
RUN echo hi > hello.txt
""".stripIndent()
and:
- def CONTAINER_ID = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def TARGET_IMAGE = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, CONTAINER_ID, null, null, null)
+ def CONTAINER_ID = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def TARGET_IMAGE = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, CONTAINER_ID, null, null)
def REQ = new BuildRequest(
containerId: CONTAINER_ID,
containerFile: dockerfile,
@@ -106,8 +106,8 @@ class BuildServiceRateLimitTest extends Specification {
RUN echo hi > hello.txt
""".stripIndent()
and:
- def CONTAINER_ID = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def TARGET_IMAGE = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, CONTAINER_ID, null, null, null)
+ def CONTAINER_ID = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def TARGET_IMAGE = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, CONTAINER_ID, null, null)
def REQ = new BuildRequest(
containerId: CONTAINER_ID,
containerFile: dockerfile,
diff --git a/src/test/groovy/io/seqera/wave/service/builder/BuildRequestTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/BuildRequestTest.groovy
index e5eaa2172..9959f7873 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/BuildRequestTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/BuildRequestTest.groovy
@@ -52,15 +52,14 @@ class BuildRequestTest extends Specification {
def CONTEXT = Mock(BuildContext)
def PLATFORM = ContainerPlatform.of('amd64')
def FORMAT = BuildFormat.DOCKER
- def CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, null, PLATFORM, BUILD_REPO, CONTEXT)
- def TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, null, null)
+ def CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, PLATFORM, BUILD_REPO, CONTEXT)
+ def TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, null)
when:
def req = new BuildRequest(
CONTAINER_ID,
CONTENT,
null,
- null,
PATH,
TARGET_IMAGE,
USER,
@@ -85,7 +84,6 @@ class BuildRequestTest extends Specification {
req.cacheRepository == CACHE_REPO
req.format == BuildFormat.DOCKER
req.condaFile == null
- req.spackFile == null
req.platform == ContainerPlatform.of('amd64')
req.configJson == '{"config":"json"}'
req.scanId == SCAN_ID
@@ -93,8 +91,6 @@ class BuildRequestTest extends Specification {
req.offsetId == OFFSET
req.containerConfig == CONFIG
req.buildContext == CONTEXT
- and:
- !req.isSpackBuild
// ==== provide a Conda recipe ====
when:
@@ -103,13 +99,12 @@ class BuildRequestTest extends Specification {
- samtools=1.0
'''
and:
- CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, CONDA_RECIPE, null, PLATFORM, BUILD_REPO, CONTEXT)
- TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, CONDA_RECIPE, null, null)
+ CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, CONDA_RECIPE, PLATFORM, BUILD_REPO, CONTEXT)
+ TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, CONDA_RECIPE, null)
req = new BuildRequest(
CONTAINER_ID,
CONTENT,
CONDA_RECIPE,
- null,
PATH,
TARGET_IMAGE,
USER,
@@ -128,24 +123,14 @@ class BuildRequestTest extends Specification {
req.containerId == '8026e3a63b5c863f'
req.targetImage == 'docker.io/wave:samtools-1.0--8026e3a63b5c863f'
req.condaFile == CONDA_RECIPE
- req.spackFile == null
- and:
- !req.isSpackBuild
-
- // ===== spack content ====
- def SPACK_RECIPE = '''\
- spack:
- specs: [bwa@0.7.15]
- '''
when:
- CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, SPACK_RECIPE, PLATFORM, BUILD_REPO, CONTEXT)
- TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, SPACK_RECIPE, null)
+ CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, PLATFORM, BUILD_REPO, CONTEXT)
+ TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, null)
req = new BuildRequest(
CONTAINER_ID,
CONTENT,
null,
- SPACK_RECIPE,
PATH,
TARGET_IMAGE,
USER,
@@ -161,12 +146,9 @@ class BuildRequestTest extends Specification {
TIMEOUT
)
then:
- req.containerId == '8726782b1d9bb8fb'
- req.targetImage == 'docker.io/wave:bwa-0.7.15--8726782b1d9bb8fb'
- req.spackFile == SPACK_RECIPE
+ req.containerId == '181ec22b26ae6d04'
+ req.targetImage == 'docker.io/wave:181ec22b26ae6d04'
req.condaFile == null
- and:
- req.isSpackBuild
}
def 'should create singularity build request'() {
@@ -183,15 +165,14 @@ class BuildRequestTest extends Specification {
def CONTEXT = Mock(BuildContext)
def PLATFORM = ContainerPlatform.of('amd64')
def FORMAT = BuildFormat.SINGULARITY
- def CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, null, PLATFORM, BUILD_REPO, CONTEXT)
- def TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, null, null)
+ def CONTAINER_ID = ContainerHelper.makeContainerId(CONTENT, null, PLATFORM, BUILD_REPO, CONTEXT)
+ def TARGET_IMAGE = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID, null, null)
when:
def req = new BuildRequest(
CONTAINER_ID,
CONTENT,
null,
- null,
PATH,
TARGET_IMAGE,
USER,
@@ -220,8 +201,6 @@ class BuildRequestTest extends Specification {
req.offsetId == OFFSET
req.containerConfig == CONFIG
req.buildContext == CONTEXT
- and:
- !req.isSpackBuild
}
@@ -238,28 +217,28 @@ class BuildRequestTest extends Specification {
def FOO_CONTENT = 'from foo'
def BAR_CONTENT = 'from bar'
and:
- def CONTAINER_ID1 = ContainerHelper.makeContainerId(FOO_CONTENT, null, null, PLATFORM, BUILD_REPO, null)
- def TARGET_IMAGE1 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID1, null, null, null)
- def req1 = new BuildRequest(CONTAINER_ID1, FOO_CONTENT, null, null, PATH, TARGET_IMAGE1, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def CONTAINER_ID1 = ContainerHelper.makeContainerId(FOO_CONTENT, null, PLATFORM, BUILD_REPO, null)
+ def TARGET_IMAGE1 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID1, null, null)
+ def req1 = new BuildRequest(CONTAINER_ID1, FOO_CONTENT, null, PATH, TARGET_IMAGE1, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
- def req2 = new BuildRequest(CONTAINER_ID1, FOO_CONTENT, null, null, PATH, TARGET_IMAGE1, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def req2 = new BuildRequest(CONTAINER_ID1, FOO_CONTENT, null, PATH, TARGET_IMAGE1, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
- def CONTAINER_ID3 = ContainerHelper.makeContainerId(BAR_CONTENT, null, null, PLATFORM, BUILD_REPO, null)
- def TARGET_IMAGE3 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID3, null, null, null)
- def req3 = new BuildRequest(CONTAINER_ID3, BAR_CONTENT, null, null, PATH, TARGET_IMAGE3, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def CONTAINER_ID3 = ContainerHelper.makeContainerId(BAR_CONTENT, null, PLATFORM, BUILD_REPO, null)
+ def TARGET_IMAGE3 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID3, null, null)
+ def req3 = new BuildRequest(CONTAINER_ID3, BAR_CONTENT, null, PATH, TARGET_IMAGE3, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
- def CONTAINER_ID4 = ContainerHelper.makeContainerId(BAR_CONTENT, CONDA_CONTENT, null, PLATFORM, BUILD_REPO, null)
- def TARGET_IMAGE4 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID4, CONDA_CONTENT, null, null)
- def req4 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, null, PATH, TARGET_IMAGE4, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def CONTAINER_ID4 = ContainerHelper.makeContainerId(BAR_CONTENT, CONDA_CONTENT, PLATFORM, BUILD_REPO, null)
+ def TARGET_IMAGE4 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID4, CONDA_CONTENT, null)
+ def req4 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, PATH, TARGET_IMAGE4, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
- def req5 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, null, PATH, TARGET_IMAGE4, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def req5 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, PATH, TARGET_IMAGE4, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
CONDA_CONTENT = 'salmon=1.2.5'
- def CONTAINER_ID6 = ContainerHelper.makeContainerId(BAR_CONTENT, CONDA_CONTENT, null, PLATFORM, BUILD_REPO, null)
- def TARGET_IMAGE6 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID6, CONDA_CONTENT, null, null)
- def req6 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, null, PATH, TARGET_IMAGE6, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
+ def CONTAINER_ID6 = ContainerHelper.makeContainerId(BAR_CONTENT, CONDA_CONTENT, PLATFORM, BUILD_REPO, null)
+ def TARGET_IMAGE6 = ContainerHelper.makeTargetImage(FORMAT, BUILD_REPO, CONTAINER_ID6, CONDA_CONTENT, null)
+ def req6 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, PATH, TARGET_IMAGE6, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', null, null, null, null, FORMAT, TIMEOUT)
and:
- def req7 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, null, PATH, TARGET_IMAGE6, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', "UTC+2", null, null, null, FORMAT, TIMEOUT)
+ def req7 = new BuildRequest(CONTAINER_ID4, BAR_CONTENT, CONDA_CONTENT, PATH, TARGET_IMAGE6, USER, PLATFORM, CACHE_REPO, "10.20.30.40", '{"config":"json"}', "UTC+2", null, null, null, FORMAT, TIMEOUT)
expect:
req1 == req2
diff --git a/src/test/groovy/io/seqera/wave/service/builder/BuildStrategyTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/BuildStrategyTest.groovy
index 8151c836f..fbab4a86c 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/BuildStrategyTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/BuildStrategyTest.groovy
@@ -128,13 +128,12 @@ class BuildStrategyTest extends Specification {
def content = 'FROM foo:latest'
def workspace = Path.of("some/path")
def buildrepo = 'foo.com/repo'
- def containerId = ContainerHelper.makeContainerId(content, null, null, ContainerPlatform.of('amd64'), buildrepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildrepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(content, null, ContainerPlatform.of('amd64'), buildrepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildrepo, containerId, null, null)
def build = new BuildRequest(
containerId,
content,
null,
- null,
workspace,
targetImage,
PlatformId.NULL,
diff --git a/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceLiveTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceLiveTest.groovy
index eae4f8c42..359e93043 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceLiveTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceLiveTest.groovy
@@ -76,8 +76,8 @@ class ContainerBuildServiceLiveTest extends Specification {
'''.stripIndent()
and:
def cfg = dockerAuthService.credentialsConfigJson(dockerFile, buildRepo, cacheRepo, Mock(PlatformId))
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -122,8 +122,8 @@ class ContainerBuildServiceLiveTest extends Specification {
'''.stripIndent()
and:
def cfg = dockerAuthService.credentialsConfigJson(dockerFile, buildRepo, null, Mock(PlatformId))
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -168,8 +168,8 @@ class ContainerBuildServiceLiveTest extends Specification {
and:
def buildRepo = "quay.io/pditommaso/wave-tests"
def cfg = dockerAuthService.credentialsConfigJson(dockerFile, buildRepo, null, Mock(PlatformId))
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('linux/arm64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('linux/arm64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -214,8 +214,8 @@ class ContainerBuildServiceLiveTest extends Specification {
and:
def duration = Duration.ofMinutes(1)
def cfg = dockerAuthService.credentialsConfigJson(dockerFile, buildRepo, null, Mock(PlatformId))
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -266,8 +266,8 @@ class ContainerBuildServiceLiveTest extends Specification {
and:
def duration = Duration.ofMinutes(1)
def cfg = dockerAuthService.credentialsConfigJson(dockerFile, buildRepo, null, Mock(PlatformId))
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
diff --git a/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceTest.groovy
index 7e0e6d647..21c05e66d 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/ContainerBuildServiceTest.groovy
@@ -40,7 +40,6 @@ import io.seqera.wave.auth.RegistryCredentialsProvider
import io.seqera.wave.auth.RegistryLookupService
import io.seqera.wave.configuration.BuildConfig
import io.seqera.wave.configuration.HttpClientConfig
-import io.seqera.wave.configuration.SpackConfig
import io.seqera.wave.core.ContainerPlatform
import io.seqera.wave.core.RegistryProxyService
import io.seqera.wave.service.builder.store.BuildRecordStore
@@ -56,7 +55,6 @@ import io.seqera.wave.test.TestHelper
import io.seqera.wave.tower.PlatformId
import io.seqera.wave.util.ContainerHelper
import io.seqera.wave.util.Packer
-import io.seqera.wave.util.SpackHelper
import io.seqera.wave.util.TemplateRenderer
import jakarta.inject.Inject
import jakarta.inject.Singleton
@@ -110,11 +108,9 @@ class ContainerBuildServiceTest extends Specification {
def buildRepo = buildConfig.defaultBuildRepository
def cacheRepo = buildConfig.defaultCacheRepository
and:
- def cfg = 'some credentials'
def dockerFile = '''
FROM busybox
RUN echo Hello > hello.txt
- RUN {{spack_cache_bucket}} {{spack_key_file}}
'''.stripIndent()
and:
def condaFile = '''
@@ -122,22 +118,13 @@ class ContainerBuildServiceTest extends Specification {
- salmon=1.6.0
'''
and:
- def spackFile = '''
- spack:
- specs: [bwa@0.7.15, salmon@1.1.1]
- concretizer: {unify: true, reuse: true}
- '''
- and:
- def spackConfig = new SpackConfig(cacheBucket: 's3://bucket/cache', secretMountPath: '/mnt/secret')
- def containerId = ContainerHelper.makeContainerId(dockerFile, condaFile, spackFile, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, condaFile, spackFile, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, condaFile, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, condaFile, null)
def req =
new BuildRequest(
containerId: containerId,
containerFile: dockerFile,
condaFile: condaFile,
- spackFile: spackFile,
- isSpackBuild: true,
workspace: folder,
targetImage: targetImage,
identity: Mock(PlatformId),
@@ -151,17 +138,17 @@ class ContainerBuildServiceTest extends Specification {
and:
def store = Mock(BuildStore)
def jobService = Mock(JobService)
- def builder = new ContainerBuildServiceImpl(buildStore: store, buildConfig: buildConfig, spackConfig:spackConfig, jobService: jobService)
+ def builder = new ContainerBuildServiceImpl(buildStore: store, buildConfig: buildConfig, jobService: jobService)
def RESPONSE = Mock(JobSpec)
-
+
when:
builder.launch(req)
+
then:
1 * jobService.launchBuild(req) >> RESPONSE
and:
- req.workDir.resolve('Containerfile').text == new TemplateRenderer().render(dockerFile, [spack_cache_bucket:'s3://bucket/cache', spack_key_file:'/mnt/secret'])
+ req.workDir.resolve('Containerfile').text == new TemplateRenderer().render(dockerFile, [:])
req.workDir.resolve('context/conda.yml').text == condaFile
- req.workDir.resolve('context/spack.yaml').text == spackFile
cleanup:
folder?.deleteDir()
@@ -172,11 +159,10 @@ class ContainerBuildServiceTest extends Specification {
def folder = Files.createTempDirectory('test')
def builder = new ContainerBuildServiceImpl()
def buildRepo = buildConfig.defaultBuildRepository
- def cacheRepo = buildConfig.defaultCacheRepository
and:
def dockerFile = 'FROM something; {{foo}}'
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -189,112 +175,16 @@ class ContainerBuildServiceTest extends Specification {
startTime: Instant.now()
)
.withBuildId('1')
- and:
- def spack = Mock(SpackConfig)
when:
- def result = builder.containerFile0(req, null, spack)
+ def result = builder.containerFile0(req, null)
then:
- 0* spack.getCacheMountPath() >> null
- 0* spack.getSecretMountPath() >> null
- 0* spack.getBuilderImage() >> null
- and:
result == 'FROM something; {{foo}}'
cleanup:
folder?.deleteDir()
}
- def 'should resolve docker file with spack config' () {
- given:
- def folder = Files.createTempDirectory('test')
- def builder = new ContainerBuildServiceImpl()
- and:
- def dockerFile = SpackHelper.builderDockerTemplate()
- def spackFile = 'some spack packages'
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, spackFile, ContainerPlatform.of('amd64'), 'buildRepo', null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'foo.com/repo', containerId, null, spackFile, null)
- def req = new BuildRequest(
- containerId: containerId,
- containerFile: dockerFile,
- spackFile: spackFile,
- isSpackBuild: true,
- workspace: folder,
- targetImage: targetImage,
- identity:Mock(PlatformId),
- platform: ContainerPlatform.of('amd64'),
- format: BuildFormat.DOCKER,
- startTime: Instant.now()
- )
- .withBuildId('1')
- and:
- def spack = Mock(SpackConfig)
-
- when:
- def result = builder.containerFile0(req, null, spack)
- then:
- 1* spack.getCacheBucket() >> 's3://bucket/cache'
- 1* spack.getSecretMountPath() >> '/mnt/key'
- 1* spack.getBuilderImage() >> 'spack-builder:2.0'
- 1* spack.getRunnerImage() >> 'ubuntu:22.04'
- and:
- result.contains('FROM spack-builder:2.0 as builder')
- result.contains('spack config add packages:all:target:[x86_64]')
- result.contains('spack mirror add seqera-spack s3://bucket/cache')
- result.contains('fingerprint="$(spack gpg trust /mnt/key 2>&1 | tee /dev/stderr | sed -nr "s/^gpg: key ([0-9A-F]{16}): secret key imported$/\\1/p")"')
-
- cleanup:
- folder?.deleteDir()
- }
-
- def 'should resolve singularity file with spack config' () {
- given:
- def folder = Files.createTempDirectory('test')
- def builder = new ContainerBuildServiceImpl()
- and:
- def context = Path.of('/some/context/dir')
- def dockerFile = SpackHelper.builderSingularityTemplate()
- def spackFile = 'some spack packages'
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, spackFile, ContainerPlatform.of('amd64'), 'buildRepo', null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.SINGULARITY, 'foo.com/repo', containerId, null, spackFile, null)
- def req =
- new BuildRequest(
- containerId: containerId,
- containerFile: dockerFile,
- spackFile: spackFile,
- isSpackBuild: true,
- workspace: folder,
- targetImage: targetImage,
- identity: Mock(PlatformId),
- platform: ContainerPlatform.of('amd64'),
- format: BuildFormat.SINGULARITY,
- startTime: Instant.now()
- )
-
- .withBuildId('1')
- and:
- def spack = Mock(SpackConfig)
-
- when:
- def result = builder.containerFile0(req, context, spack)
- then:
- 1* spack.getCacheBucket() >> 's3://bucket/cache'
- 1* spack.getSecretMountPath() >> '/mnt/key'
- 1* spack.getBuilderImage() >> 'spack-builder:2.0'
- 1* spack.getRunnerImage() >> 'ubuntu:22.04'
- and:
- result.contains('Bootstrap: docker\n' +
- 'From: spack-builder:2.0\n' +
- 'Stage: build')
- result.contains('spack config add packages:all:target:[x86_64]')
- result.contains('spack mirror add seqera-spack s3://bucket/cache')
- result.contains('fingerprint="$(spack gpg trust /mnt/key 2>&1 | tee /dev/stderr | sed -nr "s/^gpg: key ([0-9A-F]{16}): secret key imported$/\\1/p")"')
- result.contains('/some/context/dir/spack.yaml /opt/spack-env/spack.yaml')
-
- cleanup:
- folder?.deleteDir()
- }
-
def 'should replace context path' () {
given:
def folder = Path.of('/some/work/dir')
@@ -306,8 +196,8 @@ class ContainerBuildServiceTest extends Specification {
'''.stripIndent()
and:
def builder = new ContainerBuildServiceImpl()
- def containerId = ContainerHelper.makeContainerId(containerFile, null, null, ContainerPlatform.of('amd64'), 'buildRepo', null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.SINGULARITY, 'foo.com/repo', containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(containerFile, null, ContainerPlatform.of('amd64'), 'buildRepo', null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.SINGULARITY, 'foo.com/repo', containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -322,7 +212,7 @@ class ContainerBuildServiceTest extends Specification {
.withBuildId('1')
when:
- def result = builder.containerFile0(req, Path.of('/some/context/'), null)
+ def result = builder.containerFile0(req, Path.of('/some/context/'))
then:
result == '''\
BootStrap: docker
@@ -386,8 +276,8 @@ class ContainerBuildServiceTest extends Specification {
and:
def dockerFile = 'from foo'
def buildRepo = 'quay.io/org/name'
- def containerId = ContainerHelper.makeContainerId(dockerFile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
+ def containerId = ContainerHelper.makeContainerId(dockerFile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
def req =
new BuildRequest(
containerId: containerId,
@@ -420,7 +310,6 @@ class ContainerBuildServiceTest extends Specification {
containerId: 'container1234',
containerFile: 'test',
condaFile: 'test',
- spackFile: 'test',
workspace: Path.of("."),
targetImage: 'docker.io/my/repo:container1234',
identity: PlatformId.NULL,
@@ -452,7 +341,6 @@ class ContainerBuildServiceTest extends Specification {
containerId: 'container1234',
containerFile:'test',
condaFile: 'test',
- spackFile: 'test',
workspace: Path.of("."),
targetImage: 'docker.io/my/repo:container1234',
identity: PlatformId.NULL,
@@ -488,7 +376,6 @@ class ContainerBuildServiceTest extends Specification {
containerId: 'container1234',
containerFile: 'test',
condaFile: 'test',
- spackFile: 'test',
workspace: Path.of("."),
targetImage: 'docker.io/my/repo:container1234',
identity: PlatformId.NULL,
diff --git a/src/test/groovy/io/seqera/wave/service/builder/DockerBuildStrategyTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/DockerBuildStrategyTest.groovy
index 3294f88a0..52c4c1f8c 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/DockerBuildStrategyTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/DockerBuildStrategyTest.groovy
@@ -24,7 +24,6 @@ import java.nio.file.Path
import io.micronaut.context.ApplicationContext
import io.micronaut.test.extensions.spock.annotation.MicronautTest
-import io.seqera.wave.configuration.SpackConfig
import io.seqera.wave.core.ContainerPlatform
/**
*
@@ -35,17 +34,13 @@ class DockerBuildStrategyTest extends Specification {
def 'should get docker command' () {
given:
- def props = [
- 'wave.build.spack.secretKeyFile':'/host/spack/key',
- 'wave.build.spack.secretMountPath':'/opt/spack/key' ]
- def ctx = ApplicationContext.run(props)
+ def ctx = ApplicationContext.run()
and:
def service = ctx.getBean(DockerBuildStrategy)
- def spackConfig = ctx.getBean(SpackConfig)
and:
def work = Path.of('/work/foo')
when:
- def cmd = service.cmdForBuildkit('build-job-name', work, null, null, null)
+ def cmd = service.cmdForBuildkit('build-job-name', work, null, null)
then:
cmd == ['docker',
'run',
@@ -59,7 +54,7 @@ class DockerBuildStrategyTest extends Specification {
'moby/buildkit:v0.14.1-rootless']
when:
- cmd = service.cmdForBuildkit('build-job-name', work, Path.of('/foo/creds.json'), null, ContainerPlatform.of('arm64'))
+ cmd = service.cmdForBuildkit('build-job-name', work, Path.of('/foo/creds.json'), ContainerPlatform.of('arm64'))
then:
cmd == ['docker',
'run',
@@ -75,7 +70,7 @@ class DockerBuildStrategyTest extends Specification {
'moby/buildkit:v0.14.1-rootless']
when:
- cmd = service.cmdForBuildkit('build-job-name', work, Path.of('/foo/creds.json'), spackConfig, null)
+ cmd = service.cmdForBuildkit('build-job-name', work, Path.of('/foo/creds.json'), null)
then:
cmd == ['docker',
'run',
@@ -87,7 +82,6 @@ class DockerBuildStrategyTest extends Specification {
'--entrypoint',
'buildctl-daemonless.sh',
'-v', '/foo/creds.json:/home/user/.docker/config.json:ro',
- '-v', '/host/spack/key:/opt/spack/key:ro',
'moby/buildkit:v0.14.1-rootless']
cleanup:
@@ -146,13 +140,8 @@ class DockerBuildStrategyTest extends Specification {
def 'should get singularity build command' () {
given:
- def props = [
- 'wave.build.spack.secretKeyFile':'/host/spack/key',
- 'wave.build.spack.secretMountPath':'/opt/spack/key' ]
- def ctx = ApplicationContext.run(props)
+ def ctx = ApplicationContext.run()
def service = ctx.getBean(DockerBuildStrategy)
- SpackConfig spackConfig = ctx.getBean(SpackConfig)
- service.setSpackConfig(spackConfig)
and:
def creds = Path.of('/work/creds.json')
and:
@@ -161,8 +150,7 @@ class DockerBuildStrategyTest extends Specification {
platform: ContainerPlatform.of('linux/amd64'),
targetImage: 'oras://repo:d4869cc39b8d7d55',
cacheRepository: 'reg.io/wave/build/cache',
- format: BuildFormat.SINGULARITY,
- isSpackBuild: true )
+ format: BuildFormat.SINGULARITY )
when:
def cmd = service.buildCmd('build-job-name', req, creds)
then:
@@ -176,27 +164,21 @@ class DockerBuildStrategyTest extends Specification {
'-v', '/work/foo/d4869cc39b8d7d55:/work/foo/d4869cc39b8d7d55',
'-v', '/work/creds.json:/root/.singularity/docker-config.json:ro',
'-v', '/work/singularity-remote.yaml:/root/.singularity/remote.yaml:ro',
- '-v', '/host/spack/key:/opt/spack/key:ro',
'--platform', 'linux/amd64',
'quay.io/singularity/singularity:v3.11.4-slim',
'sh',
'-c',
'singularity build image.sif /work/foo/d4869cc39b8d7d55/Containerfile && singularity push image.sif oras://repo:d4869cc39b8d7d55'
]
-
+
cleanup:
ctx.close()
}
def 'should get singularity build command for arm64 architecture' () {
given:
- def props = [
- 'wave.build.spack.secretKeyFile':'/host/spack/key',
- 'wave.build.spack.secretMountPath':'/opt/spack/key' ]
- def ctx = ApplicationContext.run(props)
+ def ctx = ApplicationContext.run()
def service = ctx.getBean(DockerBuildStrategy)
- SpackConfig spackConfig = ctx.getBean(SpackConfig)
- service.setSpackConfig(spackConfig)
and:
def creds = Path.of('/work/creds.json')
and:
@@ -205,8 +187,7 @@ class DockerBuildStrategyTest extends Specification {
platform: ContainerPlatform.of('linux/arm64'),
targetImage: 'oras://repo:9c68af894bb2419c',
cacheRepository: 'reg.io/wave/build/cache',
- format: BuildFormat.SINGULARITY,
- isSpackBuild: true )
+ format: BuildFormat.SINGULARITY )
when:
def cmd = service.buildCmd('build-job-name', req, creds)
then:
@@ -220,7 +201,6 @@ class DockerBuildStrategyTest extends Specification {
'-v', '/work/foo/9c68af894bb2419c:/work/foo/9c68af894bb2419c',
'-v', '/work/creds.json:/root/.singularity/docker-config.json:ro',
'-v', '/work/singularity-remote.yaml:/root/.singularity/remote.yaml:ro',
- '-v', '/host/spack/key:/opt/spack/key:ro',
'--platform', 'linux/arm64',
'quay.io/singularity/singularity:v3.11.4-slim-arm64',
'sh',
diff --git a/src/test/groovy/io/seqera/wave/service/builder/FutureContainerBuildServiceTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/FutureContainerBuildServiceTest.groovy
index 957a32146..0904a7988 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/FutureContainerBuildServiceTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/FutureContainerBuildServiceTest.groovy
@@ -46,9 +46,9 @@ class FutureContainerBuildServiceTest extends Specification {
RUN echo 'hello' > hello.txt
""".stripIndent()
and:
- def containerId = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
- def req = new BuildRequest(containerId, dockerfile, null, null, folder, targetImage, Mock(PlatformId), ContainerPlatform.of('amd64'), cacheRepo, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
+ def containerId = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
+ def req = new BuildRequest(containerId, dockerfile, null, folder, targetImage, Mock(PlatformId), ContainerPlatform.of('amd64'), cacheRepo, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
def res = new BuildResult("", 0, "a fake build result in a test", Instant.now(), Duration.ofSeconds(3), 'abc')
and:
def buildStore = Mock(BuildStore)
@@ -81,9 +81,9 @@ class FutureContainerBuildServiceTest extends Specification {
RUN echo 'hello' > hello.txt
""".stripIndent()
and:
- def containerId = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), buildRepo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null, null)
- def req = new BuildRequest(containerId, dockerfile, null, null, folder, targetImage, Mock(PlatformId), ContainerPlatform.of('amd64'), cacheRepo, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
+ def containerId = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), buildRepo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, buildRepo, containerId, null, null)
+ def req = new BuildRequest(containerId, dockerfile, null, folder, targetImage, Mock(PlatformId), ContainerPlatform.of('amd64'), cacheRepo, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
def res = new BuildResult("", 1, "a fake build result in a test", Instant.now(), Duration.ofSeconds(3), 'abc')
and:
def buildStore = Mock(BuildStore)
diff --git a/src/test/groovy/io/seqera/wave/service/builder/KubeBuildStrategyTest.groovy b/src/test/groovy/io/seqera/wave/service/builder/KubeBuildStrategyTest.groovy
index 1b8ea51de..5e79c4824 100644
--- a/src/test/groovy/io/seqera/wave/service/builder/KubeBuildStrategyTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/builder/KubeBuildStrategyTest.groovy
@@ -68,22 +68,22 @@ class KubeBuildStrategyTest extends Specification {
def dockerfile = 'from foo'
when:
- def containerId = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), repo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, repo, containerId, null, null, null)
- def req = new BuildRequest(containerId, dockerfile, null, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
+ def containerId = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), repo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, repo, containerId, null, null)
+ def req = new BuildRequest(containerId, dockerfile, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
Files.createDirectories(req.workDir)
strategy.build('build-job-name', req)
then:
- 1 * k8sService.launchBuildJob(_, _, _, _, _, _, _, [service:'wave-build']) >> null
+ 1 * k8sService.launchBuildJob( _, _, _, _, _, _, [service:'wave-build']) >> null
when:
- def req2 = new BuildRequest(containerId, dockerfile, null, null, PATH, targetImage, USER, ContainerPlatform.of('arm64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
+ def req2 = new BuildRequest(containerId, dockerfile, null, PATH, targetImage, USER, ContainerPlatform.of('arm64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
Files.createDirectories(req2.workDir)
strategy.build('job-name', req2)
then:
- 1 * k8sService.launchBuildJob(_, _, _, _, _, _, _, [service:'wave-build-arm64']) >> null
+ 1 * k8sService.launchBuildJob( _, _, _, _, _, _, [service:'wave-build-arm64']) >> null
}
@@ -96,21 +96,21 @@ class KubeBuildStrategyTest extends Specification {
def dockerfile = 'from foo'
when:'getting docker with amd64 arch in build request'
- def containerId = ContainerHelper.makeContainerId(dockerfile, null, null, ContainerPlatform.of('amd64'), repo, null)
- def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, repo, containerId, null, null, null)
- def req = new BuildRequest(containerId, dockerfile, null, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
+ def containerId = ContainerHelper.makeContainerId(dockerfile, null, ContainerPlatform.of('amd64'), repo, null)
+ def targetImage = ContainerHelper.makeTargetImage(BuildFormat.DOCKER, repo, containerId, null, null)
+ def req = new BuildRequest(containerId, dockerfile, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{"config":"json"}', null,null , null, null, BuildFormat.DOCKER, Duration.ofMinutes(1)).withBuildId('1')
then: 'should return buildkit image'
strategy.getBuildImage(req) == 'moby/buildkit:v0.14.1-rootless'
when:'getting singularity with amd64 arch in build request'
- req = new BuildRequest(containerId, dockerfile, null, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.SINGULARITY,Duration.ofMinutes(1)).withBuildId('1')
+ req = new BuildRequest(containerId, dockerfile, null, PATH, targetImage, USER, ContainerPlatform.of('amd64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.SINGULARITY,Duration.ofMinutes(1)).withBuildId('1')
then:'should return singularity amd64 image'
strategy.getBuildImage(req) == 'quay.io/singularity/singularity:v3.11.4-slim'
when:'getting singularity with arm64 arch in build request'
- req = new BuildRequest(containerId, dockerfile, null, null, PATH, targetImage, USER, ContainerPlatform.of('arm64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.SINGULARITY, Duration.ofMinutes(1)).withBuildId('1')
+ req = new BuildRequest(containerId, dockerfile, null, PATH, targetImage, USER, ContainerPlatform.of('arm64'), cache, "10.20.30.40", '{}', null,null , null, null, BuildFormat.SINGULARITY, Duration.ofMinutes(1)).withBuildId('1')
then:'should return singularity arm64 image'
strategy.getBuildImage(req) == 'quay.io/singularity/singularity:v3.11.4-slim-arm64'
diff --git a/src/test/groovy/io/seqera/wave/service/cache/impl/LocalCacheProviderTest.groovy b/src/test/groovy/io/seqera/wave/service/cache/impl/LocalCacheProviderTest.groovy
index 5c2a14956..d1eaee375 100644
--- a/src/test/groovy/io/seqera/wave/service/cache/impl/LocalCacheProviderTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/cache/impl/LocalCacheProviderTest.groovy
@@ -80,45 +80,4 @@ class LocalCacheProviderTest extends Specification {
localCacheProvider.get('key') == 'new-value'
}
- def 'should add and find keys for values' () {
- when:
- localCacheProvider.biPut('x1', 'a', Duration.ofMinutes(1))
- localCacheProvider.biPut('x2', 'b', Duration.ofMinutes(1))
- localCacheProvider.biPut('x3', 'a', Duration.ofMinutes(1))
- localCacheProvider.biPut('x4', 'c', Duration.ofMinutes(1))
-
- then:
- localCacheProvider.biKeysFor('a') == ['x1', 'x3'] as Set
- localCacheProvider.biKeysFor('c') == ['x4'] as Set
- localCacheProvider.biKeysFor('d') == [] as Set
-
- when:
- localCacheProvider.biRemove('x1')
- then:
- localCacheProvider.biKeysFor('a') == ['x3'] as Set
-
- when:
- localCacheProvider.biRemove('x3')
- then:
- localCacheProvider.biKeysFor('a') == [] as Set
- }
-
- def 'should add and find keys for values' () {
- when:
- localCacheProvider.biPut('x1', 'a', Duration.ofMillis(100))
- localCacheProvider.biPut('x2', 'b', Duration.ofMinutes(1))
- localCacheProvider.biPut('x3', 'a', Duration.ofMinutes(1))
- localCacheProvider.biPut('x4', 'c', Duration.ofMinutes(1))
-
- then:
- localCacheProvider.biKeyFind('a', true) == 'x1'
- and:
- localCacheProvider.biKeysFor('a') == ['x1','x3'] as Set
- and:
- sleep 500
- and:
- localCacheProvider.biKeyFind('a', true) == 'x3'
- localCacheProvider.biKeysFor('a') == ['x3'] as Set
-
- }
}
diff --git a/src/test/groovy/io/seqera/wave/service/cache/impl/RedisCacheProviderTest.groovy b/src/test/groovy/io/seqera/wave/service/cache/impl/RedisCacheProviderTest.groovy
index 79c679b7e..6f548d7f4 100644
--- a/src/test/groovy/io/seqera/wave/service/cache/impl/RedisCacheProviderTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/cache/impl/RedisCacheProviderTest.groovy
@@ -89,70 +89,4 @@ class RedisCacheProviderTest extends Specification implements RedisTestContainer
redisCacheProvider.get('key') == 'new-value'
}
- def 'should add and find keys for values' () {
- when:
- redisCacheProvider.biPut('x1', 'a', Duration.ofMinutes(1))
- redisCacheProvider.biPut('x2', 'b', Duration.ofMinutes(1))
- redisCacheProvider.biPut('x3', 'a', Duration.ofMinutes(1))
- redisCacheProvider.biPut('x4', 'c', Duration.ofMinutes(1))
-
- then:
- redisCacheProvider.biKeysFor('a') == ['x1', 'x3'] as Set
- redisCacheProvider.biKeysFor('c') == ['x4'] as Set
- redisCacheProvider.biKeysFor('d') == [] as Set
-
- when:
- redisCacheProvider.biRemove('x1')
- then:
- redisCacheProvider.biKeysFor('a') == ['x3'] as Set
-
- when:
- redisCacheProvider.biRemove('x3')
- then:
- redisCacheProvider.biKeysFor('a') == [] as Set
-
- cleanup:
- redisCacheProvider.clear()
- }
-
- def 'should add and find single key for value' () {
- when:
- redisCacheProvider.biPut('x1', 'a', Duration.ofSeconds(1))
- redisCacheProvider.biPut('x2', 'b', Duration.ofMinutes(1))
- redisCacheProvider.biPut('x3', 'a', Duration.ofMinutes(1))
- redisCacheProvider.biPut('x4', 'c', Duration.ofMinutes(1))
-
- then:
- redisCacheProvider.biKeyFind('a', true) == 'x1'
- and:
- redisCacheProvider.biKeysFor('a') == ['x1','x3'] as Set
- and:
- sleep 1500
- and:
- redisCacheProvider.biKeyFind('a', true) == 'x3'
- redisCacheProvider.biKeysFor('a') == ['x3'] as Set
-
- cleanup:
- redisCacheProvider.clear()
- }
-
- def 'should update expiration when re-putting the value' () {
- when:
- redisCacheProvider.biPut('x1', 'a', Duration.ofSeconds(1))
- then:
- redisCacheProvider.biKeyFind('a', true) == 'x1'
-
- when:
- sleep 500
- redisCacheProvider.biPut('x1', 'a', Duration.ofSeconds(1))
- sleep 500
- redisCacheProvider.biPut('x1', 'a', Duration.ofSeconds(1))
- sleep 500
- then:
- redisCacheProvider.biKeyFind('a', true) == 'x1'
-
- cleanup:
- redisCacheProvider.clear()
- }
-
}
diff --git a/src/test/groovy/io/seqera/wave/service/k8s/K8sClientTest.groovy b/src/test/groovy/io/seqera/wave/service/k8s/K8sClientTest.groovy
deleted file mode 100644
index 27ef124ac..000000000
--- a/src/test/groovy/io/seqera/wave/service/k8s/K8sClientTest.groovy
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Wave, containers provisioning service
- * Copyright (c) 2023-2024, Seqera Labs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package io.seqera.wave.service.k8s
-
-import spock.lang.Ignore
-import spock.lang.Specification
-
-import java.nio.file.Path
-
-import io.micronaut.test.extensions.spock.annotation.MicronautTest
-import jakarta.inject.Inject
-/**
- *
- * @author Paolo Di Tommaso
- */
-@Ignore
-@MicronautTest
-class K8sClientTest extends Specification {
-
- @Inject K8sService k8sService
-
- def 'should create job' () {
- when:
- def job = k8sService.createJob('foo-2', 'busybox', ['sh', '-c', 'slep 10'])
- println job
- then:
- job
- }
-
- def 'should get job' () {
- when:
- def job = k8sService.getJob('foo-2')
- job.status.succeeded == 1
- then:
- true
- }
-
- def 'should create pod' () {
- when:
- def pod = k8sService.buildContainer(
- 'my-pod',
- 'busybox',
- ['cat','/home/user/.docker/config.json'],
- Path.of('/work/dir'),
- Path.of('/creds'),
- Path.of('/spack/dir'),
- ['my-creds': 'selector'])
- then:
- true
-
- when:
- def str = k8sService.logsPod('my-pod')
- then:
- str
-
- }
-}
diff --git a/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy b/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy
index 3f85ebb63..b9c50d94f 100644
--- a/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/k8s/K8sServiceImplTest.groovy
@@ -42,7 +42,6 @@ import io.micronaut.context.annotation.Replaces
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import io.seqera.wave.configuration.BlobCacheConfig
import io.seqera.wave.configuration.ScanConfig
-import io.seqera.wave.configuration.SpackConfig
/**
*
* @author Paolo Di Tommaso
@@ -188,30 +187,6 @@ class K8sServiceImplTest extends Specification {
ctx.close()
}
- def 'should get spack dir vol' () {
- given:
- def PROPS = [
- 'wave.build.workspace': '/build/work',
- 'wave.build.k8s.namespace': 'foo',
- 'wave.build.k8s.configPath': '/home/kube.config',
- 'wave.build.k8s.storage.claimName': 'bar',
- 'wave.build.k8s.storage.mountPath': '/build' ]
- and:
- def ctx = ApplicationContext.run(PROPS)
- def k8sService = ctx.getBean(K8sServiceImpl)
-
- when:
- def mount = k8sService.mountSpackCacheDir(Path.of('/foo/work/x1'), '/foo', '/opt/spack/cache')
- then:
- mount.name == 'build-data'
- mount.mountPath == '/opt/spack/cache'
- mount.subPath == 'work/x1'
- !mount.readOnly
-
- cleanup:
- ctx.close()
- }
-
def 'should create build pod for buildkit' () {
given:
def PROPS = [
@@ -225,7 +200,7 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this', 'that'], Path.of('/build/work/xyz'), Path.of('/build/work/xyz/config.json'), Duration.ofSeconds(10), null, [:])
+ def result = k8sService.buildSpec('foo', 'my-image:latest', ['this', 'that'], Path.of('/build/work/xyz'), Path.of('/build/work/xyz/config.json'), Duration.ofSeconds(10), [:])
then:
result.metadata.name == 'foo'
result.metadata.namespace == 'my-ns'
@@ -268,7 +243,7 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
def workDir = Path.of('/build/work/xyz')
when:
- def result = k8sService.buildSpec('foo', 'singularity:latest', ['this','that'], workDir, workDir.resolve('config.json'), Duration.ofSeconds(10), null, [:])
+ def result = k8sService.buildSpec('foo', 'singularity:latest', ['this','that'], workDir, workDir.resolve('config.json'), Duration.ofSeconds(10), [:])
then:
result.metadata.name == 'foo'
result.metadata.namespace == 'my-ns'
@@ -302,52 +277,6 @@ class K8sServiceImplTest extends Specification {
ctx.close()
}
- def 'should create build pod with spack cache' () {
- given:
- def PROPS = [
- 'wave.build.workspace': '/build/work',
- 'wave.build.k8s.namespace': 'my-ns',
- 'wave.build.k8s.configPath': '/home/kube.config',
- 'wave.build.k8s.storage.claimName': 'build-claim',
- 'wave.build.k8s.storage.mountPath': '/build',
- 'wave.build.spack.secretKeyFile':'/build/host/spack/key',
- 'wave.build.spack.secretMountPath':'/opt/container/spack/key'
- ]
- and:
- def ctx = ApplicationContext.run(PROPS)
- def k8sService = ctx.getBean(K8sServiceImpl)
- def spackConfig = ctx.getBean(SpackConfig)
- when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null,Duration.ofSeconds(10), spackConfig, [:])
- then:
- result.metadata.name == 'foo'
- result.metadata.namespace == 'my-ns'
- and:
- result.spec.activeDeadlineSeconds == 10
- and:
- verifyAll(result.spec.containers.get(0)) {
- name == 'foo'
- image == 'my-image:latest'
- args == ['this', 'that']
- env.name == ['BUILDKITD_FLAGS']
- env.value == ['--oci-worker-no-process-sandbox']
- volumeMounts.size() == 2
- volumeMounts.get(0).name == 'build-data'
- volumeMounts.get(0).mountPath == '/build/work/xyz'
- volumeMounts.get(0).subPath == 'work/xyz'
- volumeMounts.get(1).name == 'build-data'
- volumeMounts.get(1).mountPath == '/opt/container/spack/key'
- volumeMounts.get(1).subPath == 'host/spack/key'
- volumeMounts.get(1).readOnly
- }
- and:
- result.spec.volumes.get(0).name == 'build-data'
- result.spec.volumes.get(0).persistentVolumeClaim.claimName == 'build-claim'
-
- cleanup:
- ctx.close()
- }
-
def 'should create build pod without init container' () {
given:
def PROPS = [
@@ -361,7 +290,8 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), null,[:])
+ def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), [:])
+
then:
result.metadata.name == 'foo'
result.metadata.namespace == 'my-ns'
@@ -405,7 +335,8 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), null,[:])
+ def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), [:])
+
then:
result.metadata.name == 'foo'
result.metadata.labels.toString() == PROPS['wave.build.k8s.labels'].toString()
@@ -433,7 +364,8 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), null, PROPS['wave.build.k8s.node-selector'] as Map)
+ def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), PROPS['wave.build.k8s.node-selector'] as Map)
+
then:
result.spec.nodeSelector.toString() == PROPS['wave.build.k8s.node-selector'].toString()
and:
@@ -458,7 +390,8 @@ class K8sServiceImplTest extends Specification {
def k8sService = ctx.getBean(K8sServiceImpl)
when:
- def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), null,[:])
+ def result = k8sService.buildSpec('foo', 'my-image:latest', ['this','that'], Path.of('/build/work/xyz'), null, Duration.ofSeconds(10), [:])
+
then:
result.spec.serviceAccount == PROPS['wave.build.k8s.service-account']
and:
@@ -712,11 +645,10 @@ class K8sServiceImplTest extends Specification {
def workDir = Path.of('/work/dir')
def credsFile = Path.of('/creds/file')
def timeout = Duration.ofMinutes(10)
- def spackConfig = new SpackConfig(secretKeyFile: Path.of('/build/secret/key'), secretMountPath: '/secret/mount')
def nodeSelector = [key: 'value']
when:
- def job = k8sService.buildJobSpec(name, containerImage, args, workDir, credsFile, timeout, spackConfig, nodeSelector)
+ def job = k8sService.buildJobSpec(name, containerImage, args, workDir, credsFile, timeout, nodeSelector)
then:
job.spec.backoffLimit == 3
@@ -747,11 +679,10 @@ class K8sServiceImplTest extends Specification {
def workDir = Path.of('/work/dir')
def credsFile = Path.of('/creds/file')
def timeout = Duration.ofMinutes(10)
- def spackConfig = new SpackConfig(secretKeyFile: Path.of('/build/secret/key'), secretMountPath: '/secret/mount')
def nodeSelector = [key: 'value']
when:
- def job = k8sService.buildJobSpec(name, containerImage, args, workDir, credsFile, timeout, spackConfig, nodeSelector)
+ def job = k8sService.buildJobSpec(name, containerImage, args, workDir, credsFile, timeout, nodeSelector)
then:
job.spec.template.spec.containers[0].image == containerImage
diff --git a/src/test/groovy/io/seqera/wave/service/mail/MailServiceImplTest.groovy b/src/test/groovy/io/seqera/wave/service/mail/MailServiceImplTest.groovy
index e29034537..bd082d6fe 100644
--- a/src/test/groovy/io/seqera/wave/service/mail/MailServiceImplTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/mail/MailServiceImplTest.groovy
@@ -50,13 +50,11 @@ class MailServiceImplTest extends Specification {
1* request.getTargetImage() >> 'wave/build:xyz'
1* request.getPlatform() >> ContainerPlatform.DEFAULT
1* request.getCondaFile() >> null
- 1* request.getSpackFile() >> null
and:
mail.to == recipient
mail.body.contains('from foo')
and:
!mail.body.contains('Conda file')
- !mail.body.contains('Spack file')
// check it adds the Conda file content
when:
@@ -70,17 +68,6 @@ class MailServiceImplTest extends Specification {
mail.body.contains('Conda file')
mail.body.contains('bioconda::foo')
- // check it add the spack file content
- when:
- mail = service.buildCompletionMail(request, result, recipient)
- then:
- 1* request.getTargetImage() >> 'wave/build:xyz'
- 1* request.getPlatform() >> ContainerPlatform.DEFAULT
- 1* request.getSpackFile() >> 'some-spac-recipe'
- and:
- mail.to == recipient
- mail.body.contains('Spack file')
- mail.body.contains('some-spac-recipe')
}
}
diff --git a/src/test/groovy/io/seqera/wave/service/persistence/WaveBuildRecordTest.groovy b/src/test/groovy/io/seqera/wave/service/persistence/WaveBuildRecordTest.groovy
index fa9d5cf36..75ebd6c8c 100644
--- a/src/test/groovy/io/seqera/wave/service/persistence/WaveBuildRecordTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/persistence/WaveBuildRecordTest.groovy
@@ -45,7 +45,6 @@ class WaveBuildRecordTest extends Specification {
'container1234',
'FROM foo:latest',
'conda::recipe',
- 'some-spack-recipe',
Path.of("/some/path"),
'docker.io/my/repo:container1234',
PlatformId.NULL,
@@ -77,7 +76,6 @@ class WaveBuildRecordTest extends Specification {
'container1234',
'FROM foo:latest',
'conda::recipe',
- 'some-spack-recipe',
Path.of("/some/path"),
'docker.io/my/repo:container1234',
PlatformId.NULL,
diff --git a/src/test/groovy/io/seqera/wave/service/persistence/impl/SurrealPersistenceServiceTest.groovy b/src/test/groovy/io/seqera/wave/service/persistence/impl/SurrealPersistenceServiceTest.groovy
index 961f404b4..f23b263a6 100644
--- a/src/test/groovy/io/seqera/wave/service/persistence/impl/SurrealPersistenceServiceTest.groovy
+++ b/src/test/groovy/io/seqera/wave/service/persistence/impl/SurrealPersistenceServiceTest.groovy
@@ -104,7 +104,6 @@ class SurrealPersistenceServiceTest extends Specification implements SurrealDBTe
'container1234',
dockerFile,
condaFile,
- null,
Path.of("."),
'docker.io/my/repo:container1234',
PlatformId.NULL,
@@ -141,7 +140,6 @@ class SurrealPersistenceServiceTest extends Specification implements SurrealDBTe
'container1234',
'FROM foo:latest',
'conda::recipe',
- null,
Path.of("."),
'docker.io/my/repo:container1234',
PlatformId.NULL,
@@ -218,7 +216,6 @@ class SurrealPersistenceServiceTest extends Specification implements SurrealDBTe
'container1234',
'FROM foo:latest',
'conda::recipe',
- null,
Path.of("/some/path"),
'buildrepo:recipe-container1234',
PlatformId.NULL,
diff --git a/src/test/groovy/io/seqera/wave/util/ContainerHelperTest.groovy b/src/test/groovy/io/seqera/wave/util/ContainerHelperTest.groovy
index 7aedec722..bb68799fe 100644
--- a/src/test/groovy/io/seqera/wave/util/ContainerHelperTest.groovy
+++ b/src/test/groovy/io/seqera/wave/util/ContainerHelperTest.groovy
@@ -28,7 +28,6 @@ import io.seqera.wave.api.ImageNameStrategy
import io.seqera.wave.api.PackagesSpec
import io.seqera.wave.api.SubmitContainerTokenRequest
import io.seqera.wave.config.CondaOpts
-import io.seqera.wave.config.SpackOpts
import io.seqera.wave.exception.BadRequestException
import io.seqera.wave.service.ContainerRequestData
import io.seqera.wave.service.builder.BuildFormat
@@ -134,73 +133,6 @@ class ContainerHelperTest extends Specification {
'''.stripIndent()
}
- def 'should create spack singularity file'() {
- given:
- def SPACK_OPTS = new SpackOpts([
- basePackages: 'foo bar',
- commands: ['run','--this','--that']
- ])
- def packages = new PackagesSpec(type: PackagesSpec.Type.SPACK, spackOpts: SPACK_OPTS)
-
- when:
- def result = ContainerHelper.containerFileFromPackages(packages, true)
-
- then:
- result == '''\
- Bootstrap: docker
- From: {{spack_runner_image}}
- stage: final
-
- %files from build
- /opt/spack-env /opt/spack-env
- /opt/software /opt/software
- /opt/._view /opt/._view
- /opt/spack-env/z10_spack_environment.sh /.singularity.d/env/91-environment.sh
-
- %post
- run
- --this
- --that
- '''.stripIndent()
- }
-
- def 'should create spack docker file'() {
- given:
- def SPACK_OPTS = new SpackOpts([
- basePackages: 'foo bar',
- commands: ['run','--this','--that']
- ])
- def packages = new PackagesSpec(type: PackagesSpec.Type.SPACK, spackOpts: SPACK_OPTS)
-
- when:
- def result = ContainerHelper.containerFileFromPackages(packages, false)
-
- then:
- result == '''\
- # Runner image
- FROM {{spack_runner_image}}
-
- COPY --from=builder /opt/spack-env /opt/spack-env
- COPY --from=builder /opt/software /opt/software
- COPY --from=builder /opt/._view /opt/._view
-
- # Entrypoint for Singularity
- RUN mkdir -p /.singularity.d/env && \\
- cp -p /opt/spack-env/z10_spack_environment.sh /.singularity.d/env/91-environment.sh
- # Entrypoint for Docker
- RUN echo "#!/usr/bin/env bash\\n\\nset -ef -o pipefail\\nsource /opt/spack-env/z10_spack_environment.sh\\nexec \\"\\$@\\"" \\
- >/opt/spack-env/spack_docker_entrypoint.sh && chmod a+x /opt/spack-env/spack_docker_entrypoint.sh
-
- run
- --this
- --that
-
- ENTRYPOINT [ "/opt/spack-env/spack_docker_entrypoint.sh" ]
- CMD [ "/bin/bash" ]
- '''.stripIndent()
- }
-
-
def 'should validate conda file helper' () {
given:
def CONDA = 'this and that'
@@ -274,48 +206,6 @@ class ContainerHelperTest extends Specification {
'''.stripIndent()
}
- def 'should validate spack file helper' () {
- given:
- def SPACK = 'this and that'
- def req = new SubmitContainerTokenRequest(spackFile: SPACK.bytes.encodeBase64().toString())
- when:
- def result = ContainerHelper.spackFileFromRequest(req)
- then:
- result == SPACK
- }
-
- def 'should validate spack env file helper' () {
- given:
- def SPACK = '''\
- spack:
- specs: [bwa@0.7.15, salmon@1.1.1]
- concretizer: {unify: true, reuse: false}
- '''.stripIndent(true)
- and:
- def spec = new PackagesSpec(type: PackagesSpec.Type.SPACK, environment: SPACK.bytes.encodeBase64().toString())
- def req = new SubmitContainerTokenRequest(packages: spec)
-
- when:
- def result = ContainerHelper.spackFileFromRequest(req)
- then:
- result == SPACK
- }
-
- def 'should validate spack env packages helper' () {
- given:
- def spec = new PackagesSpec(type: PackagesSpec.Type.SPACK, entries: ['foo', 'bar'])
- def req = new SubmitContainerTokenRequest(packages: spec)
-
- when:
- def result = ContainerHelper.spackFileFromRequest(req)
- then:
- result == '''\
- spack:
- specs: [foo, bar]
- concretizer: {unify: true, reuse: false}
- '''.stripIndent(true)
- }
-
def 'should create response v1' () {
given:
def data = new ContainerRequestData(null,
@@ -474,48 +364,6 @@ class ContainerHelperTest extends Specification {
ContainerHelper.guessCondaRecipeName(CONDA,true) == new NameVersionPair(['pip','pandas'] as Set, [null, '2.2.2'] as Set)
}
- def 'should find spack recipe names from spack yaml file' () {
- def SPACK = '''\
- spack:
- specs: [bwa@0.7.15, salmon@1.1.1, nano@1.0 x=one]
- concretizer: {unify: true, reuse: true}
- '''.stripIndent(true)
-
- expect:
- ContainerHelper.guessSpackRecipeName(null) == null
- ContainerHelper.guessSpackRecipeName(SPACK) == new NameVersionPair(['bwa-0.7.15', 'salmon-1.1.1', 'nano-1.0'] as Set)
- and:
- ContainerHelper.guessSpackRecipeName(SPACK,true) == new NameVersionPair(['bwa', 'salmon', 'nano'] as Set, ['0.7.15', '1.1.1', '1.0'] as Set)
- }
-
- def 'should throw an exception when spack section is not present in spack yaml file' () {
- def SPACK = '''\
- specs: [bwa@0.7.15, salmon@1.1.1, nano@1.0 x=one]
- concretizer: {unify: true, reuse: true}
- '''.stripIndent(true)
-
- when:
- ContainerHelper.guessSpackRecipeName(SPACK)
- then:
- def e = thrown(BadRequestException)
- and:
- e.message == 'Malformed Spack environment file - missing "spack:" section'
- }
-
- def 'should throw an exception when spack.specs section is not present in spack yaml file' () {
- def SPACK = '''\
- spack:
- concretizer: {unify: true, reuse: true}
- '''.stripIndent(true)
-
- when:
- ContainerHelper.guessSpackRecipeName(SPACK)
- then:
- def e = thrown(BadRequestException)
- and:
- e.message == 'Malformed Spack environment file - missing "spack.specs:" section'
- }
-
@Unroll
def 'should normalise tag' () {
expect:
@@ -565,10 +413,10 @@ class ContainerHelperTest extends Specification {
def 'should make request target' () {
expect:
- ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'quay.io/org/name', '12345', null, null, null)
+ ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'quay.io/org/name', '12345', null, null)
== 'quay.io/org/name:12345'
and:
- ContainerHelper.makeTargetImage(BuildFormat.SINGULARITY, 'quay.io/org/name', '12345', null, null, null)
+ ContainerHelper.makeTargetImage(BuildFormat.SINGULARITY, 'quay.io/org/name', '12345', null, null)
== 'oras://quay.io/org/name:12345'
and:
@@ -576,16 +424,9 @@ class ContainerHelperTest extends Specification {
dependencies:
- salmon=1.2.3
'''
- ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'quay.io/org/name', '12345', conda, null, null)
+ ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'quay.io/org/name', '12345', conda, null)
== 'quay.io/org/name:salmon-1.2.3--12345'
- and:
- def spack = '''\
- spack:
- specs: [bwa@0.7.15]
- '''
- ContainerHelper.makeTargetImage(BuildFormat.DOCKER, 'quay.io/org/name', '12345', null, spack, null)
- == 'quay.io/org/name:bwa-0.7.15--12345'
}
@@ -633,16 +474,6 @@ class ContainerHelperTest extends Specification {
- numpy=1.0
'''.stripIndent(true)
- @Shared def SPACK1 = '''\
- spack:
- specs: [bwa@0.7.15]
- '''
-
- @Shared def SPACK2 = '''\
- spack:
- specs: [bwa@0.7.15, salmon@1.1.1]
- '''
-
@Unroll
def 'should make request target with name strategy' () {
expect:
@@ -651,62 +482,50 @@ class ContainerHelperTest extends Specification {
REPO,
ID,
CONDA,
- SPACK,
STRATEGY ? ImageNameStrategy.valueOf(STRATEGY) : null) == EXPECTED
where:
- FORMAT | REPO | ID | CONDA | SPACK | STRATEGY | EXPECTED
- 'DOCKER' | 'foo.com/build' | '123' | null | null | null | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | null | null | 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | null | null | 'tagPrefix' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | null | null | 'imageSuffix' | 'foo.com/build:123'
- and:
- 'SINGULARITY' | 'foo.com/build' | '123' | null | null | null | 'oras://foo.com/build:123'
- 'SINGULARITY' | 'foo.com/build' | '123' | null | null | 'none' | 'oras://foo.com/build:123'
- 'SINGULARITY' | 'foo.com/build' | '123' | null | null | 'tagPrefix' | 'oras://foo.com/build:123'
- 'SINGULARITY' | 'foo.com/build' | '123' | null | null | 'imageSuffix' | 'oras://foo.com/build:123'
+ FORMAT | REPO | ID | CONDA | STRATEGY | EXPECTED
+ 'DOCKER' | 'foo.com/build' | '123' | null | null | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | null | 'none' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | null | 'tagPrefix' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | null | 'imageSuffix' | 'foo.com/build:123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | CONDA1| null | null | 'foo.com/build:samtools-1.0--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA1| null | 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA1| null | 'tagPrefix' | 'foo.com/build:samtools-1.0--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA1| null | 'imageSuffix' | 'foo.com/build/samtools:1.0--123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | null | null | 'oras://foo.com/build:123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | null | 'none' | 'oras://foo.com/build:123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | null | 'tagPrefix' | 'oras://foo.com/build:123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | null | 'imageSuffix' | 'oras://foo.com/build:123'
and:
- 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| null | null | 'oras://foo.com/build:samtools-1.0--123'
- 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| null | 'none' | 'oras://foo.com/build:123'
- 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| null | 'tagPrefix' | 'oras://foo.com/build:samtools-1.0--123'
- 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| null | 'imageSuffix' | 'oras://foo.com/build/samtools:1.0--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA1| null | 'foo.com/build:samtools-1.0--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA1| 'none' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA1| 'tagPrefix' | 'foo.com/build:samtools-1.0--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA1| 'imageSuffix' | 'foo.com/build/samtools:1.0--123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | CONDA2| null | null | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA2| null | 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA2| null | 'tagPrefix' | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA2| null | 'imageSuffix' | 'foo.com/build/samtools_bamtools_multiqc:123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| null | 'oras://foo.com/build:samtools-1.0--123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| 'none' | 'oras://foo.com/build:123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| 'tagPrefix' | 'oras://foo.com/build:samtools-1.0--123'
+ 'SINGULARITY' | 'foo.com/build' | '123' | CONDA1| 'imageSuffix' | 'oras://foo.com/build/samtools:1.0--123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | CONDA3| null | null | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15_bwa-1.2.3_pruned--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA3| null | 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA3| null | 'tagPrefix' | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15_bwa-1.2.3_pruned--123'
- 'DOCKER' | 'foo.com/build' | '123' | CONDA3| null | 'imageSuffix' | 'foo.com/build/samtools_bamtools_multiqc_bwa_pruned:123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA2| null | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA2| 'none' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA2| 'tagPrefix' | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA2| 'imageSuffix' | 'foo.com/build/samtools_bamtools_multiqc:123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | PIP1 | null | null | 'foo.com/build:pip_pandas-2.2.2--123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP1 | null | 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP1 | null | 'tagPrefix' | 'foo.com/build:pip_pandas-2.2.2--123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP1 | null | 'imageSuffix' | 'foo.com/build/pip_pandas:123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA3| null | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15_bwa-1.2.3_pruned--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA3| 'none' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA3| 'tagPrefix' | 'foo.com/build:samtools-1.0_bamtools-2.0_multiqc-1.15_bwa-1.2.3_pruned--123'
+ 'DOCKER' | 'foo.com/build' | '123' | CONDA3| 'imageSuffix' | 'foo.com/build/samtools_bamtools_multiqc_bwa_pruned:123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | PIP2 | null | null | 'foo.com/build:pip_pandas-2.2.2_numpy-1.0--123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP2 | null | 'tagPrefix' | 'foo.com/build:pip_pandas-2.2.2_numpy-1.0--123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP2 | null | 'imageSuffix' | 'foo.com/build/pip_pandas_numpy:123'
- 'DOCKER' | 'foo.com/build' | '123' | PIP2 | null | 'none' | 'foo.com/build:123'
-
+ 'DOCKER' | 'foo.com/build' | '123' | PIP1 | null | 'foo.com/build:pip_pandas-2.2.2--123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP1 | 'none' | 'foo.com/build:123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP1 | 'tagPrefix' | 'foo.com/build:pip_pandas-2.2.2--123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP1 | 'imageSuffix' | 'foo.com/build/pip_pandas:123'
and:
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK1| null | 'foo.com/build:bwa-0.7.15--123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK1| 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK1| 'tagPrefix' | 'foo.com/build:bwa-0.7.15--123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK1| 'imageSuffix' | 'foo.com/build/bwa:0.7.15--123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP2 | null | 'foo.com/build:pip_pandas-2.2.2_numpy-1.0--123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP2 | 'tagPrefix' | 'foo.com/build:pip_pandas-2.2.2_numpy-1.0--123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP2 | 'imageSuffix' | 'foo.com/build/pip_pandas_numpy:123'
+ 'DOCKER' | 'foo.com/build' | '123' | PIP2 | 'none' | 'foo.com/build:123'
- and:
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK2| null | 'foo.com/build:bwa-0.7.15_salmon-1.1.1--123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK2| 'none' | 'foo.com/build:123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK2| 'tagPrefix' | 'foo.com/build:bwa-0.7.15_salmon-1.1.1--123'
- 'DOCKER' | 'foo.com/build' | '123' | null | SPACK2| 'imageSuffix' | 'foo.com/build/bwa_salmon:123'
}
def 'should validate containerfile' () {
diff --git a/src/test/groovy/io/seqera/wave/util/SpackHelperTest.groovy b/src/test/groovy/io/seqera/wave/util/SpackHelperTest.groovy
deleted file mode 100644
index 6e5ac880f..000000000
--- a/src/test/groovy/io/seqera/wave/util/SpackHelperTest.groovy
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Wave, containers provisioning service
- * Copyright (c) 2023-2024, Seqera Labs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package io.seqera.wave.util
-
-import spock.lang.Specification
-
-import io.seqera.wave.core.ContainerPlatform
-import io.seqera.wave.service.builder.BuildFormat
-
-/**
- *
- * @author Paolo Di Tommaso
- */
-class SpackHelperTest extends Specification {
-
- def 'should load builder template' () {
- expect:
- SpackHelper.builderDockerTemplate().startsWith('# Builder image')
- }
-
- def 'should prepend builder template' () {
- expect:
- SpackHelper.prependBuilderTemplate('foo', BuildFormat.DOCKER).startsWith('# Builder image')
- SpackHelper.prependBuilderTemplate('foo', BuildFormat.SINGULARITY).endsWith('\nfoo')
- }
-
- def 'should map platform to spack arch' () {
- expect:
- SpackHelper.toSpackArch(ContainerPlatform.of('x86_64')) == 'x86_64'
- SpackHelper.toSpackArch(ContainerPlatform.of('linux/x86_64')) == 'x86_64'
- SpackHelper.toSpackArch(ContainerPlatform.of('amd64')) == 'x86_64'
- SpackHelper.toSpackArch(ContainerPlatform.of('aarch64')) == 'aarch64'
- SpackHelper.toSpackArch(ContainerPlatform.of('arm64')) == 'aarch64'
- SpackHelper.toSpackArch(ContainerPlatform.of('linux/arm64/v8')) == 'aarch64'
-
- when:
- SpackHelper.toSpackArch(ContainerPlatform.of('linux/arm64/v7'))
- then:
- thrown(IllegalArgumentException)
- }
-}
diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml
index f7ff1edfa..b56b9bd5d 100644
--- a/src/test/resources/application-test.yml
+++ b/src/test/resources/application-test.yml
@@ -53,8 +53,6 @@ wave:
password: 'bar'
build:
workspace: 'build-workspace'
- spack:
- cacheDirectory: "spack-cache"
logs :
enabled : true
bucket : 'nextflow-ci'
diff --git a/typespec/models/Packages.tsp b/typespec/models/Packages.tsp
index 6fa59e16d..ce534501b 100644
--- a/typespec/models/Packages.tsp
+++ b/typespec/models/Packages.tsp
@@ -1,5 +1,4 @@
import "./CondaOpts.tsp";
-import "./SpackOpts.tsp";
@doc("Package configurations for container builds.")
model Packages {
@@ -7,6 +6,5 @@ model Packages {
condaOpts?: CondaOpts;
entries: string[];
environment: string;
- spackOpts?: SpackOpts;
- type: "CONDA" | "SPACK";
-}
\ No newline at end of file
+ type: "CONDA";
+}
diff --git a/typespec/models/SpackOpts.tsp b/typespec/models/SpackOpts.tsp
deleted file mode 100644
index 813caa6a2..000000000
--- a/typespec/models/SpackOpts.tsp
+++ /dev/null
@@ -1,5 +0,0 @@
-@doc("Options for Spack environments. Spack support will be removed in future releases")
-model SpackOpts {
- basePackages: string;
- commands: string[];
-}
diff --git a/typespec/models/WaveBuildRecord.tsp b/typespec/models/WaveBuildRecord.tsp
index f8e40bc4c..50f6966d1 100644
--- a/typespec/models/WaveBuildRecord.tsp
+++ b/typespec/models/WaveBuildRecord.tsp
@@ -10,7 +10,6 @@ model WaveBuildRecord {
platform: string;
requestIp: string;
scanId: string;
- spackFile: string;
startTime: string;
succeeded: boolean;
targetImage: string;
@@ -18,4 +17,3 @@ model WaveBuildRecord {
userId: int64;
userName: string;
}
-
\ No newline at end of file