Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/reference/config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ The amount of time the Apptainer pull can last, exceeding which the process is t

The registry from where Docker images are pulled. It should be only used to specify a private registry server. It should NOT include the protocol prefix i.e. `http://`.

##### `apptainer.resourceLimits`

<AddedInVersion version="26.10" />

Apply the task `cpus` and `memory` directives as container resource limits using the `--cpus` and `--memory` flags (default: `false`).

##### `apptainer.runOptions`

Specify extra command line options supported by `apptainer exec`.
Expand Down Expand Up @@ -1974,6 +1980,12 @@ The amount of time the Singularity pull can last, after which the process is ter

The registry from where Docker images are pulled. It should be only used to specify a private registry server. It should NOT include the protocol prefix i.e. `http://`.

##### `singularity.resourceLimits`

<AddedInVersion version="26.10" />

Apply the task `cpus` and `memory` directives as container resource limits using the `--cpus` and `--memory` flags (default: `false`).

##### `singularity.runOptions`

Specify extra command line options supported by `singularity exec`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class ApptainerBuilder extends SingularityBuilder {
if( config.engineOptions )
this.addEngineOptions(config.engineOptions)

this.resourceLimits = config.resourceLimits

if( config.runOptions )
this.addRunOptions(config.runOptions)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ class ApptainerConfig implements ConfigScope, ContainerConfig {
""")
final String registry

@ConfigOption
@Description("""
Apply the task `cpus` and `memory` directives as container resource limits using the `--cpus` and `--memory` flags (default: `false`).
""")
final boolean resourceLimits

@ConfigOption
@Description("""
Specify extra command line options supported by `apptainer exec`.
Expand All @@ -109,6 +115,7 @@ class ApptainerConfig implements ConfigScope, ContainerConfig {
ociAutoPull = opts.ociAutoPull as boolean
pullTimeout = opts.pullTimeout as Duration ?: Duration.of('20min')
registry = opts.registry
resourceLimits = opts.resourceLimits as boolean
runOptions = opts.runOptions
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class SingularityBuilder extends ContainerBuilder<SingularityBuilder> {

private Boolean ociMode

protected boolean resourceLimits

SingularityBuilder(String name) {
this.image = name
this.homeMount = defaultHomeMount()
Expand Down Expand Up @@ -84,6 +86,7 @@ class SingularityBuilder extends ContainerBuilder<SingularityBuilder> {
this.addEngineOptions(config.engineOptions)

this.ociMode = config.ociMode
this.resourceLimits = config.resourceLimits

if( config.runOptions )
this.addRunOptions(config.runOptions)
Expand Down Expand Up @@ -132,6 +135,13 @@ class SingularityBuilder extends ContainerBuilder<SingularityBuilder> {
if( ociMode != null )
result << (ociMode ? '--oci ' : '--no-oci ')

if( resourceLimits ) {
if( cpus )
result << "--cpus ${cpus} "
if( memory )
result << "--memory ${memory} "
}

if( autoMounts ) {
makeVolumes(mounts, result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ class SingularityConfig implements ConfigScope, ContainerConfig {
""")
final String registry

@ConfigOption
@Description("""
Apply the task `cpus` and `memory` directives as container resource limits using the `--cpus` and `--memory` flags (default: `false`).
""")
final boolean resourceLimits

@ConfigOption
@Description("""
Specify extra command line options supported by `singularity exec`.
Expand All @@ -116,6 +122,7 @@ class SingularityConfig implements ConfigScope, ContainerConfig {
ociMode = opts.ociMode as Boolean
pullTimeout = opts.pullTimeout as Duration ?: Duration.of('20min')
registry = opts.registry
resourceLimits = opts.resourceLimits as boolean
runOptions = opts.runOptions
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package nextflow.container
import java.nio.file.Paths

import nextflow.SysEnv
import nextflow.util.MemoryUnit
import spock.lang.Specification
import spock.lang.Unroll
/**
Expand Down Expand Up @@ -220,6 +221,21 @@ class ApptainerBuilderTest extends Specification {
cmd == 'set +u; env - PATH="$PATH" ${TMP:+APPTAINERENV_TMP="$TMP"} ${TMPDIR:+APPTAINERENV_TMPDIR="$TMPDIR"} apptainer exec --no-home --pid -B "$NXF_TASK_WORKDIR" ubuntu.img /bin/sh -c "cd \\"$NXF_TASK_WORKDIR\\"; bwa --this --that file.fastq"'
}

def 'should emit resource limits when enabled' () {
expect:
new ApptainerBuilder('busybox')
.setCpus(2)
.setMemory(new MemoryUnit('100M'))
.build()
.runCommand == 'set +u; env - PATH="$PATH" ${TMP:+APPTAINERENV_TMP="$TMP"} ${TMPDIR:+APPTAINERENV_TMPDIR="$TMPDIR"} apptainer exec --no-home --pid -B "$NXF_TASK_WORKDIR" busybox'

new ApptainerBuilder('busybox', new ApptainerConfig(resourceLimits: true))
.setCpus(2)
.setMemory(new MemoryUnit('100M'))
.build()
.runCommand == 'set +u; env - PATH="$PATH" ${TMP:+APPTAINERENV_TMP="$TMP"} ${TMPDIR:+APPTAINERENV_TMPDIR="$TMPDIR"} apptainer exec --no-home --pid --cpus 2 --memory 100m -B "$NXF_TASK_WORKDIR" busybox'
}

@Unroll
def 'test apptainer env'() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ApptainerConfigTest extends Specification {
expect:
config.envWhitelist == []
config.pullTimeout.toMillis() == 20 * 60 * 1000 //20 min
config.resourceLimits == false
}

def 'should create config with full map'(){
Expand All @@ -48,6 +49,7 @@ class ApptainerConfigTest extends Specification {
ociAutoPull: false,
pullTimeout: '50s',
registry: 'http://registry.com',
resourceLimits: true,
runOptions: '--contain --writable'
]
def config = new ApptainerConfig(configMap)
Expand All @@ -61,9 +63,10 @@ class ApptainerConfigTest extends Specification {
config.libraryDir == 'libraryDir'
config.noHttps == false
config.ociAutoPull == false
config.pullTimeout.toMillis() == 50_000 // 50s
config.registry == 'http://registry.com'
config.resourceLimits == true
config.runOptions == '--contain --writable'
config.pullTimeout.toMillis() == 50_000 // 50s

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package nextflow.container
import java.nio.file.Paths

import nextflow.SysEnv
import nextflow.util.MemoryUnit
import spock.lang.Specification
import spock.lang.Unroll

Expand Down Expand Up @@ -221,6 +222,25 @@ class SingularityBuilderTest extends Specification {
cmd == 'set +u; env - PATH="$PATH" ${TMP:+SINGULARITYENV_TMP="$TMP"} ${TMPDIR:+SINGULARITYENV_TMPDIR="$TMPDIR"} singularity exec --no-home --pid -B "$NXF_TASK_WORKDIR" ubuntu.img /bin/sh -c "cd \\"$NXF_TASK_WORKDIR\\"; bwa --this --that file.fastq"'
}

def 'should emit resource limits when enabled' () {
expect:
new SingularityBuilder('busybox')
.setCpus(2)
.setMemory(new MemoryUnit('100M'))
.build()
.runCommand == 'set +u; env - PATH="$PATH" ${TMP:+SINGULARITYENV_TMP="$TMP"} ${TMPDIR:+SINGULARITYENV_TMPDIR="$TMPDIR"} singularity exec --no-home --pid -B "$NXF_TASK_WORKDIR" busybox'

new SingularityBuilder('busybox', new SingularityConfig(resourceLimits: true))
.setCpus(2)
.setMemory(new MemoryUnit('100M'))
.build()
.runCommand == 'set +u; env - PATH="$PATH" ${TMP:+SINGULARITYENV_TMP="$TMP"} ${TMPDIR:+SINGULARITYENV_TMPDIR="$TMPDIR"} singularity exec --no-home --pid --cpus 2 --memory 100m -B "$NXF_TASK_WORKDIR" busybox'

new SingularityBuilder('busybox', new SingularityConfig(resourceLimits: true))
.build()
.runCommand == 'set +u; env - PATH="$PATH" ${TMP:+SINGULARITYENV_TMP="$TMP"} ${TMPDIR:+SINGULARITYENV_TMPDIR="$TMPDIR"} singularity exec --no-home --pid -B "$NXF_TASK_WORKDIR" busybox'
}

@Unroll
def 'test singularity env'() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SingularityConfigTest extends Specification {
expect:
config.envWhitelist == []
config.pullTimeout.toMillis() == 20 * 60 * 1000 //20 min
config.resourceLimits == false
}

def 'should create config with full map'(){
Expand All @@ -48,6 +49,7 @@ class SingularityConfigTest extends Specification {
ociAutoPull: false,
pullTimeout: '50s',
registry: 'http://registry.com',
resourceLimits: true,
runOptions: '--contain --writable'
]
def config = new SingularityConfig(configMap)
Expand All @@ -62,6 +64,7 @@ class SingularityConfigTest extends Specification {
config.noHttps == false
config.ociAutoPull == false
config.registry == 'http://registry.com'
config.resourceLimits == true
config.runOptions == '--contain --writable'
config.pullTimeout.toMillis() == 50_000 // 50s

Expand Down
Loading