Browse Source

Merge branch '3.2.x' into 3.3.x

Closes gh-43069
pull/43333/head
Andy Wilkinson 1 year ago
parent
commit
81872afd53
  1. 28
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java
  2. 47
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/LoadImageUpdateEvent.java
  3. 10
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java
  4. 12
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/LoadImageUpdateEventTests.java
  5. 1
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/load-error.json

28
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java

@ -233,7 +233,7 @@ public class DockerApi { @@ -233,7 +233,7 @@ public class DockerApi {
Assert.notNull(archive, "Archive must not be null");
Assert.notNull(listener, "Listener must not be null");
URI loadUri = buildUrl("/images/load");
StreamCaptureUpdateListener streamListener = new StreamCaptureUpdateListener();
LoadImageUpdateListener streamListener = new LoadImageUpdateListener(archive);
listener.onStart();
try {
try (Response response = http().post(loadUri, "application/x-tar", archive::writeTo)) {
@ -242,9 +242,7 @@ public class DockerApi { @@ -242,9 +242,7 @@ public class DockerApi {
listener.onUpdate(event);
});
}
Assert.state(StringUtils.hasText(streamListener.getCapturedStream()),
"Invalid response received when loading image "
+ ((archive.getTag() != null) ? "\"" + archive.getTag() + "\"" : ""));
streamListener.assertValidResponseReceived();
}
finally {
listener.onFinish();
@ -482,19 +480,33 @@ public class DockerApi { @@ -482,19 +480,33 @@ public class DockerApi {
}
/**
* {@link UpdateListener} used to ensure an image load response stream.
* {@link UpdateListener} for an image load response stream.
*/
private static final class StreamCaptureUpdateListener implements UpdateListener<LoadImageUpdateEvent> {
private static final class LoadImageUpdateListener implements UpdateListener<LoadImageUpdateEvent> {
private final ImageArchive archive;
private String stream;
private LoadImageUpdateListener(ImageArchive archive) {
this.archive = archive;
}
@Override
public void onUpdate(LoadImageUpdateEvent event) {
Assert.state(event.getErrorDetail() == null,
() -> "Error response received when loading image" + image() + ": " + event.getErrorDetail());
this.stream = event.getStream();
}
String getCapturedStream() {
return this.stream;
private String image() {
ImageReference tag = this.archive.getTag();
return (tag != null) ? " \"" + tag + "\"" : "";
}
private void assertValidResponseReceived() {
Assert.state(StringUtils.hasText(this.stream),
() -> "Invalid response received when loading image" + image());
}
}

47
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/LoadImageUpdateEvent.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.boot.buildpack.platform.docker;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A {@link ProgressUpdateEvent} fired as an image is loaded.
@ -28,10 +29,14 @@ public class LoadImageUpdateEvent extends ProgressUpdateEvent { @@ -28,10 +29,14 @@ public class LoadImageUpdateEvent extends ProgressUpdateEvent {
private final String stream;
private final ErrorDetail errorDetail;
@JsonCreator
public LoadImageUpdateEvent(String stream, String status, ProgressDetail progressDetail, String progress) {
public LoadImageUpdateEvent(String stream, String status, ProgressDetail progressDetail, String progress,
ErrorDetail errorDetail) {
super(status, progressDetail, progress);
this.stream = stream;
this.errorDetail = errorDetail;
}
/**
@ -42,4 +47,42 @@ public class LoadImageUpdateEvent extends ProgressUpdateEvent { @@ -42,4 +47,42 @@ public class LoadImageUpdateEvent extends ProgressUpdateEvent {
return this.stream;
}
/**
* Return the error detail or {@code null} if no error occurred.
* @return the error detail, if any
* @since 3.2.12
*/
public ErrorDetail getErrorDetail() {
return this.errorDetail;
}
/**
* Details of an error embedded in a response stream.
*
* @since 3.2.12
*/
public static class ErrorDetail {
private final String message;
@JsonCreator
public ErrorDetail(@JsonProperty("message") String message) {
this.message = message;
}
/**
* Returns the message field from the error detail.
* @return the message
*/
public String getMessage() {
return this.message;
}
@Override
public String toString() {
return this.message;
}
}
}

10
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java

@ -252,6 +252,16 @@ class DockerApiTests { @@ -252,6 +252,16 @@ class DockerApiTests {
.withMessageContaining("Invalid response received");
}
@Test // gh-31243
void loadWithErrorResponseThrowsException() throws Exception {
Image image = Image.of(getClass().getResourceAsStream("type/image.json"));
ImageArchive archive = ImageArchive.from(image);
URI loadUri = new URI(IMAGES_URL + "/load");
given(http().post(eq(loadUri), eq("application/x-tar"), any())).willReturn(responseOf("load-error.json"));
assertThatIllegalStateException().isThrownBy(() -> this.api.load(archive, this.loadListener))
.withMessageContaining("Error response received");
}
@Test
void loadLoadsImage() throws Exception {
Image image = Image.of(getClass().getResourceAsStream("type/image.json"));

12
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/LoadImageUpdateEventTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.springframework.boot.buildpack.platform.docker; @@ -18,6 +18,7 @@ package org.springframework.boot.buildpack.platform.docker;
import org.junit.jupiter.api.Test;
import org.springframework.boot.buildpack.platform.docker.LoadImageUpdateEvent.ErrorDetail;
import org.springframework.boot.buildpack.platform.docker.ProgressUpdateEvent.ProgressDetail;
import static org.assertj.core.api.Assertions.assertThat;
@ -36,9 +37,16 @@ class LoadImageUpdateEventTests extends ProgressUpdateEventTests<LoadImageUpdate @@ -36,9 +37,16 @@ class LoadImageUpdateEventTests extends ProgressUpdateEventTests<LoadImageUpdate
assertThat(event.getStream()).isEqualTo("stream");
}
@Test
void getErrorDetailReturnsErrorDetail() {
LoadImageUpdateEvent event = createEvent();
assertThat(event.getErrorDetail()).extracting(ErrorDetail::getMessage).isEqualTo("max depth exceeded");
}
@Override
protected LoadImageUpdateEvent createEvent(String status, ProgressDetail progressDetail, String progress) {
return new LoadImageUpdateEvent("stream", status, progressDetail, progress);
return new LoadImageUpdateEvent("stream", status, progressDetail, progress,
new ErrorDetail("max depth exceeded"));
}
}

1
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/load-error.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
{"errorDetail":{"message":"max depth exceeded"}}
Loading…
Cancel
Save