Skip to content

Commit

Permalink
Add support for layer uri
Browse files Browse the repository at this point in the history
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
  • Loading branch information
pditommaso committed Apr 9, 2024
1 parent 73d223d commit 35ef98e
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 19 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repositories {
}

dependencies {
implementation 'io.seqera:wave-api:0.8.0'
implementation 'io.seqera:wave-api:0.9.0'
implementation 'io.seqera:wave-utils:0.12.0'
implementation 'info.picocli:picocli:4.6.1'
implementation 'com.squareup.moshi:moshi:1.15.0'
Expand Down
12 changes: 12 additions & 0 deletions app/conf/reflect-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@
"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,
Expand Down
7 changes: 5 additions & 2 deletions app/src/main/java/io/seqera/wave/cli/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
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.YamlHelper;
Expand Down Expand Up @@ -409,7 +411,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 Down Expand Up @@ -629,7 +632,7 @@ protected String dumpOutput(SubmitContainerTokenResponse resp) {
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
6 changes: 3 additions & 3 deletions app/src/main/java/io/seqera/wave/cli/json/JsonHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import io.seqera.wave.api.ContainerInspectRequest;
import io.seqera.wave.api.ContainerInspectResponse;
import io.seqera.wave.api.SubmitContainerTokenRequest;
import io.seqera.wave.api.SubmitContainerTokenResponse;
import io.seqera.wave.cli.model.ContainerInspectResponseEx;

/**
* Helper class to encode and decode JSON payloads
Expand Down Expand Up @@ -54,8 +54,8 @@ public static String toJson(ContainerInspectRequest request) {
return adapter.toJson(request);
}

public static String toJson(ContainerInspectResponse response) {
JsonAdapter<ContainerInspectResponse> adapter = moshi.adapter(ContainerInspectResponse.class);
public static String toJson(ContainerInspectResponseEx response) {
JsonAdapter<ContainerInspectResponseEx> adapter = moshi.adapter(ContainerInspectResponseEx.class);
return adapter.toJson(response);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2023, Seqera Labs
*
* 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 io.seqera.wave.cli.model;

import io.seqera.wave.api.ContainerInspectResponse;
import io.seqera.wave.core.spec.ContainerSpec;

/**
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
public class ContainerInspectResponseEx extends ContainerInspectResponse {

public ContainerInspectResponseEx(ContainerInspectResponse response) {
super(new ContainerSpecEx(response.getContainer()));
}

public ContainerInspectResponseEx(ContainerSpec spec) {
super(new ContainerSpecEx(spec));
}
}
44 changes: 44 additions & 0 deletions app/src/main/java/io/seqera/wave/cli/model/ContainerSpecEx.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2023, Seqera Labs
*
* 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 io.seqera.wave.cli.model;

import java.util.List;

import io.seqera.wave.core.spec.ContainerSpec;
import io.seqera.wave.core.spec.ObjectRef;

/**
* Wrapper for {@link ContainerSpec} that replaces
* {@link ObjectRef} with {@link LayerRef} objects
*
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
public class ContainerSpecEx extends ContainerSpec {
public ContainerSpecEx(ContainerSpec spec) {
super(spec);
// update the layers uri
if( spec.getManifest()!=null && spec.getManifest().getLayers()!=null ) {
List<ObjectRef> layers = spec.getManifest().getLayers();
for( int i=0; i<layers.size(); i++ ) {
ObjectRef it = layers.get(i);
String uri = spec.getHostName() + "/v2/" + spec.getImageName() + "/blobs/" + it.digest;
layers.set(i, new LayerRef(it, uri));
}
}
}
}
36 changes: 36 additions & 0 deletions app/src/main/java/io/seqera/wave/cli/model/LayerRef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2023, Seqera Labs
*
* 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 io.seqera.wave.cli.model;

import io.seqera.wave.core.spec.ObjectRef;

/**
* Extends a {@link ObjectRef} adding the URI attribute
*
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
public class LayerRef extends ObjectRef {

final public String uri;

public LayerRef(ObjectRef obj, String uri) {
super(obj);
this.uri = uri;
}

}
8 changes: 7 additions & 1 deletion app/src/main/java/io/seqera/wave/cli/util/YamlHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

import io.seqera.wave.api.ContainerInspectResponse;
import io.seqera.wave.api.SubmitContainerTokenResponse;
import io.seqera.wave.cli.model.ContainerInspectResponseEx;
import io.seqera.wave.cli.model.ContainerSpecEx;
import io.seqera.wave.cli.model.LayerRef;
import io.seqera.wave.core.spec.ConfigSpec;
import io.seqera.wave.core.spec.ContainerSpec;
import io.seqera.wave.core.spec.ManifestSpec;
Expand Down Expand Up @@ -51,17 +54,20 @@ public static String toYaml(SubmitContainerTokenResponse resp) {
return yaml.dump(resp);
}

public static String toYaml(ContainerInspectResponse resp) {
public static String toYaml(ContainerInspectResponseEx resp) {
final DumperOptions opts = new DumperOptions();
opts.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
opts.setAllowReadOnlyProperties(true);

final Representer representer = new Representer(opts) {
{
addClassTag(ContainerSpec.class, Tag.MAP);
addClassTag(ContainerSpecEx.class, Tag.MAP);
addClassTag(ConfigSpec.class, Tag.MAP);
addClassTag(ManifestSpec.class, Tag.MAP);
addClassTag(ContainerInspectResponse.class, Tag.MAP);
addClassTag(ContainerInspectResponseEx.class, Tag.MAP);
addClassTag(LayerRef.class, Tag.MAP);
representers.put(Instant.class, data -> representScalar(Tag.STR, data.toString()));
}
};
Expand Down
11 changes: 6 additions & 5 deletions app/src/test/groovy/io/seqera/wave/cli/AppTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ package io.seqera.wave.cli
import java.nio.file.Files
import java.time.Instant

import io.seqera.wave.api.ContainerInspectResponse
import io.seqera.wave.api.SubmitContainerTokenResponse
import io.seqera.wave.cli.exception.IllegalCliArgumentException
import io.seqera.wave.cli.model.ContainerInspectResponseEx
import io.seqera.wave.core.spec.ContainerSpec
import io.seqera.wave.util.TarUtils
import io.seqera.wave.cli.exception.IllegalCliArgumentException
import picocli.CommandLine
import spock.lang.Specification
import spock.lang.Unroll
Expand Down Expand Up @@ -103,21 +103,21 @@ class AppTest extends Specification {
def app = new App()
String[] args = ["--output", "json"]
and:
def resp = new ContainerInspectResponse( new ContainerSpec('docker.io', 'busybox', 'latest', 'sha:12345', null, null, null) )
def resp = new ContainerInspectResponseEx( new ContainerSpec('docker.io', 'https://docker.io', 'busybox', 'latest', 'sha:12345', null, null) )

when:
new CommandLine(app).parseArgs(args)
def result = app.dumpOutput(resp)
then:
result == '{"container":{"digest":"sha:12345","imageName":"busybox","reference":"latest","registry":"docker.io"}}'
result == '{"container":{"digest":"sha:12345","hostName":"https://docker.io","imageName":"busybox","reference":"latest","registry":"docker.io"}}'
}

def 'should dump inspect to yaml' () {
given:
def app = new App()
String[] args = ["--output", "yaml"]
and:
def resp = new ContainerInspectResponse( new ContainerSpec('docker.io', 'busybox', 'latest', 'sha:12345', null, null, null) )
def resp = new ContainerInspectResponseEx( new ContainerSpec('docker.io', 'https://docker.io', 'busybox', 'latest', 'sha:12345', null, null) )

when:
new CommandLine(app).parseArgs(args)
Expand All @@ -127,6 +127,7 @@ class AppTest extends Specification {
container:
config: null
digest: sha:12345
hostName: https://docker.io
imageName: busybox
manifest: null
reference: latest
Expand Down
15 changes: 13 additions & 2 deletions app/src/test/groovy/io/seqera/wave/cli/json/JsonHelperTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
package io.seqera.wave.cli.json

import io.seqera.wave.api.SubmitContainerTokenRequest
import spock.lang.Specification;

import io.seqera.wave.cli.model.ContainerInspectResponseEx
import io.seqera.wave.core.spec.ContainerSpec
import spock.lang.Specification
/**
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
Expand All @@ -43,5 +44,15 @@ class JsonHelperTest extends Specification {
result.containerImage == 'quay.io/nextflow/bash:latest'
}

def 'should convert response to json' () {
given:
def spec = new ContainerSpec('docker.io', 'https://docker.io', 'ubuntu', '22.04', 'sha:12345', null, null)
def resp = new ContainerInspectResponseEx(spec)

when:
def result = JsonHelper.toJson(resp)
then:
result == '{"container":{"digest":"sha:12345","hostName":"https://docker.io","imageName":"ubuntu","reference":"22.04","registry":"docker.io"}}'
}

}
31 changes: 26 additions & 5 deletions app/src/test/groovy/io/seqera/wave/cli/util/YamlHelperTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@

package io.seqera.wave.cli.util


import java.time.Instant

import io.seqera.wave.api.ContainerInspectResponse
import io.seqera.wave.api.SubmitContainerTokenResponse
import io.seqera.wave.cli.model.ContainerInspectResponseEx
import io.seqera.wave.core.spec.ContainerSpec
import io.seqera.wave.core.spec.ManifestSpec
import io.seqera.wave.core.spec.ObjectRef
import spock.lang.Specification
/**
*
Expand Down Expand Up @@ -58,8 +59,10 @@ class YamlHelperTest extends Specification {

def 'should convert response to yaml' () {
given:
def spec = new ContainerSpec('docker.io','ubuntu','22.04','sha:12345', null, null, null)
def resp = new ContainerInspectResponse(spec)
def layers = [ new ObjectRef('text', 'sha256:12345', 100, null), new ObjectRef('text', 'sha256:67890', 200, null) ]
def manifest = new ManifestSpec(2, 'some/media', null, layers, [one: '1', two:'2'])
def spec = new ContainerSpec('docker.io', 'https://docker.io', 'ubuntu','22.04','sha:12345', null, manifest)
def resp = new ContainerInspectResponseEx(spec)

when:
def result = YamlHelper.toYaml(resp)
Expand All @@ -68,8 +71,26 @@ class YamlHelperTest extends Specification {
container:
config: null
digest: sha:12345
hostName: https://docker.io
imageName: ubuntu
manifest: null
manifest:
annotations:
one: '1'
two: '2'
config: null
layers:
- annotations: null
digest: sha256:12345
mediaType: text
size: 100
uri: https://docker.io/v2/ubuntu/blobs/sha256:12345
- annotations: null
digest: sha256:67890
mediaType: text
size: 200
uri: https://docker.io/v2/ubuntu/blobs/sha256:67890
mediaType: some/media
schemaVersion: 2
reference: '22.04'
registry: docker.io
'''.stripIndent(true)
Expand Down

0 comments on commit 35ef98e

Please sign in to comment.