16
16
17
17
package nextflow.cloud.aws.batch
18
18
19
- import static AwsContainerOptionsMapper.*
19
+
20
+ import static nextflow.cloud.aws.batch.AwsContainerOptionsMapper.*
20
21
21
22
import java.nio.file.Path
22
23
import java.nio.file.Paths
23
24
import java.time.Instant
24
25
26
+ import groovy.transform.Canonical
27
+ import groovy.transform.CompileStatic
28
+ import groovy.transform.Memoized
29
+ import groovy.util.logging.Slf4j
30
+ import nextflow.BuildInfo
31
+ import nextflow.SysEnv
32
+ import nextflow.cloud.aws.batch.model.ContainerPropertiesModel
33
+ import nextflow.cloud.aws.batch.model.RegisterJobDefinitionModel
34
+ import nextflow.cloud.types.CloudMachineInfo
35
+ import nextflow.container.ContainerNameValidator
36
+ import nextflow.exception.ProcessException
37
+ import nextflow.exception.ProcessSubmitException
38
+ import nextflow.exception.ProcessUnrecoverableException
39
+ import nextflow.executor.BashWrapperBuilder
40
+ import nextflow.fusion.FusionAwareTask
41
+ import nextflow.processor.BatchContext
42
+ import nextflow.processor.BatchHandler
43
+ import nextflow.processor.TaskArrayRun
44
+ import nextflow.processor.TaskHandler
45
+ import nextflow.processor.TaskRun
46
+ import nextflow.processor.TaskStatus
47
+ import nextflow.trace.TraceRecord
48
+ import nextflow.util.CacheHelper
49
+ import nextflow.util.MemoryUnit
50
+ import nextflow.util.TestOnly
25
51
import software.amazon.awssdk.services.batch.BatchClient
26
- import software.amazon.awssdk.services.batch.model.BatchException
27
52
import software.amazon.awssdk.services.batch.model.ArrayProperties
28
53
import software.amazon.awssdk.services.batch.model.AssignPublicIp
29
54
import software.amazon.awssdk.services.batch.model.AttemptContainerDetail
55
+ import software.amazon.awssdk.services.batch.model.BatchException
30
56
import software.amazon.awssdk.services.batch.model.ClientException
31
57
import software.amazon.awssdk.services.batch.model.ContainerOverrides
32
- import software.amazon.awssdk.services.batch.model.ContainerProperties
33
58
import software.amazon.awssdk.services.batch.model.DescribeJobDefinitionsRequest
34
59
import software.amazon.awssdk.services.batch.model.DescribeJobDefinitionsResponse
35
60
import software.amazon.awssdk.services.batch.model.DescribeJobsRequest
36
- import software.amazon.awssdk.services.batch.model.DescribeJobsResponse
37
61
import software.amazon.awssdk.services.batch.model.EphemeralStorage
38
62
import software.amazon.awssdk.services.batch.model.EvaluateOnExit
39
63
import software.amazon.awssdk.services.batch.model.Host
@@ -57,29 +81,6 @@ import software.amazon.awssdk.services.batch.model.SubmitJobRequest
57
81
import software.amazon.awssdk.services.batch.model.SubmitJobResponse
58
82
import software.amazon.awssdk.services.batch.model.TerminateJobRequest
59
83
import software.amazon.awssdk.services.batch.model.Volume
60
- import groovy.transform.Canonical
61
- import groovy.transform.CompileStatic
62
- import groovy.transform.Memoized
63
- import groovy.util.logging.Slf4j
64
- import nextflow.BuildInfo
65
- import nextflow.SysEnv
66
- import nextflow.cloud.types.CloudMachineInfo
67
- import nextflow.container.ContainerNameValidator
68
- import nextflow.exception.ProcessException
69
- import nextflow.exception.ProcessSubmitException
70
- import nextflow.exception.ProcessUnrecoverableException
71
- import nextflow.executor.BashWrapperBuilder
72
- import nextflow.fusion.FusionAwareTask
73
- import nextflow.processor.BatchContext
74
- import nextflow.processor.BatchHandler
75
- import nextflow.processor.TaskArrayRun
76
- import nextflow.processor.TaskHandler
77
- import nextflow.processor.TaskRun
78
- import nextflow.processor.TaskStatus
79
- import nextflow.trace.TraceRecord
80
- import nextflow.util.CacheHelper
81
- import nextflow.util.MemoryUnit
82
- import nextflow.util.TestOnly
83
84
/**
84
85
* Implements a task handler for AWS Batch jobs
85
86
*/
@@ -488,10 +489,9 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
488
489
489
490
@CompileStatic
490
491
protected String resolveJobDefinition0 (TaskRun task ) {
491
- final builder = makeJobDefRequest(task)
492
- final req = builder. build()
492
+ final req = makeJobDefRequest(task)
493
493
final container = task. getContainer()
494
- final token = req. parameters() . get(' nf-token' )
494
+ final token = req. parameters. get(' nf-token' )
495
495
final jobKey = " $container :$token " . toString()
496
496
if ( jobDefinitions. containsKey(jobKey) )
497
497
return jobDefinitions[jobKey]
@@ -501,12 +501,12 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
501
501
return jobDefinitions[jobKey]
502
502
503
503
def msg
504
- def name = findJobDef(req. jobDefinitionName() , token)
504
+ def name = findJobDef(req. jobDefinitionName, token)
505
505
if ( name ) {
506
506
msg = " [AWS BATCH] Found job definition name=$name ; container=$container "
507
507
}
508
508
else {
509
- name = createJobDef(builder )
509
+ name = createJobDef(req )
510
510
msg = " [AWS BATCH] Created job definition name=$name ; container=$container "
511
511
}
512
512
// log the request
@@ -526,7 +526,8 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
526
526
* @param image The Docker container image for which is required to create a Batch job definition
527
527
* @return An instance of {@link software.amazon.awssdk.services.batch.model.RegisterJobDefinitionRequest.Builder} for the specified Docker image
528
528
*/
529
- protected RegisterJobDefinitionRequest.Builder makeJobDefRequest (TaskRun task ) {
529
+ @CompileStatic
530
+ protected RegisterJobDefinitionModel makeJobDefRequest (TaskRun task ) {
530
531
final uniq = new ArrayList ()
531
532
final result = configJobDefRequest(task, uniq)
532
533
@@ -552,43 +553,43 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
552
553
* @return
553
554
* An instance of {@link software.amazon.awssdk.services.batch.model.RegisterJobDefinitionRequest} for the specified Docker image
554
555
*/
555
- protected RegisterJobDefinitionRequest.Builder configJobDefRequest (TaskRun task , List hashingTokens ) {
556
+ @CompileStatic
557
+ protected RegisterJobDefinitionModel configJobDefRequest (TaskRun task , List hashingTokens ) {
556
558
final image = task. getContainer()
557
559
final name = normalizeJobDefinitionName(image)
558
560
final opts = getAwsOptions()
559
561
560
- final result = RegisterJobDefinitionRequest . builder ()
562
+ final result = new RegisterJobDefinitionModel ()
561
563
result. jobDefinitionName(name)
562
564
result. type(JobDefinitionType . CONTAINER )
563
565
564
566
// create the container opts based on task config
565
- final builder = ContainerProperties . builder()
566
567
final containerOpts = task. getConfig(). getContainerOptionsMap()
567
- addCmdOptions (containerOpts, builder )
568
+ final container = createContainerProperties (containerOpts)
568
569
569
570
// container definition
570
571
// https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
571
572
final reqCpus = ResourceRequirement . builder(). type(ResourceType . VCPU ). value(' 1' ). build()
572
573
final reqMem = ResourceRequirement . builder(). type(ResourceType . MEMORY ). value( opts. fargateMode ? ' 2048' : ' 1024' ). build()
573
- builder
574
+ container
574
575
.image(image)
575
576
.command(' true' )
576
577
// note the actual command, memory and cpus are overridden when the job is executed
577
578
.resourceRequirements( reqCpus, reqMem )
578
579
579
580
final jobRole = opts. getJobRole()
580
581
if ( jobRole )
581
- builder . jobRoleArn(jobRole)
582
+ container . jobRoleArn(jobRole)
582
583
583
584
if ( opts. executionRole )
584
- builder . executionRoleArn(opts. executionRole)
585
+ container . executionRoleArn(opts. executionRole)
585
586
586
587
final logsGroup = opts. getLogsGroup()
587
588
if ( logsGroup )
588
- builder . logConfiguration(getLogConfiguration(logsGroup, opts. getRegion()))
589
+ container . logConfiguration(getLogConfiguration(logsGroup, opts. getRegion()))
589
590
590
591
if ( fusionEnabled() )
591
- builder . privileged(true )
592
+ container . privileged(true )
592
593
593
594
final mountsMap = new LinkedHashMap ( 10 )
594
595
final awscli = opts. cliPath
@@ -604,20 +605,20 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
604
605
}
605
606
606
607
if ( mountsMap )
607
- addVolumeMountsToContainer(mountsMap, builder )
608
+ addVolumeMountsToContainer(mountsMap, container )
608
609
609
610
// Fargate specific settings
610
611
if ( opts. isFargateMode() ) {
611
612
result. platformCapabilities(List . of(PlatformCapability . FARGATE ))
612
- builder . networkConfiguration( NetworkConfiguration . builder(). assignPublicIp(AssignPublicIp . ENABLED ). build() )
613
+ container . networkConfiguration( NetworkConfiguration . builder(). assignPublicIp(AssignPublicIp . ENABLED ). build() )
613
614
// use at least 50 GB as disk local storage
614
615
final diskGb = task. config. getDisk()?. toGiga()?. toInteger() ?: 50
615
- builder . ephemeralStorage( EphemeralStorage . builder(). sizeInGiB(diskGb). build() )
616
+ container . ephemeralStorage( EphemeralStorage . builder(). sizeInGiB(diskGb). build() )
616
617
// check for arm64 cpu architecture
617
618
if ( task. config. getArchitecture()?. arch == ' arm64' )
618
- builder . runtimePlatform(RuntimePlatform . builder(). cpuArchitecture(' ARM64' ). build())
619
+ container . runtimePlatform(RuntimePlatform . builder(). cpuArchitecture(' ARM64' ). build())
619
620
}
620
- final container = builder . build()
621
+
621
622
// finally set the container options
622
623
result. containerProperties(container)
623
624
@@ -641,7 +642,8 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
641
642
]). build()
642
643
}
643
644
644
- protected void addVolumeMountsToContainer (Map<String ,String > mountsMap , ContainerProperties.Builder container ) {
645
+ @CompileStatic
646
+ protected void addVolumeMountsToContainer (Map<String ,String > mountsMap , ContainerPropertiesModel container ) {
645
647
final mounts = new ArrayList<MountPoint > (mountsMap. size())
646
648
final volumes = new ArrayList<Volume > (mountsMap. size())
647
649
for ( Map.Entry < String ,String > entry : mountsMap. entrySet() ) {
@@ -656,12 +658,14 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
656
658
def mount = MountPoint . builder()
657
659
.sourceVolume(mountName)
658
660
.containerPath(hostPath)
659
- .readOnly(readOnly). build()
661
+ .readOnly(readOnly)
662
+ .build()
660
663
mounts << mount
661
664
662
665
def vol = Volume . builder()
663
666
.name(mountName)
664
- .host(Host . builder(). sourcePath(containerPath). build()). build()
667
+ .host(Host . builder(). sourcePath(containerPath). build())
668
+ .build()
665
669
volumes << vol
666
670
}
667
671
@@ -698,17 +702,16 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler<String,Job
698
702
/**
699
703
* Create (aka register) a new Batch job definition
700
704
*
701
- * @param req A {@link RegisterJobDefinitionRequest} representing the Batch jib definition to create
705
+ * @param model A {@link RegisterJobDefinitionRequest} representing the Batch jib definition to create
702
706
* @return The fully qualified Batch job definition name eg {@code my-job-definition:3 }
703
707
*/
704
- protected String createJobDef (RegisterJobDefinitionRequest.Builder builder ) {
708
+ protected String createJobDef (RegisterJobDefinitionModel model ) {
705
709
// add nextflow tags
706
- builder. tags([
707
- ' nextflow.io/createdAt' : Instant . now(). toString(),
708
- ' nextflow.io/version' : BuildInfo . version
709
- ])
710
+ model. addTagsEntry(' nextflow.io/createdAt' , Instant . now(). toString())
711
+ model. addTagsEntry(' nextflow.io/version' , BuildInfo . version)
710
712
// create the job def
711
- final res = createJobDef0(bypassProxy(client), builder. build() as RegisterJobDefinitionRequest ) // bypass the client proxy! see #1024
713
+ final req = model. toBatchRequest()
714
+ final res = createJobDef0(bypassProxy(client), req) // bypass the client proxy! see #1024
712
715
return " ${ res.jobDefinitionName()} :${ res.revision()} "
713
716
}
714
717
0 commit comments