Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.gesellix.docker.remote.api.client

import de.gesellix.docker.remote.api.BuildInfo
import de.gesellix.docker.remote.api.ImageID

fun List<BuildInfo>.getImageId(): ImageID? {
val reversedInfos = this.reversed()
val firstAux = reversedInfos.stream()
.filter { (_, _, _, _, _, _, _, aux): BuildInfo -> aux != null }
.findFirst()
if (firstAux.isPresent) {
return firstAux.get().aux
} else {
val idFromStream = reversedInfos.stream()
.filter { (_, stream): BuildInfo -> stream?.contains("Successfully built ")!! }
.findFirst()
return if (idFromStream.isPresent) {
ImageID(idFromStream.get().stream!!.removePrefix("Successfully built ").replaceAfter('\n', "").trim())
} else {
val tagFromStream = reversedInfos.stream()
.filter { (_, stream): BuildInfo -> stream?.contains("Successfully tagged ")!! }
.findFirst()
tagFromStream.map { (_, stream): BuildInfo ->
ImageID(stream!!.removePrefix("Successfully tagged ").replaceAfter('\n', "").trim())
}
.orElse(null)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,8 @@ class ContainerApi(dockerClientConfig: DockerClientConfig = defaultClientConfig,
path = "/containers/{id}/changes".replace("{" + "id" + "}", id),
query = localVariableQuery,
headers = localVariableHeaders,
body = localVariableBody
body = localVariableBody,
elementType = ContainerChangeResponseItem::class.java
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.gesellix.docker.remote.api.client

import de.gesellix.docker.remote.api.CreateImageInfo

fun List<CreateImageInfo>.getImageId(): String? {
val reversedInfos = this.reversed()
val firstStatus = reversedInfos.stream()
.filter { (_, _, status, _, _): CreateImageInfo -> status != null }
.findFirst()
if (firstStatus.isPresent) {
return firstStatus.get().status
} else {
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import de.gesellix.docker.remote.api.core.RequestConfig
import de.gesellix.docker.remote.api.core.ResponseType
import de.gesellix.docker.remote.api.core.ServerError
import de.gesellix.docker.remote.api.core.ServerException
import de.gesellix.docker.remote.api.core.StreamCallback
import de.gesellix.docker.remote.api.core.Success
import de.gesellix.docker.remote.api.core.SuccessStream
import kotlinx.coroutines.cancel
Expand Down Expand Up @@ -234,28 +235,37 @@ class ExecApi(dockerClientConfig: DockerClientConfig = defaultClientConfig, prox
* @throws ServerException If the API returns a server error response
*/
@Throws(UnsupportedOperationException::class, ClientException::class, ServerException::class)
fun execStart(id: String, execStartConfig: ExecStartConfig?) {
@JvmOverloads
fun execStart(
id: String, execStartConfig: ExecStartConfig?,
callback: StreamCallback<Frame?>? = null, timeoutMillis: Long? = null /*= 24.hours.toLongMilliseconds()*/
) {
val localVariableConfig = execStartRequestConfig(id = id, execStartConfig = execStartConfig)

// TODO do we need to inspect the exec, because it might have been created with tty==false?
// val expectMultiplexedResponse = !(execInspect(id).processConfig?.tty ?: false)
val expectMultiplexedResponse = !(execStartConfig?.tty ?: false)
val expectMultiplexedResponse: Boolean = if (execStartConfig?.tty != null) {
!(execStartConfig.tty ?: false)
} else {
!(execInspect(id).processConfig?.tty ?: false)
}
val localVarResponse = requestFrames(
localVariableConfig, expectMultiplexedResponse
)

// TODO the caller of #execStart() should decide about timeout and callback
val timeout = Duration.of(1, ChronoUnit.HOURS)
val callback = LoggingCallback<Frame>()
val timeout = if (timeoutMillis == null) {
Duration.of(10, ChronoUnit.MINUTES)
} else {
Duration.of(timeoutMillis, ChronoUnit.MILLIS)
}
val actualCallback = callback ?: LoggingCallback<Frame?>()

when (localVarResponse.responseType) {
ResponseType.Success -> {
runBlocking {
launch {
withTimeoutOrNull(timeout.toMillis()) {
callback.onStarting(this@launch::cancel)
((localVarResponse as SuccessStream<*>).data as Flow<Frame>).collect { callback.onNext(it) }
callback.onFinished()
actualCallback.onStarting(this@launch::cancel)
((localVarResponse as SuccessStream<*>).data as Flow<Frame>).collect { actualCallback.onNext(it) }
actualCallback.onFinished()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import de.gesellix.docker.remote.api.HistoryResponseItem
import de.gesellix.docker.remote.api.IdResponse
import de.gesellix.docker.remote.api.Image
import de.gesellix.docker.remote.api.ImageDeleteResponseItem
import de.gesellix.docker.remote.api.ImageID
import de.gesellix.docker.remote.api.ImagePruneResponse
import de.gesellix.docker.remote.api.ImageSearchResponseItem
import de.gesellix.docker.remote.api.ImageSummary
Expand Down Expand Up @@ -270,31 +269,6 @@ class ImageApi(dockerClientConfig: DockerClientConfig = defaultClientConfig, pro
}
}

fun getImageId(buildInfos: List<BuildInfo>): ImageID? {
val reversedInfos = buildInfos.reversed()
val firstAux = reversedInfos.stream()
.filter { (_, _, _, _, _, _, _, aux): BuildInfo -> aux != null }
.findFirst()
if (firstAux.isPresent) {
return firstAux.get().aux
} else {
val idFromStream = reversedInfos.stream()
.filter { (_, stream): BuildInfo -> stream?.contains("Successfully built ")!! }
.findFirst()
return if (idFromStream.isPresent) {
ImageID(idFromStream.get().stream!!.removePrefix("Successfully built ").replaceAfter('\n', "").trim())
} else {
val tagFromStream = reversedInfos.stream()
.filter { (_, stream): BuildInfo -> stream?.contains("Successfully tagged ")!! }
.findFirst()
tagFromStream.map { (_, stream): BuildInfo ->
ImageID(stream!!.removePrefix("Successfully tagged ").replaceAfter('\n', "").trim())
}
.orElse(null)
}
}
}

/**
* To obtain the request config of the operation imageBuild
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package de.gesellix.docker.remote.api.client;

import de.gesellix.docker.engine.DockerClientConfig;
import de.gesellix.docker.remote.api.BuildInfo;
import de.gesellix.docker.remote.api.ImageID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

class ImageApiTest {

private ImageApi imageApi;

@BeforeEach
public void setup() {
imageApi = new ImageApi(new DockerClientConfig());
}
class BuildInfoExtensionsTest {

@Test
public void getImageIdFromAux() {
Expand All @@ -28,7 +19,7 @@ public void getImageIdFromAux() {
infos.add(new BuildInfo(null, "Successfully built f9d5f290d048\nfoo bar", null, null, null, null, null, null));
infos.add(new BuildInfo(null, "Successfully tagged image:tag\nbar baz", null, null, null, null, null, null));

ImageID imageId = imageApi.getImageId(infos);
ImageID imageId = BuildInfoExtensionsKt.getImageId(infos);

assertEquals("sha256:expected-id", imageId.getID());
}
Expand All @@ -40,7 +31,7 @@ public void getImageIdFromStreamWithBuildMessage() {
infos.add(new BuildInfo(null, "Successfully built f9d5f290d048\nfoo bar", null, null, null, null, null, null));
infos.add(new BuildInfo(null, "Successfully tagged image:tag\nbar baz", null, null, null, null, null, null));

ImageID imageId = imageApi.getImageId(infos);
ImageID imageId = BuildInfoExtensionsKt.getImageId(infos);

assertEquals("f9d5f290d048", imageId.getID());
}
Expand All @@ -50,7 +41,7 @@ public void getImageIdFromStreamWithTagMessage() {
List<BuildInfo> infos = new ArrayList<>();
infos.add(new BuildInfo(null, "Successfully tagged image:tag\nbar baz", null, null, null, null, null, null));

ImageID imageId = imageApi.getImageId(infos);
ImageID imageId = BuildInfoExtensionsKt.getImageId(infos);

assertEquals("image:tag", imageId.getID());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public void run() {
}

@Test
public void containerLogsWithTty() {
public void containerLogsWithTty() throws InterruptedException {
imageApi.imageCreate(testImage.getImageName(), null, null, testImage.getImageTag(), null, null, null, null, null);

ContainerCreateRequest containerCreateRequest = new ContainerCreateRequest(
Expand All @@ -342,8 +342,9 @@ public void containerLogsWithTty() {
);
containerApi.containerCreate(containerCreateRequest, "container-logs-with-tty-test");
containerApi.containerStart("container-logs-with-tty-test", null);
Thread.sleep(500);

Duration timeout = Duration.of(5, SECONDS);
Duration timeout = Duration.of(10, SECONDS);
LogFrameStreamCallback callback = new LogFrameStreamCallback();

new Thread(() -> containerApi.containerLogs(
Expand All @@ -366,7 +367,9 @@ public void run() {
catch (InterruptedException e) {
e.printStackTrace();
}
assertSame(callback.frames.stream().findAny().get().getStreamType(), Frame.StreamType.RAW);
Optional<Frame> anyFrame = callback.frames.stream().findAny();
assertTrue(anyFrame.isPresent());
assertSame(anyFrame.get().getStreamType(), Frame.StreamType.RAW);

removeContainer(engineApiClient, "container-logs-with-tty-test");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.gesellix.docker.remote.api.client;

import de.gesellix.docker.remote.api.CreateImageInfo;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

class CreateImageInfoExtensionsTest {

@Test
public void getImageIdFromStatus() {
List<CreateImageInfo> infos = new ArrayList<>();
infos.add(new CreateImageInfo("os-linux", null, "Pulling from gesellix/echo-server", null, null));
infos.add(new CreateImageInfo(null, null, "Digest: sha256:04c0275878dc243b2f92193467cb33cdb9ee2262be64b627ed476de73e399244", null, null));
infos.add(new CreateImageInfo(null, null, "Status: Image is up to date for gesellix/echo-server:os-linux", null, null));
infos.add(new CreateImageInfo(null, null, "sha256:87f5e747ad067f91a7c4adf154deea20cebc3a749be5c2864a0c65cf70ddd8c4", null, null));

String imageId = CreateImageInfoExtensionsKt.getImageId(infos);

assertEquals("sha256:87f5e747ad067f91a7c4adf154deea20cebc3a749be5c2864a0c65cf70ddd8c4", imageId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public void onFinished() {
log.error("Wait interrupted", e);
}

ImageID imageId = imageApi.getImageId(infos);
ImageID imageId = BuildInfoExtensionsKt.getImageId(infos);
assertNotNull(imageId);
assertNotNull(imageId.getID());
assertTrue(imageId.getID().matches(".+"));
Expand Down