Skip to content

Commit

Permalink
Use container-alpha1v2 endpoint (#62)
Browse files Browse the repository at this point in the history

Signed-off-by: Paolo Di Tommaso <[email protected]>
Signed-off-by: munishchouhan <[email protected]>
Co-authored-by: munishchouhan <[email protected]>
  • Loading branch information
pditommaso and munishchouhan authored Apr 11, 2024
1 parent 9decb2a commit a923aac
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 411 deletions.
5 changes: 2 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ repositories {
}

dependencies {
implementation 'io.seqera:wave-api:0.7.1'
implementation 'io.seqera:wave-utils:0.9.0'
implementation 'io.seqera:wave-api:0.9.1'
implementation 'io.seqera:wave-utils:0.12.0'
implementation 'info.picocli:picocli:4.6.1'
implementation 'com.squareup.moshi:moshi:1.15.0'
implementation 'com.squareup.moshi:moshi-adapters:1.14.0'
Expand All @@ -38,7 +38,6 @@ dependencies {
testImplementation ("org.objenesis:objenesis:3.2")
testImplementation ("org.spockframework:spock-core:2.3-groovy-3.0") { exclude group: 'org.codehaus.groovy'; exclude group: 'net.bytebuddy' }
testImplementation ('org.spockframework:spock-junit4:2.3-groovy-3.0') { exclude group: 'org.codehaus.groovy'; exclude group: 'net.bytebuddy' }
testImplementation 'com.github.tomakehurst:wiremock:2.27.2'
}

test {
Expand Down
49 changes: 48 additions & 1 deletion app/conf/reflect-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.api.BuildStatusResponse",
"allDeclaredFields":true,
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.api.BuildStatusResponse$Status",
"fields":[{"name":"COMPLETED"}, {"name":"PENDING"}]
},
{
"name":"io.seqera.wave.api.ContainerConfig",
"allDeclaredFields":true,
Expand Down Expand Up @@ -175,6 +185,15 @@
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.api.PackagesSpec",
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.api.PackagesSpec$Type",
"fields":[{"name":"CONDA"}, {"name":"SPACK"}]
},
{
"name":"io.seqera.wave.api.ServiceInfo",
"allDeclaredFields":true,
Expand All @@ -196,6 +215,12 @@
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.api.SubmitContainerTokenResponseBeanInfo"
},
{
"name":"io.seqera.wave.api.SubmitContainerTokenResponseCustomizer"
},
{
"name":"io.seqera.wave.cli.App",
"allDeclaredFields":true,
Expand All @@ -208,18 +233,40 @@
{
"name":"io.seqera.wave.cli.json.DateTimeAdapter",
"queryAllDeclaredMethods":true,
"methods":[{"name":"deserializeInstant","parameterTypes":["java.lang.String"] }, {"name":"serializeInstant","parameterTypes":["java.time.Instant"] }]
"methods":[{"name":"deserializeDuration","parameterTypes":["java.lang.String"] }, {"name":"deserializeInstant","parameterTypes":["java.lang.String"] }, {"name":"serializeInstant","parameterTypes":["java.time.Instant"] }]
},
{
"name":"io.seqera.wave.cli.json.PathAdapter",
"queryAllDeclaredMethods":true
},
{
"name":"io.seqera.wave.cli.model.ContainerInspectResponseEx",
"allDeclaredFields":true
},
{
"name":"io.seqera.wave.cli.model.ContainerSpecEx",
"allDeclaredFields":true
},
{
"name":"io.seqera.wave.cli.model.LayerRef",
"allDeclaredFields":true
},
{
"name":"io.seqera.wave.cli.util.CliVersionProvider",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.config.CondaOpts",
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.config.SpackOpts",
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"io.seqera.wave.core.spec.ConfigSpec",
"allDeclaredFields":true,
Expand Down
146 changes: 56 additions & 90 deletions app/src/main/java/io/seqera/wave/cli/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import ch.qos.logback.classic.Level;
Expand All @@ -44,15 +44,19 @@
import io.seqera.wave.api.ContainerInspectRequest;
import io.seqera.wave.api.ContainerInspectResponse;
import io.seqera.wave.api.ContainerLayer;
import io.seqera.wave.api.PackagesSpec;
import io.seqera.wave.api.ServiceInfo;
import io.seqera.wave.api.SubmitContainerTokenRequest;
import io.seqera.wave.api.SubmitContainerTokenResponse;
import io.seqera.wave.cli.exception.BadClientResponseException;
import io.seqera.wave.cli.exception.ClientConnectionException;
import io.seqera.wave.cli.exception.IllegalCliArgumentException;
import io.seqera.wave.cli.json.JsonHelper;
import io.seqera.wave.cli.model.ContainerInspectResponseEx;
import io.seqera.wave.cli.model.ContainerSpecEx;
import io.seqera.wave.cli.util.BuildInfo;
import io.seqera.wave.cli.util.CliVersionProvider;
import io.seqera.wave.cli.util.DurationConverter;
import io.seqera.wave.cli.util.YamlHelper;
import io.seqera.wave.config.CondaOpts;
import io.seqera.wave.config.SpackOpts;
Expand All @@ -62,16 +66,6 @@
import picocli.CommandLine;
import static io.seqera.wave.cli.util.Checkers.isEmpty;
import static io.seqera.wave.cli.util.Checkers.isEnvVar;
import static io.seqera.wave.util.DockerHelper.addPackagesToSpackFile;
import static io.seqera.wave.util.DockerHelper.condaFileFromPackages;
import static io.seqera.wave.util.DockerHelper.condaFileFromPath;
import static io.seqera.wave.util.DockerHelper.condaFileToDockerFile;
import static io.seqera.wave.util.DockerHelper.condaFileToSingularityFile;
import static io.seqera.wave.util.DockerHelper.condaPackagesToDockerFile;
import static io.seqera.wave.util.DockerHelper.condaPackagesToSingularityFile;
import static io.seqera.wave.util.DockerHelper.spackFileToDockerFile;
import static io.seqera.wave.util.DockerHelper.spackFileToSingularityFile;
import static io.seqera.wave.util.DockerHelper.spackPackagesToSpackFile;
import static picocli.CommandLine.Command;
import static picocli.CommandLine.Option;

Expand Down Expand Up @@ -124,8 +118,8 @@ public class App implements Runnable {
@Option(names = {"--platform"}, paramLabel = "''", description = "Platform to be used for the container build. One of: linux/amd64, linux/arm64.")
private String platform;

@Option(names = {"--await"}, paramLabel = "false", description = "Await the container build to be available.")
private boolean await;
@Option(names = {"--await"}, paramLabel = "false", arity = "0..1", description = "Await the container build to be available. you can provide a timeout like --await 10m or 2s, by default its 15 minutes.")
private Duration await;

@Option(names = {"--context"}, paramLabel = "''", description = "Directory path where the build context is stored e.g. /some/context/path.")
private String contextDir;
Expand Down Expand Up @@ -205,6 +199,9 @@ public static void main(String[] args) {
final App app = new App();
final CommandLine cli = new CommandLine(app);

//register duration converter
cli.registerConverter(Duration.class, new DurationConverter());

// add examples in help
cli
.getCommandSpec()
Expand Down Expand Up @@ -376,7 +373,7 @@ protected void validateArgs() {
throw new IllegalCliArgumentException("Context path is not a directory - offending value: " + contextDir);
}

if( dryRun && await)
if( dryRun && await != null )
throw new IllegalCliArgumentException("Options --dry-run and --await conflicts each other");

if( !isEmpty(platform) && !VALID_PLATFORMS.contains(platform) )
Expand All @@ -392,8 +389,7 @@ protected SubmitContainerTokenRequest createRequest() {
return new SubmitContainerTokenRequest()
.withContainerImage(image)
.withContainerFile(containerFileBase64())
.withCondaFile(condaFileBase64())
.withSpackFile(spackFileBase64())
.withPackages(packagesSpec())
.withContainerPlatform(platform)
.withTimestamp(OffsetDateTime.now())
.withBuildRepository(buildRepository)
Expand All @@ -420,7 +416,8 @@ public void inspect() {
;

final ContainerInspectResponse resp = client.inspect(req);
System.out.println(dumpOutput(resp));
final ContainerSpecEx spec = new ContainerSpecEx(resp.getContainer());
System.out.println(dumpOutput(new ContainerInspectResponseEx(spec)));
}

@Override
Expand All @@ -437,8 +434,8 @@ public void run() {
// submit it
SubmitContainerTokenResponse resp = client.submit(request);
// await build to be completed
if( await )
client.awaitImage(resp.targetImage);
if( await != null && resp.buildId!=null && !resp.cached )
client.awaitCompletion(resp.buildId, await);
// print the wave container name
System.out.println(dumpOutput(resp));
}
Expand Down Expand Up @@ -576,69 +573,55 @@ private ContainerInspectRequest inspectRequest(String image) {
private CondaOpts condaOpts() {
return new CondaOpts()
.withMambaImage(condaBaseImage)
.withCommands(condaRunCommands);
.withCommands(condaRunCommands)
;
}

protected String containerFileBase64() {
if( !isEmpty(containerFile) ) {
return encodePathBase64(containerFile);
}

if (!isEmpty(condaFile) || !isEmpty(condaPackages)) {
String result;
final String lock = condaLock();
if (!isEmpty(lock)) {
result = singularity
? condaPackagesToSingularityFile(lock, condaChannels(), condaOpts())
: condaPackagesToDockerFile(lock, condaChannels(), condaOpts());
} else {
result = singularity
? condaFileToSingularityFile(condaOpts())
: condaFileToDockerFile(condaOpts());
}
return encodeStringBase64(result);
}

if( !isEmpty(spackFile) || spackPackages!=null ) {
final SpackOpts opts = new SpackOpts() .withCommands(spackRunCommands);
final String result = singularity
? spackFileToSingularityFile(opts)
: spackFileToDockerFile(opts);
return encodeStringBase64(result);
}
private SpackOpts spackOpts() {
return new SpackOpts()
.withCommands(spackRunCommands);
}

return null;
protected String containerFileBase64() {
return !isEmpty(containerFile)
? encodePathBase64(containerFile)
: null;
}

protected String condaFileBase64() {
if (!isEmpty(condaFile)) {
// parse the attribute as a conda file path *and* append the base packages if any
// note 'channel' is null, because they are expected to be provided in the conda file
final Path path = condaFileFromPath(condaFile, null);
return path != null ? encodePathBase64(path.toString()) : null;
protected PackagesSpec packagesSpec() {
if( !isEmpty(condaFile) ) {
return new PackagesSpec()
.withType(PackagesSpec.Type.CONDA)
.withCondaOpts(condaOpts())
.withEnvironment(encodePathBase64(condaFile))
.withChannels(condaChannels())
;
}
else if (!isEmpty(condaPackages) && isEmpty(condaLock())) {
// create a minimal conda file with package spec from user input
final String packages = condaPackages.stream().collect(Collectors.joining(" "));
final Path path = condaFileFromPackages(packages, condaChannels());
return path != null ? encodePathBase64(path.toString()) : null;

if( !isEmpty(condaPackages) ) {
return new PackagesSpec()
.withType(PackagesSpec.Type.CONDA)
.withCondaOpts(condaOpts())
.withEntries(condaPackages)
.withChannels(condaChannels())
;
}
else
return null;
}

protected String spackFileBase64() {
if( !isEmpty(spackFile) ) {
// parse the attribute as a spack file path *and* append the base packages if any
return encodePathBase64(addPackagesToSpackFile(spackFile, new SpackOpts()).toString());
return new PackagesSpec()
.withType(PackagesSpec.Type.SPACK)
.withSpackOpts(spackOpts())
.withEnvironment(encodePathBase64(spackFile));
}
else if( spackPackages!=null && spackPackages.size()>0 ) {
// create a minimal spack file with package spec from user input
final String packages = spackPackages.stream().collect(Collectors.joining(" "));
return encodePathBase64(spackPackagesToSpackFile(packages, new SpackOpts()).toString());

if( !isEmpty(spackPackages) ) {
return new PackagesSpec()
.withType(PackagesSpec.Type.SPACK)
.withSpackOpts(spackOpts())
.withEntries(spackPackages);
}
else
return null;

return null;
}

protected String dumpOutput(SubmitContainerTokenResponse resp) {
Expand All @@ -651,12 +634,10 @@ protected String dumpOutput(SubmitContainerTokenResponse resp) {
if( outputFormat!=null )
throw new IllegalArgumentException("Unexpected output format: "+outputFormat);

return freeze
? resp.containerImage
: resp.targetImage;
return resp.targetImage;
}

protected String dumpOutput(ContainerInspectResponse resp) {
protected String dumpOutput(ContainerInspectResponseEx resp) {
if( "json".equals(outputFormat) || outputFormat==null ) {
return JsonHelper.toJson(resp);
}
Expand Down Expand Up @@ -696,21 +677,6 @@ protected List<String> condaChannels() {
.collect(Collectors.toList());
}

protected String condaLock() {
if( isEmpty(condaPackages) )
return null;
Optional<String> result = condaPackages
.stream()
.filter(it->it.startsWith("http://") || it.startsWith("https://"))
.findFirst();
if( !result.isPresent() )
return null;
if( condaPackages.size()!=1 ) {
throw new IllegalCliArgumentException("No more than one Conda lock remote file can be specified at the same time");
}
return result.get();
}

void printInfo() {
System.out.println(String.format("Client:"));
System.out.println(String.format(" Version : %s", BuildInfo.getVersion()));
Expand Down
Loading

0 comments on commit a923aac

Please sign in to comment.