Skip to content

Commit 9810fcc

Browse files
pditommasoclaude
andcommitted
Fix config validation warnings for Seqera executor options [ci fast]
Make ExecutorOpts implement ConfigScope and remove @ConfigOption from the executor field in SeqeraConfig so nested config options are properly discovered by the config validator. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
1 parent 03c801e commit 9810fcc

File tree

12 files changed

+438
-244
lines changed

12 files changed

+438
-244
lines changed

docs/executor.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,14 @@ By default, a gp3 volume with 325 MiB/s throughput is used (Fusion recommended s
455455

456456
```groovy
457457
seqera {
458-
machineRequirement {
459-
diskAllocation = 'task' // Per-task EBS volume (default)
460-
diskType = 'ebs/io1' // Use provisioned IOPS SSD
461-
diskIops = 10000 // Required for io1/io2
462-
diskThroughputMiBps = 500 // Throughput for gp3 volumes
463-
diskEncrypted = true // Enable KMS encryption
458+
executor {
459+
machineRequirement {
460+
diskAllocation = 'task' // Per-task EBS volume (default)
461+
diskType = 'ebs/io1' // Use provisioned IOPS SSD
462+
diskIops = 10000 // Required for io1/io2
463+
diskThroughputMiBps = 500 // Throughput for gp3 volumes
464+
diskEncrypted = true // Enable KMS encryption
465+
}
464466
}
465467
}
466468
```
@@ -473,8 +475,10 @@ To use instance storage instead of per-task EBS volumes:
473475

474476
```groovy
475477
seqera {
476-
machineRequirement {
477-
diskAllocation = 'node' // Use instance storage
478+
executor {
479+
machineRequirement {
480+
diskAllocation = 'node' // Use instance storage
481+
}
478482
}
479483
}
480484
```

docs/reference/config.md

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,56 +1498,63 @@ The following settings are available:
14981498
*Preview feature: may change in a future release.*
14991499
:::
15001500

1501-
The `seqera` scope allows you to configure the interactions with the Seqera scheduler service for the {ref}`seqera-executor`.
1501+
The `seqera` scope allows you to configure the interactions with Seqera services.
1502+
1503+
### `executor`
1504+
1505+
The `seqera.executor` scope configures the Seqera scheduler service for the {ref}`seqera-executor`.
15021506

15031507
The following settings are available:
15041508

1505-
`seqera.endpoint`
1509+
`seqera.executor.endpoint`
15061510
: The Seqera scheduler service endpoint URL (required).
15071511

1508-
`seqera.region`
1512+
`seqera.executor.region`
15091513
: The AWS region for task execution (default: `'eu-central-1'`).
15101514

1511-
`seqera.machineRequirement.arch`
1515+
`seqera.executor.labels`
1516+
: Custom labels to apply to AWS resources for cost tracking and resource organization. Labels are propagated to ECS tasks, capacity providers, and EC2 instances.
1517+
1518+
`seqera.executor.machineRequirement.arch`
15121519
: The CPU architecture for task execution, e.g. `'x86_64'` or `'arm64'`.
15131520

1514-
`seqera.machineRequirement.provisioning`
1521+
`seqera.executor.machineRequirement.provisioning`
15151522
: The instance provisioning mode. Can be `'spot'`, `'ondemand'`, or `'spotFirst'`.
15161523

1517-
`seqera.machineRequirement.maxSpotAttempts`
1524+
`seqera.executor.machineRequirement.maxSpotAttempts`
15181525
: The maximum number of spot retry attempts before falling back to on-demand. Only used when `provisioning` is `'spot'` or `'spotFirst'`.
15191526

1520-
`seqera.machineRequirement.machineFamilies`
1527+
`seqera.executor.machineRequirement.machineFamilies`
15211528
: List of acceptable EC2 instance families, e.g. `['m5', 'c5', 'r5']`.
15221529

1523-
`seqera.machineRequirement.diskAllocation`
1530+
`seqera.executor.machineRequirement.diskAllocation`
15241531
: The disk allocation strategy. Can be `'task'` (default) for per-task EBS volumes, or `'node'` for per-node instance storage. When using `'node'` allocation, EBS-specific options (`diskType`, `diskIops`, `diskThroughputMiBps`, `diskEncrypted`) are not applicable.
15251532

1526-
`seqera.machineRequirement.diskType`
1533+
`seqera.executor.machineRequirement.diskType`
15271534
: The EBS volume type for task scratch disk. Supported types: `'ebs/gp3'` (default), `'ebs/gp2'`, `'ebs/io1'`, `'ebs/io2'`, `'ebs/st1'`, `'ebs/sc1'`. Only applicable when `diskAllocation` is `'task'`.
15281535

1529-
`seqera.machineRequirement.diskThroughputMiBps`
1536+
`seqera.executor.machineRequirement.diskThroughputMiBps`
15301537
: The throughput in MiB/s for gp3 volumes (125-1000). Default: `325` (Fusion recommended). Only applicable when `diskAllocation` is `'task'`.
15311538

1532-
`seqera.machineRequirement.diskIops`
1539+
`seqera.executor.machineRequirement.diskIops`
15331540
: The IOPS for io1/io2/gp3 volumes. Required for io1/io2 volume types. Only applicable when `diskAllocation` is `'task'`.
15341541

1535-
`seqera.machineRequirement.diskEncrypted`
1542+
`seqera.executor.machineRequirement.diskEncrypted`
15361543
: Enable KMS encryption for the EBS volume (default: `false`). Only applicable when `diskAllocation` is `'task'`.
15371544

1538-
`seqera.retryPolicy.delay`
1545+
`seqera.executor.retryPolicy.delay`
15391546
: The initial delay when a failing HTTP request is retried (default: `'450ms'`).
15401547

1541-
`seqera.retryPolicy.maxDelay`
1548+
`seqera.executor.retryPolicy.maxDelay`
15421549
: The maximum delay when a failing HTTP request is retried (default: `'90s'`).
15431550

1544-
`seqera.retryPolicy.maxAttempts`
1551+
`seqera.executor.retryPolicy.maxAttempts`
15451552
: The maximum number of retry attempts (default: `10`).
15461553

1547-
`seqera.retryPolicy.jitter`
1554+
`seqera.executor.retryPolicy.jitter`
15481555
: The jitter factor for randomizing retry delays (default: `0.25`).
15491556

1550-
`seqera.retryPolicy.multiplier`
1557+
`seqera.executor.retryPolicy.multiplier`
15511558
: The multiplier for exponential backoff (default: `2.0`).
15521559

15531560
(config-spack)=

plugins/nf-seqera/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.7.0
1+
0.8.0

plugins/nf-seqera/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ dependencies {
4646
compileOnly project(':nextflow')
4747
compileOnly 'org.slf4j:slf4j-api:2.0.17'
4848
compileOnly 'org.pf4j:pf4j:3.12.0'
49-
api 'io.seqera:sched-client:0.16.0-SNAPSHOT'
49+
api 'io.seqera:sched-client:0.19.0-SNAPSHOT'
5050

5151
testImplementation(testFixtures(project(":nextflow")))
5252
testImplementation "org.apache.groovy:groovy:4.0.29"
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2013-2025, Seqera Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package io.seqera.config
19+
20+
import groovy.transform.CompileStatic
21+
import nextflow.config.spec.ConfigOption
22+
import nextflow.config.spec.ConfigScope
23+
import nextflow.script.dsl.Description
24+
import nextflow.util.Duration
25+
26+
/**
27+
* Configuration for the Seqera executor.
28+
*
29+
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
30+
*/
31+
@Description("""
32+
The `seqera.executor` scope provides configuration for the Seqera compute executor.
33+
""")
34+
@CompileStatic
35+
class ExecutorOpts implements ConfigScope {
36+
37+
final RetryOpts retryPolicy
38+
39+
@ConfigOption
40+
@Description("""
41+
The Seqera scheduler service endpoint URL.
42+
""")
43+
final String endpoint
44+
45+
@ConfigOption
46+
@Description("""
47+
The AWS region for task execution (default: `eu-central-1`).
48+
""")
49+
final String region
50+
51+
@ConfigOption
52+
@Description("""
53+
The EC2 key pair name for SSH access to instances.
54+
""")
55+
final String keyPairName
56+
57+
@ConfigOption
58+
@Description("""
59+
The interval for batching task submissions (default: `1 sec`).
60+
""")
61+
final Duration batchFlushInterval
62+
63+
@Description("""
64+
Machine/infrastructure requirements for session tasks.
65+
""")
66+
final MachineRequirementOpts machineRequirement
67+
68+
@ConfigOption
69+
@Description("""
70+
Custom labels to apply to AWS resources for cost tracking and resource organization.
71+
Labels are propagated to ECS tasks, capacity providers, and EC2 instances.
72+
""")
73+
final Map<String, String> labels
74+
75+
/* required by config scope -- do not remove */
76+
77+
ExecutorOpts() {}
78+
79+
ExecutorOpts(Map opts) {
80+
this.retryPolicy = new RetryOpts(opts.retryPolicy as Map ?: Map.of())
81+
this.endpoint = opts.endpoint as String
82+
if (!endpoint)
83+
throw new IllegalArgumentException("Missing Seqera endpoint - make sure to specify 'seqera.executor.endpoint' settings")
84+
85+
this.region = opts.region as String ?: "eu-central-1"
86+
this.keyPairName = opts.keyPairName as String
87+
this.batchFlushInterval = opts.batchFlushInterval
88+
? Duration.of(opts.batchFlushInterval as String)
89+
: Duration.of('1 sec')
90+
// machine requirement settings
91+
this.machineRequirement = new MachineRequirementOpts(opts.machineRequirement as Map ?: Map.of())
92+
// labels for cost tracking
93+
this.labels = opts.labels as Map<String, String>
94+
}
95+
96+
RetryOpts retryOpts() {
97+
this.retryPolicy
98+
}
99+
100+
String getEndpoint() {
101+
return endpoint
102+
}
103+
104+
String getRegion() {
105+
return region
106+
}
107+
108+
String getKeyPairName() {
109+
return keyPairName
110+
}
111+
112+
Duration getBatchFlushInterval() {
113+
return batchFlushInterval
114+
}
115+
116+
MachineRequirementOpts getMachineRequirement() {
117+
return machineRequirement
118+
}
119+
120+
Map<String, String> getLabels() {
121+
return labels
122+
}
123+
}

plugins/nf-seqera/src/main/io/seqera/config/MachineRequirementOpts.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import groovy.transform.CompileStatic
2121
import nextflow.config.spec.ConfigOption
2222
import nextflow.config.spec.ConfigScope
2323
import nextflow.script.dsl.Description
24+
import nextflow.util.MemoryUnit
2425

2526
/**
2627
* Machine/infrastructure requirements configuration options.
@@ -90,6 +91,12 @@ class MachineRequirementOpts implements ConfigScope {
9091
""")
9192
final String diskAllocation
9293

94+
@ConfigOption
95+
@Description("""
96+
The disk size for session-level storage (e.g., `100.GB`).
97+
""")
98+
final MemoryUnit diskSize
99+
93100
/* required by config scope -- do not remove */
94101
MachineRequirementOpts() {}
95102

@@ -103,6 +110,9 @@ class MachineRequirementOpts implements ConfigScope {
103110
this.diskIops = opts.diskIops as Integer
104111
this.diskEncrypted = opts.diskEncrypted as Boolean
105112
this.diskAllocation = opts.diskAllocation as String
113+
this.diskSize = opts.diskSize instanceof MemoryUnit
114+
? opts.diskSize as MemoryUnit
115+
: (opts.diskSize ? MemoryUnit.of(opts.diskSize as String) : null)
106116
}
107117

108118
String getArch() {
@@ -140,4 +150,8 @@ class MachineRequirementOpts implements ConfigScope {
140150
String getDiskAllocation() {
141151
return diskAllocation
142152
}
153+
154+
MemoryUnit getDiskSize() {
155+
return diskSize
156+
}
143157
}

0 commit comments

Comments
 (0)