Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom labels in wave-api #18

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
25 changes: 16 additions & 9 deletions wave-api/src/main/java/io/seqera/wave/api/ContainerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
package io.seqera.wave.api;


import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;

import static io.seqera.wave.api.ObjectUtils.isEmpty;
Expand All @@ -42,6 +40,11 @@ public class ContainerConfig {

public List<ContainerLayer> layers;

/**
* Labels to be added in conda and spack build images
*/
public Map<String, String> labels;

public ContainerConfig() {
entrypoint = null;
cmd = null;
Expand All @@ -50,12 +53,13 @@ public ContainerConfig() {
layers = new ArrayList<>();
}

public ContainerConfig(List<String> entrypoint, List<String> cmd, List<String> env, String workDir, List<ContainerLayer> layers) {
public ContainerConfig(List<String> entrypoint, List<String> cmd, List<String> env, String workDir, List<ContainerLayer> layers, Map<String, String> labels) {
this.entrypoint = entrypoint;
this.cmd = cmd;
this.env = env;
this.workingDir = workDir;
this.layers = layers;
this.labels = labels;
munishchouhan marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand All @@ -72,7 +76,8 @@ public boolean empty() {
isEmpty(cmd) &&
isEmpty(env) &&
isEmpty(workingDir) &&
isEmpty(layers);
isEmpty(layers) &&
isEmpty(labels);
}

public void validate(){
Expand Down Expand Up @@ -103,20 +108,21 @@ public FusionVersion fusionVersion() {

@Override
public String toString() {
return String.format("ContainerConfig[entrypoint=%s; cmd=%s; env=%s; workingDir=%s; layers=%s]", entrypoint, cmd, env, workingDir, layers);
return String.format("ContainerConfig[entrypoint=%s; cmd=%s; env=%s; workingDir=%s; layers=%s; labels=%s]", entrypoint, cmd, env, workingDir, layers, labels);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ContainerConfig that = (ContainerConfig) o;
return Objects.equals(entrypoint, that.entrypoint) && Objects.equals(cmd, that.cmd) && Objects.equals(env, that.env) && Objects.equals(workingDir, that.workingDir) && Objects.equals(layers, that.layers);
return Objects.equals(entrypoint, that.entrypoint) && Objects.equals(cmd, that.cmd) && Objects.equals(env, that.env)
&& Objects.equals(workingDir, that.workingDir) && Objects.equals(layers, that.layers) && Objects.equals(labels, that.labels);
}

@Override
public int hashCode() {
return Objects.hash(entrypoint, cmd, env, workingDir, layers);
return Objects.hash(entrypoint, cmd, env, workingDir, layers, labels);
}

static ContainerConfig copy(ContainerConfig that) {
Expand All @@ -136,7 +142,8 @@ static public ContainerConfig copy(ContainerConfig that, boolean stripData) {
that.cmd!=null ? new ArrayList<>(that.cmd) : null,
that.env!=null ? new ArrayList<>(that.env) : null,
that.workingDir,
that.layers != null ? that.layers.stream().map(it -> ContainerLayer.copy(it,stripData)).collect(Collectors.toList()) : null
that.layers != null ? that.layers.stream().map(it -> ContainerLayer.copy(it,stripData)).collect(Collectors.toList()) : null,
that.labels != null ? that.labels.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) : null
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ class ContainerConfigTest extends Specification {
def l3 = new ContainerLayer( 'http://bar.com', 'sha256:88788', 100, 'sha256:67890' )

and:
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1])
def c2 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l2])
def c3 = new ContainerConfig(['/entry/xyz.sh'], ['/your/cmd'], ['BAR=2'], '/work/dir', [l3])
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1], [foo:'bar'])
def c2 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l2], [foo:'bar'])
def c3 = new ContainerConfig(['/entry/xyz.sh'], ['/your/cmd'], ['BAR=2'], '/work/dir', [l3], [bar:'foo'])

expect:
c1 == c2
Expand All @@ -51,50 +51,50 @@ class ContainerConfigTest extends Specification {
def c0 = new ContainerConfig()
and:
def l1 = new ContainerLayer( 'http://foo.com', 'sha256:12345', 100, 'sha256:67890' )
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1])
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1], [foo:'bar'])

expect:
c0.toString() == 'ContainerConfig[entrypoint=null; cmd=null; env=null; workingDir=null; layers=[]]'
c1.toString() == 'ContainerConfig[entrypoint=[/entry/point.sh]; cmd=[/my/cmd]; env=[FOO=1]; workingDir=/work/dir; layers=[ContainerLayer[location=http://foo.com; tarDigest=sha256:67890; gzipDigest=sha256:12345; gzipSize=100]]]'
c0.toString() == 'ContainerConfig[entrypoint=null; cmd=null; env=null; workingDir=null; layers=[]; labels=null]'
c1.toString() == 'ContainerConfig[entrypoint=[/entry/point.sh]; cmd=[/my/cmd]; env=[FOO=1]; workingDir=/work/dir; layers=[ContainerLayer[location=http://foo.com; tarDigest=sha256:67890; gzipDigest=sha256:12345; gzipSize=100]]; labels={foo=bar}]'
}

def 'should validate empty' () {
expect:
new ContainerConfig().empty()
new ContainerConfig([], null, null, null, null).empty()
new ContainerConfig(null, [], null, null, null).empty()
new ContainerConfig(null, null, [], null, null).empty()
new ContainerConfig(null, null, null, '', null).empty()
new ContainerConfig(null, null, null, null, []).empty()
new ContainerConfig([], null, null, null, null, null).empty()
new ContainerConfig(null, [], null, null, null, null).empty()
new ContainerConfig(null, null, [], null, null, null).empty()
new ContainerConfig(null, null, null, '', null, null).empty()
new ContainerConfig(null, null, null, null, [], null).empty()
munishchouhan marked this conversation as resolved.
Show resolved Hide resolved
and:
!new ContainerConfig(['x'], null, null, null, null).empty()
!new ContainerConfig(null, ['x'], null, null, null).empty()
!new ContainerConfig(null, null, ['x'], null, null).empty()
!new ContainerConfig(null, null, null, 'x', null).empty()
!new ContainerConfig(null, null, null, null, [new ContainerLayer()]).empty()
!new ContainerConfig(['x'], null, null, null, null, null).empty()
!new ContainerConfig(null, ['x'], null, null, null, null).empty()
!new ContainerConfig(null, null, ['x'], null, null, null).empty()
!new ContainerConfig(null, null, null, 'x', null, null).empty()
!new ContainerConfig(null, null, null, null, [new ContainerLayer()], [:]).empty()
munishchouhan marked this conversation as resolved.
Show resolved Hide resolved
}

def 'should validate groovy truth' () {
expect:
!new ContainerConfig()
and:
!new ContainerConfig([], null, null, null, null)
!new ContainerConfig(null, [], null, null, null)
!new ContainerConfig(null, null, [], null, null)
!new ContainerConfig(null, null, null, '', null)
!new ContainerConfig(null, null, null, null, [])
!new ContainerConfig([], null, null, null, null, null)
!new ContainerConfig(null, [], null, null, null, null)
!new ContainerConfig(null, null, [], null, null, null)
!new ContainerConfig(null, null, null, '', null, null)
!new ContainerConfig(null, null, null, null, [], [:])
and:
new ContainerConfig(['x'], null, null, null, null)
new ContainerConfig(null, ['x'], null, null, null)
new ContainerConfig(null, null, ['x'], null, null)
new ContainerConfig(null, null, null, 'x', null)
new ContainerConfig(null, null, null, null, [new ContainerLayer()])
new ContainerConfig(['x'], null, null, null, null, null)
new ContainerConfig(null, ['x'], null, null, null, null)
new ContainerConfig(null, null, ['x'], null, null, null)
new ContainerConfig(null, null, null, 'x', null, null)
new ContainerConfig(null, null, null, null, [new ContainerLayer()], [:])
}

def 'should copy objects' () {
given:
def l1 = new ContainerLayer( 'http://foo.com', 'sha256:12345', 100, 'sha256:67890' )
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1])
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1], [foo:'bar'])

expect:
null == ContainerConfig.copy(null)
Expand All @@ -107,7 +107,7 @@ class ContainerConfigTest extends Specification {
def 'should copy objects and strip data' () {
given:
def l1 = new ContainerLayer( 'data:12345678890', 'sha256:12345', 100, 'sha256:67890' )
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1])
def c1 = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1], [foo:'bar'])

expect:
c1 == ContainerConfig.copy(c1)
Expand All @@ -120,7 +120,7 @@ class ContainerConfigTest extends Specification {
def 'should find fusion version' () {
given:
def l1 = new ContainerLayer( 'https://fusionfs.seqera.io/releases/v2.1.3-amd64.json' )
def config = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1])
def config = new ContainerConfig(['/entry/point.sh'], ['/my/cmd'], ['FOO=1'], '/work/dir', [l1], [foo:'bar'])

expect:
config.fusionVersion() == new FusionVersion('2.1.3', 'amd64')
Expand Down