diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a022a7722c..ed4083c735 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,13 +43,13 @@ jobs: COMMIT_MESSAGE="$(curl -s \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ https://api.github.com/repos/${{ github.repository }}/commits/$COMMIT_SHA | jq -r '.commit.message')" - echo "Commit message=$(printf "%q" "$COMMIT_MESSAGE")" | head -n 1 - echo "commit_message=$(printf "%q" "$COMMIT_MESSAGE")" | head -n 1 >> $GITHUB_OUTPUT + echo "Commit message=$(printf "%s" "$COMMIT_MESSAGE")" | head -n 1 + echo "commit_message=$(printf "%s" "$COMMIT_MESSAGE")" | head -n 1 >> $GITHUB_OUTPUT else echo "GitHub event=${{ github.event_name }}" COMMIT_MESSAGE="${{ github.event.head_commit.message }}" - echo "Commit message=$(printf "%q" "$COMMIT_MESSAGE")" | head -n 1 - echo "commit_message=$(printf "%q" "$COMMIT_MESSAGE")" | head -n 1 >> $GITHUB_OUTPUT + echo "Commit message=$(printf "%s" "$COMMIT_MESSAGE")" | head -n 1 + echo "commit_message=$(printf "%s" "$COMMIT_MESSAGE")" | head -n 1 >> $GITHUB_OUTPUT fi - name: Setup env diff --git a/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchHelper.groovy b/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchHelper.groovy index 36bb2895ec..9de9a198e6 100644 --- a/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchHelper.groovy +++ b/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchHelper.groovy @@ -20,6 +20,9 @@ import software.amazon.awssdk.services.batch.BatchClient import software.amazon.awssdk.services.batch.model.DescribeComputeEnvironmentsRequest import software.amazon.awssdk.services.batch.model.DescribeJobQueuesRequest import software.amazon.awssdk.services.batch.model.DescribeJobsRequest +import software.amazon.awssdk.services.batch.model.EcsTaskDetails +import software.amazon.awssdk.services.batch.model.JobDetail +import software.amazon.awssdk.services.batch.model.TaskContainerDetails import software.amazon.awssdk.services.ec2.Ec2Client import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest import software.amazon.awssdk.services.ec2.model.Instance @@ -193,7 +196,8 @@ class AwsBatchHelper { final response = batchClient.describeJobs(request) if( response.jobs() ) { final detail = response.jobs()[0] - return detail.container().logStreamName() + return getTaskContainer(detail)?.logStreamName() + ?: detail.container()?.logStreamName() } else { log.debug "Unable to find info for batch job id=$jobId" @@ -201,6 +205,46 @@ class AwsBatchHelper { } } + /** + * Retrieve the first EcsTaskDetails from the given JobDetail. + * + * In combination with {@code getTaskContainer(job)} this is analogous to {@code job.getContainer()}, but + * using the multi-container ECSProperties model. + * + * @param job + * @return + * The first EcsTaskDetails of the first TaskProperties, or {@code null} + */ + static EcsTaskDetails getTaskProperties(JobDetail job) { + try { + return job.ecsProperties().taskProperties().first() + } catch (Exception e) { + def jobId = job?.jobId() ?: '(unknown)' + log.debug "Unable to get container properties for batch job id=$jobId: ${e.getMessage()}" + return null + } + } + + /** + * Retrieve the first TaskContainerDetails from the given JobDetail. + * + * In combination with {@code getTaskProperties(job)} this is analogous to {@code job.getContainer()}, but + * using the multi-container ECSProperties model. + * + * @param job + * @return + * The first TaskContainerDetails of the first TaskProperties, or {@code null} + */ + static TaskContainerDetails getTaskContainer(JobDetail job) { + try { + return getTaskProperties(job).containers().first() + } catch (Exception e) { + def jobId = job?.jobId() ?: '(unknown)' + log.debug "Unable to get container details for batch job id=$jobId: ${e.getMessage()}" + return null + } + } + /** * Retrieve the cloudwatch logs for the specified AWS Batch Job ID * diff --git a/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchTaskHandler.groovy b/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchTaskHandler.groovy index 636e28c0ef..3ac579ecb4 100644 --- a/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchTaskHandler.groovy +++ b/plugins/nf-amazon/src/main/nextflow/cloud/aws/batch/AwsBatchTaskHandler.groovy @@ -16,7 +16,7 @@ package nextflow.cloud.aws.batch - +import static nextflow.cloud.aws.batch.AwsBatchHelper.* import static nextflow.cloud.aws.batch.AwsContainerOptionsMapper.* import java.nio.file.Path @@ -51,13 +51,13 @@ import nextflow.util.TestOnly import software.amazon.awssdk.services.batch.BatchClient import software.amazon.awssdk.services.batch.model.ArrayProperties import software.amazon.awssdk.services.batch.model.AssignPublicIp -import software.amazon.awssdk.services.batch.model.AttemptContainerDetail +import software.amazon.awssdk.services.batch.model.AttemptDetail import software.amazon.awssdk.services.batch.model.BatchException import software.amazon.awssdk.services.batch.model.ClientException -import software.amazon.awssdk.services.batch.model.ContainerOverrides import software.amazon.awssdk.services.batch.model.DescribeJobDefinitionsRequest import software.amazon.awssdk.services.batch.model.DescribeJobDefinitionsResponse import software.amazon.awssdk.services.batch.model.DescribeJobsRequest +import software.amazon.awssdk.services.batch.model.EcsPropertiesOverride import software.amazon.awssdk.services.batch.model.EphemeralStorage import software.amazon.awssdk.services.batch.model.EvaluateOnExit import software.amazon.awssdk.services.batch.model.Host @@ -79,6 +79,8 @@ import software.amazon.awssdk.services.batch.model.RetryStrategy import software.amazon.awssdk.services.batch.model.RuntimePlatform import software.amazon.awssdk.services.batch.model.SubmitJobRequest import software.amazon.awssdk.services.batch.model.SubmitJobResponse +import software.amazon.awssdk.services.batch.model.TaskContainerOverrides +import software.amazon.awssdk.services.batch.model.TaskPropertiesOverride import software.amazon.awssdk.services.batch.model.TerminateJobRequest import software.amazon.awssdk.services.batch.model.Volume /** @@ -246,7 +248,8 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler(5) - final container = ContainerOverrides.builder() + final container = TaskContainerOverrides.builder() container.command(getSubmitCommand()) // set the task memory final cpus = task.config.getCpus() @@ -849,7 +862,13 @@ class AwsBatchTaskHandler extends TaskHandler implements BatchHandler> ['bash', '-c', 'something'] 1 * handler.maxSpotAttempts() >> 5 @@ -106,10 +107,10 @@ class AwsBatchTaskHandlerTest extends Specification { req.jobName() == 'batch-task' req.jobQueue() == 'queue1' req.jobDefinition() == 'job-def:1' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' - req.containerOverrides().environment() == [VAR_FOO, VAR_BAR] - req.containerOverrides().command() == ['bash', '-c', 'something'] + overrides.resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' + overrides.resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' + overrides.environment() == [VAR_FOO, VAR_BAR] + overrides.command() == ['bash', '-c', 'something'] req.retryStrategy() == RetryStrategy.builder() .attempts(5) .evaluateOnExit( EvaluateOnExit.builder().action('RETRY').onStatusReason('Host EC2*').build(), EvaluateOnExit.builder().onReason('*').action('EXIT').build() ) @@ -117,6 +118,7 @@ class AwsBatchTaskHandlerTest extends Specification { when: req = handler.newSubmitRequest(task) + overrides = req.ecsPropertiesOverride().taskProperties()[0].containers()[0] then: 1 * handler.getSubmitCommand() >> ['bash', '-c', 'something'] 1 * handler.maxSpotAttempts() >> 0 @@ -128,10 +130,10 @@ class AwsBatchTaskHandlerTest extends Specification { req.jobName() == 'batch-task' req.jobQueue() == 'queue1' req.jobDefinition() == 'job-def:1' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' - req.containerOverrides().environment() == [VAR_FOO, VAR_BAR] - req.containerOverrides().command() == ['bash', '-c', 'something'] + overrides.resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' + overrides.resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' + overrides.environment() == [VAR_FOO, VAR_BAR] + overrides.command() == ['bash', '-c', 'something'] req.retryStrategy() == null // <-- retry is managed by NF, hence this must be null } @@ -145,6 +147,7 @@ class AwsBatchTaskHandlerTest extends Specification { when: def req = handler.newSubmitRequest(task) + def overrides = req.ecsPropertiesOverride().taskProperties()[0].containers()[0] then: 1 * handler.getSubmitCommand() >> ['bash', '-c', 'something'] 1 * handler.maxSpotAttempts() >> 5 @@ -156,12 +159,13 @@ class AwsBatchTaskHandlerTest extends Specification { req.jobName() == 'batch-task' req.jobQueue() == 'queue1' req.jobDefinition() == 'job-def:1' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' - req.containerOverrides().command() == ['bash', '-c', 'something'] + overrides.resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' + overrides.resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' + overrides.command() == ['bash', '-c', 'something'] when: def req2 = handler.newSubmitRequest(task) + def overrides2 = req2.ecsPropertiesOverride().taskProperties()[0].containers()[0] then: 1 * handler.getSubmitCommand() >> ['bash', '-c', 'something'] 1 * handler.maxSpotAttempts() >> 5 @@ -173,9 +177,9 @@ class AwsBatchTaskHandlerTest extends Specification { req2.jobName() == 'batch-task' req2.jobQueue() == 'queue1' req2.jobDefinition() == 'job-def:1' - req2.containerOverrides().resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' - req2.containerOverrides().resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' - req2.containerOverrides().command() ==['bash', '-c', 'something'] + overrides2.resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' + overrides2.resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '8192' + overrides2.command() ==['bash', '-c', 'something'] req2.shareIdentifier() == 'priority/high' req2.schedulingPriorityOverride() == 9999 } @@ -193,6 +197,7 @@ class AwsBatchTaskHandlerTest extends Specification { when: def req = handler.newSubmitRequest(task) + def overrides = req.ecsPropertiesOverride().taskProperties()[0].containers()[0] then: handler.getAwsOptions() >> { new AwsOptions(awsConfig: new AwsConfig(batch:[cliPath: '/bin/aws'],region: 'eu-west-1')) } and: @@ -202,12 +207,12 @@ class AwsBatchTaskHandlerTest extends Specification { 1 * handler.getJobQueue(task) >> 'queue1' 1 * handler.getJobDefinition(task) >> 'job-def:1' and: - def res = req.containerOverrides().resourceRequirements() + def res = overrides.resourceRequirements() res.size()==3 and: - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '2048' - req.containerOverrides().resourceRequirements().find { it.type() == ResourceType.GPU}.value() == '2' + overrides.resourceRequirements().find { it.type() == ResourceType.VCPU}.value() == '4' + overrides.resourceRequirements().find { it.type() == ResourceType.MEMORY}.value() == '2048' + overrides.resourceRequirements().find { it.type() == ResourceType.GPU}.value() == '2' } def 'should create an aws submit request with a timeout'() { @@ -305,7 +310,7 @@ class AwsBatchTaskHandlerTest extends Specification { .attempts(3) .evaluateOnExit( EvaluateOnExit.builder().action('RETRY').onStatusReason('Host EC2*').build(), EvaluateOnExit.builder().onReason('*').action('EXIT').build() ).build() - req.containerOverrides().environment() == [VAR_RETRY_MODE, VAR_MAX_ATTEMPTS, VAR_METADATA_ATTEMPTS] + req.ecsPropertiesOverride().taskProperties()[0].containers()[0].environment() == [VAR_RETRY_MODE, VAR_MAX_ATTEMPTS, VAR_METADATA_ATTEMPTS] } def 'should return job queue'() { @@ -526,31 +531,32 @@ class AwsBatchTaskHandlerTest extends Specification { handler.addVolumeMountsToContainer(mounts, containerModel) when: - def container = containerModel.toBatchContainerProperties() + def taskProps = containerModel.toBatchContainerProperties() + def container = taskProps.containers()[0] then: - container.volumes().size() == 4 + taskProps.volumes().size() == 4 container.mountPoints().size() == 4 - container.volumes()[0].name() == 'vol0' - container.volumes()[0].host().sourcePath() == '/foo' + taskProps.volumes()[0].name() == 'vol0' + taskProps.volumes()[0].host().sourcePath() == '/foo' container.mountPoints()[0].sourceVolume() == 'vol0' container.mountPoints()[0].containerPath() == '/foo' !container.mountPoints()[0].readOnly() - container.volumes()[1].name() == 'vol1' - container.volumes()[1].host().sourcePath() == '/foo' + taskProps.volumes()[1].name() == 'vol1' + taskProps.volumes()[1].host().sourcePath() == '/foo' container.mountPoints()[1].sourceVolume() == 'vol1' container.mountPoints()[1].containerPath() == '/bar' !container.mountPoints()[1].readOnly() - container.volumes()[2].name() == 'vol2' - container.volumes()[2].host().sourcePath() == '/here' + taskProps.volumes()[2].name() == 'vol2' + taskProps.volumes()[2].host().sourcePath() == '/here' container.mountPoints()[2].sourceVolume() == 'vol2' container.mountPoints()[2].containerPath() == '/there' container.mountPoints()[2].readOnly() - container.volumes()[3].name() == 'vol3' - container.volumes()[3].host().sourcePath() == '/this' + taskProps.volumes()[3].name() == 'vol3' + taskProps.volumes()[3].host().sourcePath() == '/this' container.mountPoints()[3].sourceVolume() == 'vol3' container.mountPoints()[3].containerPath() == '/that' !container.mountPoints()[3].readOnly() @@ -986,6 +992,7 @@ class AwsBatchTaskHandlerTest extends Specification { when: def req = handler.newSubmitRequest(task) + def overrides = req.ecsPropertiesOverride().taskProperties()[0].containers()[0] then: 1 * handler.getSubmitCommand() >> ['sh', '-c', 'hello'] 1 * handler.maxSpotAttempts() >> 5 @@ -997,10 +1004,10 @@ class AwsBatchTaskHandlerTest extends Specification { req.jobName() == 'batch-task' req.jobQueue() == 'queue1' req.jobDefinition() == 'job-def:1' - req.containerOverrides().resourceRequirements().find { it.type()==ResourceType.VCPU}.value() == '4' - req.containerOverrides().resourceRequirements().find { it.type()==ResourceType.MEMORY}.value() == '8192' - req.containerOverrides().environment() == [VAR_FOO, VAR_BAR] - req.containerOverrides().command() == ['sh', '-c','hello'] + overrides.resourceRequirements().find { it.type()==ResourceType.VCPU}.value() == '4' + overrides.resourceRequirements().find { it.type()==ResourceType.MEMORY}.value() == '8192' + overrides.environment() == [VAR_FOO, VAR_BAR] + overrides.command() == ['sh', '-c','hello'] req.retryStrategy() == RetryStrategy.builder() .attempts(5) .evaluateOnExit( EvaluateOnExit.builder().action('RETRY').onStatusReason('Host EC2*').build(), diff --git a/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/ContainerPropertiesModelTest.groovy b/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/ContainerPropertiesModelTest.groovy index 510acc5a7f..5da6525c66 100644 --- a/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/ContainerPropertiesModelTest.groovy +++ b/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/ContainerPropertiesModelTest.groovy @@ -1,6 +1,6 @@ package nextflow.cloud.aws.batch.model -import software.amazon.awssdk.services.batch.model.ContainerProperties +import software.amazon.awssdk.services.batch.model.EcsTaskProperties import software.amazon.awssdk.services.batch.model.EphemeralStorage import software.amazon.awssdk.services.batch.model.KeyValuePair import software.amazon.awssdk.services.batch.model.LinuxParameters @@ -10,6 +10,7 @@ import software.amazon.awssdk.services.batch.model.NetworkConfiguration import software.amazon.awssdk.services.batch.model.ResourceRequirement import software.amazon.awssdk.services.batch.model.ResourceType import software.amazon.awssdk.services.batch.model.RuntimePlatform +import software.amazon.awssdk.services.batch.model.TaskContainerProperties import software.amazon.awssdk.services.batch.model.Ulimit import software.amazon.awssdk.services.batch.model.Volume import spock.lang.Specification @@ -518,16 +519,19 @@ class ContainerPropertiesModelTest extends Specification { .ephemeralStorage(ephemeralStorage) .runtimePlatform(runtimePlatform) - def containerProperties = model.toBatchContainerProperties() + def taskProperties = model.toBatchContainerProperties() then: - containerProperties instanceof ContainerProperties + taskProperties instanceof EcsTaskProperties + + def containerProperties = taskProperties.containers()[0] + containerProperties instanceof TaskContainerProperties containerProperties.image() == 'ubuntu:20.04' containerProperties.command() == ['echo', 'hello'] containerProperties.resourceRequirements().size() == 1 containerProperties.resourceRequirements()[0] == req - containerProperties.jobRoleArn() == 'arn:aws:iam::123456789012:role/BatchJobRole' - containerProperties.executionRoleArn() == 'arn:aws:iam::123456789012:role/BatchExecutionRole' + taskProperties.taskRoleArn() == 'arn:aws:iam::123456789012:role/BatchJobRole' + taskProperties.executionRoleArn() == 'arn:aws:iam::123456789012:role/BatchExecutionRole' containerProperties.linuxParameters() == linuxParams containerProperties.environment().size() == 1 containerProperties.environment()[0].name() == 'VAR1' @@ -539,11 +543,11 @@ class ContainerPropertiesModelTest extends Specification { containerProperties.logConfiguration() == logConfig containerProperties.mountPoints().size() == 1 containerProperties.mountPoints()[0].sourceVolume() == 'tmp' - containerProperties.volumes().size() == 1 - containerProperties.volumes()[0].name() == 'tmp' - containerProperties.networkConfiguration() == networkConfig - containerProperties.ephemeralStorage() == ephemeralStorage - containerProperties.runtimePlatform() == runtimePlatform + taskProperties.volumes().size() == 1 + taskProperties.volumes()[0].name() == 'tmp' + taskProperties.networkConfiguration() == networkConfig + taskProperties.ephemeralStorage() == ephemeralStorage + taskProperties.runtimePlatform() == runtimePlatform } def 'should convert to ContainerProperties with null fields'() { @@ -551,15 +555,18 @@ class ContainerPropertiesModelTest extends Specification { def model = new ContainerPropertiesModel() when: - def containerProperties = model.toBatchContainerProperties() + def taskProperties = model.toBatchContainerProperties() then: - containerProperties instanceof ContainerProperties + taskProperties instanceof EcsTaskProperties + + def containerProperties = taskProperties.containers()[0] + containerProperties instanceof TaskContainerProperties containerProperties.image() == null containerProperties.command() == [] containerProperties.resourceRequirements() == [] - containerProperties.jobRoleArn() == null - containerProperties.executionRoleArn() == null + taskProperties.taskRoleArn() == null + taskProperties.executionRoleArn() == null containerProperties.linuxParameters() == null containerProperties.environment() == [] containerProperties.privileged() == null @@ -568,10 +575,10 @@ class ContainerPropertiesModelTest extends Specification { containerProperties.ulimits() == [] containerProperties.logConfiguration() == null containerProperties.mountPoints() == [] - containerProperties.volumes() == [] - containerProperties.networkConfiguration() == null - containerProperties.ephemeralStorage() == null - containerProperties.runtimePlatform() == null + taskProperties.volumes() == [] + taskProperties.networkConfiguration() == null + taskProperties.ephemeralStorage() == null + taskProperties.runtimePlatform() == null } def 'should convert to ContainerProperties with empty collections'() { @@ -584,13 +591,16 @@ class ContainerPropertiesModelTest extends Specification { .mountPoints([]) .volumes([]) - def containerProperties = model.toBatchContainerProperties() + def taskProperties = model.toBatchContainerProperties() then: - containerProperties instanceof ContainerProperties + taskProperties instanceof EcsTaskProperties + + def containerProperties = taskProperties.containers()[0] + containerProperties instanceof TaskContainerProperties containerProperties.environment() == [] containerProperties.ulimits() == [] containerProperties.mountPoints() == [] - containerProperties.volumes() == [] + taskProperties.volumes() == [] } } diff --git a/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/RegisterJobDefinitionModelTest.groovy b/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/RegisterJobDefinitionModelTest.groovy index 601e23436d..358e083d50 100644 --- a/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/RegisterJobDefinitionModelTest.groovy +++ b/plugins/nf-amazon/src/test/nextflow/cloud/aws/batch/model/RegisterJobDefinitionModelTest.groovy @@ -233,11 +233,13 @@ class RegisterJobDefinitionModelTest extends Specification { then: request instanceof RegisterJobDefinitionRequest + request.jobDefinitionName() == 'test-job-def' request.type() == JobDefinitionType.CONTAINER request.platformCapabilities() == capabilities - request.containerProperties() != null - request.containerProperties().image() == 'ubuntu:20.04' + def container = request.ecsProperties().taskProperties()[0].containers()[0] + container != null + container.image() == 'ubuntu:20.04' request.parameters() == params request.tags() == tags } @@ -254,7 +256,7 @@ class RegisterJobDefinitionModelTest extends Specification { !request.jobDefinitionName() !request.type() !request.platformCapabilities() - !request.containerProperties() + !request.ecsProperties() !request.parameters() !request.tags() } @@ -276,8 +278,8 @@ class RegisterJobDefinitionModelTest extends Specification { request instanceof RegisterJobDefinitionRequest request.jobDefinitionName() == 'minimal-job' request.type() == JobDefinitionType.CONTAINER - request.containerProperties() != null - request.containerProperties().image() == 'nginx' + request.ecsProperties() != null + request.ecsProperties().taskProperties()[0].containers()[0].image() == 'nginx' !request.platformCapabilities() !request.parameters() !request.tags() @@ -303,7 +305,7 @@ class RegisterJobDefinitionModelTest extends Specification { request.jobDefinitionName() == 'empty-collections-job' request.type() == JobDefinitionType.CONTAINER request.platformCapabilities() == [] - request.containerProperties() != null + request.ecsProperties() != null request.parameters() == [:] request.tags() == [:] } @@ -327,7 +329,7 @@ class RegisterJobDefinitionModelTest extends Specification { request instanceof RegisterJobDefinitionRequest request.jobDefinitionName() == 'chained-job' request.type() == JobDefinitionType.CONTAINER - request.containerProperties().image() == 'alpine' + request.ecsProperties().taskProperties()[0].containers()[0].image() == 'alpine' request.tags().size() == 2 request.tags()['env'] == 'test' request.tags()['project'] == 'nextflow'