From e6d3dd3328a74fd8ee8868a2fa88eada4326c560 Mon Sep 17 00:00:00 2001 From: Abhinav Sharma Date: Mon, 15 Jul 2024 18:07:20 +0200 Subject: [PATCH] Constraints refactor to introduce a specific models package (#68) * refactor the package organization to create a separate package for models * Refactor the test folder and add license headers --- .../nomad/config/ConstraintAttrSpec.groovy | 38 ------- .../nomad/config/ConstraintNodeSpec.groovy | 81 -------------- .../nomad/config/ConstraintsSpec.groovy | 38 ------- .../nextflow/nomad/config/NomadJobOpts.groovy | 34 +++--- .../nomad/executor/ConstraintsBuilder.groovy | 12 +- .../nomad/executor/NomadService.groovy | 14 +-- .../JobAffinity.groovy} | 12 +- .../JobConstraint.groovy} | 10 +- .../nomad/models/JobConstraints.groovy | 61 ++++++++++ .../nomad/models/JobConstraintsAttr.groovy | 62 +++++++++++ .../nomad/models/JobConstraintsNode.groovy | 105 ++++++++++++++++++ .../JobVolume.groovy} | 14 +-- .../nomad/config/NomadConfigSpec.groovy | 22 ++-- ...Spec.groovy => NomadJobConstraints.groovy} | 2 +- .../JobConstraintsSpec.groovy} | 6 +- validation/sun-nomadlab/nextflow.config | 10 +- 16 files changed, 301 insertions(+), 220 deletions(-) delete mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintAttrSpec.groovy delete mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintNodeSpec.groovy delete mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintsSpec.groovy rename plugins/nf-nomad/src/main/nextflow/nomad/{config/AffinitySpec.groovy => models/JobAffinity.groovy} (86%) rename plugins/nf-nomad/src/main/nextflow/nomad/{config/ConstraintSpec.groovy => models/JobConstraint.groovy} (86%) create mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraints.groovy create mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsAttr.groovy create mode 100644 plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsNode.groovy rename plugins/nf-nomad/src/main/nextflow/nomad/{config/VolumeSpec.groovy => models/JobVolume.groovy} (92%) rename plugins/nf-nomad/src/test/nextflow/nomad/config/{NomadConstraintsSpec.groovy => NomadJobConstraints.groovy} (98%) rename plugins/nf-nomad/src/test/nextflow/nomad/{executor/NomadServiceConstraintsSpec.groovy => models/JobConstraintsSpec.groovy} (98%) diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintAttrSpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintAttrSpec.groovy deleted file mode 100644 index 0e3cda8..0000000 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintAttrSpec.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package nextflow.nomad.config - -class ConstraintAttrSpec { - - private String arch = null - private Integer numcores= null - private Integer reservablecores= null - private Double totalcompute= null - - String getArch() { - return arch - } - - Integer getNumcores() { - return numcores - } - - Integer getReservablecores() { - return reservablecores - } - - Double getTotalcompute() { - return totalcompute - } - - ConstraintAttrSpec setCpu(Map map){ - cpu(map) - } - - ConstraintAttrSpec cpu(Map map){ - this.arch = map.containsKey("arch") ? map["arch"].toString() : null - this.numcores = map.containsKey("numcores") ? map["numcores"] as int : null - this.reservablecores = map.containsKey("reservablecores") ? map["reservablecores"] as int : null - this.totalcompute = map.containsKey("totalcompute") ? map["totalcompute"] as double : null - this - } - -} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintNodeSpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintNodeSpec.groovy deleted file mode 100644 index 6260175..0000000 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintNodeSpec.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package nextflow.nomad.config - -class ConstraintNodeSpec { - - private String id = null - private String name = null - private String clientClass = null - private String pool = null - private String dataCenter = null - private String region = null - - String getId() { - return id - } - - String getName() { - return name - } - - String getClientClass() { - return clientClass - } - - String getPool() { - return pool - } - - String getDataCenter() { - return dataCenter - } - - String getRegion() { - return region - } - - ConstraintNodeSpec setUnique(Map map){ - unique(map) - } - - ConstraintNodeSpec unique(Map map){ - this.id = map.containsKey("id") ? map["id"].toString() : null - this.name = map.containsKey("name") ? map["name"].toString() : null - this - } - - ConstraintNodeSpec setClientClass(Object map){ - clientClass(map) - } - - ConstraintNodeSpec clientClass(Object clientClass){ - this.clientClass = clientClass.toString() - this - } - - ConstraintNodeSpec setPool(Object map){ - pool(map) - } - - ConstraintNodeSpec pool(Object pool){ - this.pool = pool.toString() - this - } - - ConstraintNodeSpec setDataCenter(Object map){ - dataCenter(map) - } - - ConstraintNodeSpec dataCenter(Object dataCenter){ - this.dataCenter = dataCenter.toString() - this - } - - ConstraintNodeSpec setRegion(Object map){ - region(map) - } - - ConstraintNodeSpec region(Object region){ - this.region = region.toString() - this - } -} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintsSpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintsSpec.groovy deleted file mode 100644 index 0de58da..0000000 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintsSpec.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package nextflow.nomad.config - -class ConstraintsSpec { - - List nodeSpecs = [] - List attrSpecs = [] - - ConstraintsSpec node( @DelegatesTo(ConstraintNodeSpec)Closure closure){ - ConstraintNodeSpec constraintSpec = new ConstraintNodeSpec() - def clone = closure.rehydrate(constraintSpec, closure.owner, closure.thisObject) - clone.resolveStrategy = Closure.DELEGATE_FIRST - clone() - nodeSpecs << constraintSpec - this - } - - ConstraintsSpec attr( @DelegatesTo(ConstraintAttrSpec)Closure closure){ - ConstraintAttrSpec constraintSpec = new ConstraintAttrSpec() - def clone = closure.rehydrate(constraintSpec, closure.owner, closure.thisObject) - clone.resolveStrategy = Closure.DELEGATE_FIRST - clone() - attrSpecs << constraintSpec - this - } - - void validate(){ - - } - - static ConstraintsSpec parse(@DelegatesTo(ConstraintsSpec)Closure closure){ - ConstraintsSpec constraintsSpec = new ConstraintsSpec() - def clone = closure.rehydrate(constraintsSpec, closure.owner, closure.thisObject) - clone.resolveStrategy = Closure.DELEGATE_FIRST - clone() - constraintsSpec.validate() - constraintsSpec - } -} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/NomadJobOpts.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/config/NomadJobOpts.groovy index ea0b001..a31dd3f 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/NomadJobOpts.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/config/NomadJobOpts.groovy @@ -19,6 +19,10 @@ package nextflow.nomad.config import groovy.transform.CompileStatic import groovy.util.logging.Slf4j +import nextflow.nomad.models.JobAffinity +import nextflow.nomad.models.JobConstraint +import nextflow.nomad.models.JobConstraints +import nextflow.nomad.models.JobVolume /** @@ -37,11 +41,11 @@ class NomadJobOpts{ String region String namespace String dockerVolume - VolumeSpec[] volumeSpec - AffinitySpec affinitySpec - ConstraintSpec constraintSpec + JobVolume[] volumeSpec + JobAffinity affinitySpec + JobConstraint constraintSpec - ConstraintsSpec constraintsSpec + JobConstraints constraintsSpec NomadJobOpts(Map nomadJobOpts, Map env=null){ assert nomadJobOpts!=null @@ -74,10 +78,10 @@ class NomadJobOpts{ this.constraintsSpec = parseConstraints(nomadJobOpts) } - VolumeSpec[] parseVolumes(Map nomadJobOpts){ - List ret = [] + JobVolume[] parseVolumes(Map nomadJobOpts){ + List ret = [] if( nomadJobOpts.volume && nomadJobOpts.volume instanceof Closure){ - def volumeSpec = new VolumeSpec() + def volumeSpec = new JobVolume() def closure = (nomadJobOpts.volume as Closure) def clone = closure.rehydrate(volumeSpec, closure.owner, closure.thisObject) clone.resolveStrategy = Closure.DELEGATE_FIRST @@ -89,7 +93,7 @@ class NomadJobOpts{ if( nomadJobOpts.volumes && nomadJobOpts.volumes instanceof List){ nomadJobOpts.volumes.each{ closure -> if( closure instanceof Closure){ - def volumeSpec = new VolumeSpec() + def volumeSpec = new JobVolume() def clone = closure.rehydrate(volumeSpec, closure.owner, closure.thisObject) clone.resolveStrategy = Closure.DELEGATE_FIRST clone() @@ -108,13 +112,13 @@ class NomadJobOpts{ throw new IllegalArgumentException("No more than a workdir volume allowed") } - return ret as VolumeSpec[] + return ret as JobVolume[] } - AffinitySpec parseAffinity(Map nomadJobOpts) { + JobAffinity parseAffinity(Map nomadJobOpts) { if (nomadJobOpts.affinity && nomadJobOpts.affinity instanceof Closure) { log.info "affinity config will be deprecated, use affinities closure instead" - def affinitySpec = new AffinitySpec() + def affinitySpec = new JobAffinity() def closure = (nomadJobOpts.affinity as Closure) def clone = closure.rehydrate(affinitySpec, closure.owner, closure.thisObject) clone.resolveStrategy = Closure.DELEGATE_FIRST @@ -126,10 +130,10 @@ class NomadJobOpts{ } } - ConstraintSpec parseConstraint(Map nomadJobOpts){ + JobConstraint parseConstraint(Map nomadJobOpts){ if (nomadJobOpts.constraint && nomadJobOpts.constraint instanceof Closure) { log.info "constraint config will be deprecated, use constraints closure instead" - def constraintSpec = new ConstraintSpec() + def constraintSpec = new JobConstraint() def closure = (nomadJobOpts.constraint as Closure) def clone = closure.rehydrate(constraintSpec, closure.owner, closure.thisObject) clone.resolveStrategy = Closure.DELEGATE_FIRST @@ -141,9 +145,9 @@ class NomadJobOpts{ } } - ConstraintsSpec parseConstraints(Map nomadJobOpts){ + JobConstraints parseConstraints(Map nomadJobOpts){ if (nomadJobOpts.constraints && nomadJobOpts.constraints instanceof Closure) { - def constraintsSpec = new ConstraintsSpec() + def constraintsSpec = new JobConstraints() def closure = (nomadJobOpts.constraints as Closure) def clone = closure.rehydrate(constraintsSpec, closure.owner, closure.thisObject) clone.resolveStrategy = Closure.DELEGATE_FIRST diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/executor/ConstraintsBuilder.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/executor/ConstraintsBuilder.groovy index 5c5cc05..bfd187b 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/executor/ConstraintsBuilder.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/executor/ConstraintsBuilder.groovy @@ -1,13 +1,13 @@ package nextflow.nomad.executor import io.nomadproject.client.model.Constraint -import nextflow.nomad.config.ConstraintAttrSpec -import nextflow.nomad.config.ConstraintNodeSpec -import nextflow.nomad.config.ConstraintsSpec +import nextflow.nomad.models.JobConstraintsAttr +import nextflow.nomad.models.JobConstraintsNode +import nextflow.nomad.models.JobConstraints class ConstraintsBuilder { - protected static List constraintsSpecToList(ConstraintsSpec spec){ + protected static List constraintsSpecToList(JobConstraints spec){ def constraints = [] as List if( spec?.nodeSpecs ){ def nodes = spec.nodeSpecs @@ -24,7 +24,7 @@ class ConstraintsBuilder { return constraints } - protected static List nodeConstraints(ConstraintNodeSpec nodeSpec){ + protected static List nodeConstraints(JobConstraintsNode nodeSpec){ def ret = [] as List if( nodeSpec.id ){ ret.add new Constraint() @@ -65,7 +65,7 @@ class ConstraintsBuilder { ret } - protected static List attrConstraints(ConstraintAttrSpec nodeSpec) { + protected static List attrConstraints(JobConstraintsAttr nodeSpec) { def ret = [] as List if (nodeSpec.arch) { ret.add new Constraint() diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/executor/NomadService.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/executor/NomadService.groovy index cd800c9..bc9ca50 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/executor/NomadService.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/executor/NomadService.groovy @@ -22,9 +22,9 @@ import groovy.util.logging.Slf4j import io.nomadproject.client.ApiClient import io.nomadproject.client.api.JobsApi import io.nomadproject.client.model.* -import nextflow.nomad.config.ConstraintsSpec +import nextflow.nomad.models.JobConstraints import nextflow.nomad.config.NomadConfig -import nextflow.nomad.config.VolumeSpec +import nextflow.nomad.models.JobVolume import nextflow.processor.TaskRun import nextflow.util.MemoryUnit import nextflow.exception.ProcessSubmitException @@ -136,7 +136,7 @@ class NomadService implements Closeable{ if( config.jobOpts().volumeSpec ) { taskGroup.volumes = [:] config.jobOpts().volumeSpec.eachWithIndex { volumeSpec , idx-> - if (volumeSpec && volumeSpec.type == VolumeSpec.VOLUME_CSI_TYPE) { + if (volumeSpec && volumeSpec.type == JobVolume.VOLUME_CSI_TYPE) { taskGroup.volumes["vol_${idx}".toString()] = new VolumeRequest( type: volumeSpec.type, source: volumeSpec.name, @@ -146,7 +146,7 @@ class NomadService implements Closeable{ ) } - if (volumeSpec && volumeSpec.type == VolumeSpec.VOLUME_HOST_TYPE) { + if (volumeSpec && volumeSpec.type == JobVolume.VOLUME_HOST_TYPE) { taskGroup.volumes["vol_${idx}".toString()] = new VolumeRequest( type: volumeSpec.type, source: volumeSpec.name, @@ -183,7 +183,7 @@ class NomadService implements Closeable{ volumes(task, taskDef, workingDir) affinity(task, taskDef) - constrain(task, taskDef) + constraint(task, taskDef) constraints(task, taskDef) return taskDef @@ -235,7 +235,7 @@ class NomadService implements Closeable{ taskDef } - protected Task constrain(TaskRun task, Task taskDef){ + protected Task constraint(TaskRun task, Task taskDef){ if( config.jobOpts().constraintSpec ){ def constraint = new Constraint() if(config.jobOpts().constraintSpec.attribute){ @@ -264,7 +264,7 @@ class NomadService implements Closeable{ if( task.processor?.config?.get(TaskDirectives.CONSTRAINTS) && task.processor?.config?.get(TaskDirectives.CONSTRAINTS) instanceof Closure) { Closure closure = task.processor?.config?.get(TaskDirectives.CONSTRAINTS) as Closure - ConstraintsSpec constraintsSpec = ConstraintsSpec.parse(closure) + JobConstraints constraintsSpec = JobConstraints.parse(closure) def list = ConstraintsBuilder.constraintsSpecToList(constraintsSpec) constraints.addAll(list) } diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/AffinitySpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobAffinity.groovy similarity index 86% rename from plugins/nf-nomad/src/main/nextflow/nomad/config/AffinitySpec.groovy rename to plugins/nf-nomad/src/main/nextflow/nomad/models/JobAffinity.groovy index 7d8277e..9e96584 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/AffinitySpec.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobAffinity.groovy @@ -15,13 +15,13 @@ * limitations under the License. */ -package nextflow.nomad.config +package nextflow.nomad.models /** * Nomad Job Affinity Spec * * @author Jorge Aguilera */ -class AffinitySpec{ +class JobAffinity { private String attribute private String operator @@ -44,22 +44,22 @@ class AffinitySpec{ return weight } - AffinitySpec attribute(String attribute){ + JobAffinity attribute(String attribute){ this.attribute=attribute this } - AffinitySpec operator(String operator){ + JobAffinity operator(String operator){ this.operator = operator this } - AffinitySpec value(String value){ + JobAffinity value(String value){ this.value = value this } - AffinitySpec weight(int weight){ + JobAffinity weight(int weight){ this.weight = weight this } diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintSpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraint.groovy similarity index 86% rename from plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintSpec.groovy rename to plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraint.groovy index 266bfd2..22a57f1 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/ConstraintSpec.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraint.groovy @@ -15,14 +15,14 @@ * limitations under the License. */ -package nextflow.nomad.config +package nextflow.nomad.models /** * Nomad Job Constraint Spec * * @author Jorge Aguilera */ -class ConstraintSpec { +class JobConstraint { private String attribute private String operator @@ -40,17 +40,17 @@ class ConstraintSpec { return value } - ConstraintSpec attribute(String attribute){ + JobConstraint attribute(String attribute){ this.attribute=attribute this } - ConstraintSpec operator(String operator){ + JobConstraint operator(String operator){ this.operator = operator this } - ConstraintSpec value(String value){ + JobConstraint value(String value){ this.value = value this } diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraints.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraints.groovy new file mode 100644 index 0000000..dff45d5 --- /dev/null +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraints.groovy @@ -0,0 +1,61 @@ +/* + * Copyright 2023-, Stellenbosch University, South Africa + * Copyright 2024, Evaluacion y Desarrollo de Negocios, Spain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package nextflow.nomad.models + +/** + * Nomad Job Constraint Spec + * + * @author Jorge Aguilera + */ + +class JobConstraints { + + List nodeSpecs = [] + List attrSpecs = [] + + JobConstraints node(@DelegatesTo(JobConstraintsNode)Closure closure){ + JobConstraintsNode constraintSpec = new JobConstraintsNode() + def clone = closure.rehydrate(constraintSpec, closure.owner, closure.thisObject) + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone() + nodeSpecs << constraintSpec + this + } + + JobConstraints attr(@DelegatesTo(JobConstraintsAttr)Closure closure){ + JobConstraintsAttr constraintSpec = new JobConstraintsAttr() + def clone = closure.rehydrate(constraintSpec, closure.owner, closure.thisObject) + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone() + attrSpecs << constraintSpec + this + } + + void validate(){ + + } + + static JobConstraints parse(@DelegatesTo(JobConstraints)Closure closure){ + JobConstraints constraintsSpec = new JobConstraints() + def clone = closure.rehydrate(constraintsSpec, closure.owner, closure.thisObject) + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone() + constraintsSpec.validate() + constraintsSpec + } +} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsAttr.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsAttr.groovy new file mode 100644 index 0000000..5b0c1eb --- /dev/null +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsAttr.groovy @@ -0,0 +1,62 @@ +/* + * Copyright 2023-, Stellenbosch University, South Africa + * Copyright 2024, Evaluacion y Desarrollo de Negocios, Spain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package nextflow.nomad.models + +/** + * Nomad Job Constraint Spec + * + * @author Jorge Aguilera + */ + +class JobConstraintsAttr { + + private String arch = null + private Integer numcores= null + private Integer reservablecores= null + private Double totalcompute= null + + String getArch() { + return arch + } + + Integer getNumcores() { + return numcores + } + + Integer getReservablecores() { + return reservablecores + } + + Double getTotalcompute() { + return totalcompute + } + + JobConstraintsAttr setCpu(Map map){ + cpu(map) + } + + JobConstraintsAttr cpu(Map map){ + this.arch = map.containsKey("arch") ? map["arch"].toString() : null + this.numcores = map.containsKey("numcores") ? map["numcores"] as int : null + this.reservablecores = map.containsKey("reservablecores") ? map["reservablecores"] as int : null + this.totalcompute = map.containsKey("totalcompute") ? map["totalcompute"] as double : null + this + } + +} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsNode.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsNode.groovy new file mode 100644 index 0000000..f02f4fa --- /dev/null +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobConstraintsNode.groovy @@ -0,0 +1,105 @@ +/* + * Copyright 2023-, Stellenbosch University, South Africa + * Copyright 2024, Evaluacion y Desarrollo de Negocios, Spain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package nextflow.nomad.models + +/** + * Nomad Job Constraint Spec + * + * @author Jorge Aguilera + */ + +class JobConstraintsNode { + + private String id = null + private String name = null + private String clientClass = null + private String pool = null + private String dataCenter = null + private String region = null + + String getId() { + return id + } + + String getName() { + return name + } + + String getClientClass() { + return clientClass + } + + String getPool() { + return pool + } + + String getDataCenter() { + return dataCenter + } + + String getRegion() { + return region + } + + JobConstraintsNode setUnique(Map map){ + unique(map) + } + + JobConstraintsNode unique(Map map){ + this.id = map.containsKey("id") ? map["id"].toString() : null + this.name = map.containsKey("name") ? map["name"].toString() : null + this + } + + JobConstraintsNode setClientClass(Object map){ + clientClass(map) + } + + JobConstraintsNode clientClass(Object clientClass){ + this.clientClass = clientClass.toString() + this + } + + JobConstraintsNode setPool(Object map){ + pool(map) + } + + JobConstraintsNode pool(Object pool){ + this.pool = pool.toString() + this + } + + JobConstraintsNode setDataCenter(Object map){ + dataCenter(map) + } + + JobConstraintsNode dataCenter(Object dataCenter){ + this.dataCenter = dataCenter.toString() + this + } + + JobConstraintsNode setRegion(Object map){ + region(map) + } + + JobConstraintsNode region(Object region){ + this.region = region.toString() + this + } +} diff --git a/plugins/nf-nomad/src/main/nextflow/nomad/config/VolumeSpec.groovy b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobVolume.groovy similarity index 92% rename from plugins/nf-nomad/src/main/nextflow/nomad/config/VolumeSpec.groovy rename to plugins/nf-nomad/src/main/nextflow/nomad/models/JobVolume.groovy index 529439b..70d3c80 100644 --- a/plugins/nf-nomad/src/main/nextflow/nomad/config/VolumeSpec.groovy +++ b/plugins/nf-nomad/src/main/nextflow/nomad/models/JobVolume.groovy @@ -15,13 +15,13 @@ * limitations under the License. */ -package nextflow.nomad.config +package nextflow.nomad.models /** * Nomad Volume Spec * * @author Jorge Aguilera */ -class VolumeSpec { +class JobVolume { final static public String VOLUME_DOCKER_TYPE = "docker" final static public String VOLUME_CSI_TYPE = "csi" @@ -57,27 +57,27 @@ class VolumeSpec { return readOnly } - VolumeSpec type(String type){ + JobVolume type(String type){ this.type = type this } - VolumeSpec name(String name){ + JobVolume name(String name){ this.name = name this } - VolumeSpec workDir(boolean b){ + JobVolume workDir(boolean b){ this.workDir = b this } - VolumeSpec path(String path){ + JobVolume path(String path){ this.path = path this } - VolumeSpec readOnly(boolean readOnly){ + JobVolume readOnly(boolean readOnly){ this.readOnly = readOnly this } diff --git a/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConfigSpec.groovy b/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConfigSpec.groovy index 749b87f..3856a57 100644 --- a/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConfigSpec.groovy +++ b/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConfigSpec.groovy @@ -17,8 +17,8 @@ package nextflow.nomad.config -import nextflow.nomad.config.NomadConfig -import nextflow.nomad.config.VolumeSpec + +import nextflow.nomad.models.JobVolume import spock.lang.Specification import spock.lang.Unroll @@ -140,7 +140,7 @@ class NomadConfigSpec extends Specification { then: config.jobOpts.volumeSpec - config.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_DOCKER_TYPE + config.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_DOCKER_TYPE config.jobOpts.volumeSpec[0].name == "test" when: @@ -150,7 +150,7 @@ class NomadConfigSpec extends Specification { then: config2.jobOpts.volumeSpec - config2.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_CSI_TYPE + config2.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_CSI_TYPE config2.jobOpts.volumeSpec[0].name == "test" when: @@ -160,7 +160,7 @@ class NomadConfigSpec extends Specification { then: config3.jobOpts.volumeSpec - config3.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_HOST_TYPE + config3.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_HOST_TYPE config3.jobOpts.volumeSpec[0].name == "test" when: @@ -220,7 +220,7 @@ class NomadConfigSpec extends Specification { then: config.jobOpts.volumeSpec - config.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_DOCKER_TYPE + config.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_DOCKER_TYPE config.jobOpts.volumeSpec[0].name == "test" config.jobOpts.volumeSpec[0].workDir @@ -249,9 +249,9 @@ class NomadConfigSpec extends Specification { then: config2.jobOpts.volumeSpec.size()==2 - config2.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_CSI_TYPE + config2.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_CSI_TYPE config2.jobOpts.volumeSpec[0].name == "test" - config2.jobOpts.volumeSpec[1].type == VolumeSpec.VOLUME_DOCKER_TYPE + config2.jobOpts.volumeSpec[1].type == JobVolume.VOLUME_DOCKER_TYPE config2.jobOpts.volumeSpec[1].name == "test" config.jobOpts.volumeSpec[0].workDir @@ -270,9 +270,9 @@ class NomadConfigSpec extends Specification { then: config3.jobOpts.volumeSpec.size()==3 - config3.jobOpts.volumeSpec[0].type == VolumeSpec.VOLUME_CSI_TYPE - config3.jobOpts.volumeSpec[1].type == VolumeSpec.VOLUME_CSI_TYPE - config3.jobOpts.volumeSpec[2].type == VolumeSpec.VOLUME_DOCKER_TYPE + config3.jobOpts.volumeSpec[0].type == JobVolume.VOLUME_CSI_TYPE + config3.jobOpts.volumeSpec[1].type == JobVolume.VOLUME_CSI_TYPE + config3.jobOpts.volumeSpec[2].type == JobVolume.VOLUME_DOCKER_TYPE config3.jobOpts.volumeSpec[0].workDir config3.jobOpts.volumeSpec.findAll{ it.workDir}.size() == 1 diff --git a/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConstraintsSpec.groovy b/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadJobConstraints.groovy similarity index 98% rename from plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConstraintsSpec.groovy rename to plugins/nf-nomad/src/test/nextflow/nomad/config/NomadJobConstraints.groovy index 43bb352..d4b9692 100644 --- a/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadConstraintsSpec.groovy +++ b/plugins/nf-nomad/src/test/nextflow/nomad/config/NomadJobConstraints.groovy @@ -25,7 +25,7 @@ import spock.lang.Specification * @author : Jorge Aguilera * @author : Abhinav Sharma */ -class NomadConstraintsSpec extends Specification { +class NomadJobConstraints extends Specification { void "should instantiate a constraints spec if specified"() { diff --git a/plugins/nf-nomad/src/test/nextflow/nomad/executor/NomadServiceConstraintsSpec.groovy b/plugins/nf-nomad/src/test/nextflow/nomad/models/JobConstraintsSpec.groovy similarity index 98% rename from plugins/nf-nomad/src/test/nextflow/nomad/executor/NomadServiceConstraintsSpec.groovy rename to plugins/nf-nomad/src/test/nextflow/nomad/models/JobConstraintsSpec.groovy index 11a2d77..1e57c6c 100644 --- a/plugins/nf-nomad/src/test/nextflow/nomad/executor/NomadServiceConstraintsSpec.groovy +++ b/plugins/nf-nomad/src/test/nextflow/nomad/models/JobConstraintsSpec.groovy @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package nextflow.nomad.executor + +package nextflow.nomad.models import groovy.json.JsonOutput import groovy.json.JsonSlurper import nextflow.executor.Executor import nextflow.nomad.config.NomadConfig +import nextflow.nomad.executor.NomadService import nextflow.processor.TaskBean import nextflow.processor.TaskConfig import nextflow.processor.TaskProcessor @@ -39,7 +41,7 @@ import java.nio.file.Path * * @author : Jorge Aguilera */ -class NomadServiceConstraintsSpec extends Specification{ +class JobConstraintsSpec extends Specification{ MockWebServer mockWebServer diff --git a/validation/sun-nomadlab/nextflow.config b/validation/sun-nomadlab/nextflow.config index 5ff7c27..8863dd9 100644 --- a/validation/sun-nomadlab/nextflow.config +++ b/validation/sun-nomadlab/nextflow.config @@ -31,8 +31,12 @@ nomad { jobs { deleteOnCompletion = true - volumes = [ - { type "csi" name "juicefs-volume" } - ] + volumes = [ { type "csi" name "juicefs-volume" } ] + constraints: { + attr { + unique = [hostName:'nomad02'] + } + } + } }