mirror of https://github.com/dapr/java-sdk.git
Adding Dapr Container default wait strategy based on healthz/outbound (#1105)
* Adding Dapr Container default wait strategy based on healthz/outbound Signed-off-by: Artur Ciocanu <ciocanu@adobe.com> * Ensure Testcontainers Dapr uses the alpha version Signed-off-by: Artur Ciocanu <ciocanu@adobe.com> --------- Signed-off-by: Artur Ciocanu <ciocanu@adobe.com> Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
This commit is contained in:
parent
b808c92320
commit
a6923ed75c
|
@ -25,6 +25,8 @@
|
|||
<springboot.version>3.3.1</springboot.version>
|
||||
<logback-classic.version>1.4.12</logback-classic.version>
|
||||
<wiremock.version>3.9.1</wiremock.version>
|
||||
<testcontainers-dapr.version>${dapr.sdk.alpha.version}</testcontainers-dapr.version>
|
||||
<testcontainers-test.version>1.20.0</testcontainers-test.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -214,6 +216,17 @@
|
|||
<version>4.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>testcontainers-dapr</artifactId>
|
||||
<version>${testcontainers-dapr.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${testcontainers-test.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -13,7 +13,7 @@ limitations under the License.
|
|||
|
||||
package io.dapr.it.testcontainers;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
|
||||
import io.dapr.client.DaprClient;
|
||||
import io.dapr.client.DaprClientBuilder;
|
||||
import io.dapr.client.domain.Metadata;
|
||||
|
@ -23,10 +23,10 @@ import io.dapr.testcontainers.DaprContainer;
|
|||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.testcontainers.Testcontainers;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
@ -43,11 +43,12 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
|
|||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@Testcontainers
|
||||
@WireMockTest(httpPort = 8081)
|
||||
public class DaprContainerTest {
|
||||
|
||||
// Time-to-live for messages published.
|
||||
|
@ -57,10 +58,7 @@ public class DaprContainerTest {
|
|||
private static final String PUBSUB_NAME = "pubsub";
|
||||
private static final String PUBSUB_TOPIC_NAME = "topic";
|
||||
|
||||
@ClassRule
|
||||
public static WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8081));
|
||||
|
||||
@ClassRule
|
||||
@Container
|
||||
public static DaprContainer daprContainer = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
|
@ -69,16 +67,15 @@ public class DaprContainerTest {
|
|||
/**
|
||||
* Sets the Dapr properties for the test.
|
||||
*/
|
||||
@BeforeClass
|
||||
@BeforeAll
|
||||
public static void setDaprProperties() {
|
||||
configStub();
|
||||
Testcontainers.exposeHostPorts(8081);
|
||||
org.testcontainers.Testcontainers.exposeHostPorts(8081);
|
||||
System.setProperty("dapr.grpc.port", Integer.toString(daprContainer.getGrpcPort()));
|
||||
System.setProperty("dapr.http.port", Integer.toString(daprContainer.getHttpPort()));
|
||||
}
|
||||
|
||||
private static void configStub() {
|
||||
|
||||
stubFor(any(urlMatching("/dapr/subscribe"))
|
||||
.willReturn(aResponse().withBody("[]").withStatus(200)));
|
||||
|
||||
|
@ -98,19 +95,20 @@ public class DaprContainerTest {
|
|||
@Test
|
||||
public void testDaprContainerDefaults() {
|
||||
assertEquals(
|
||||
"The pubsub and kvstore component should be configured by default",
|
||||
2,
|
||||
daprContainer.getComponents().size());
|
||||
daprContainer.getComponents().size(),
|
||||
"The pubsub and kvstore component should be configured by default"
|
||||
);
|
||||
assertEquals(
|
||||
"A subscription should be configured by default if none is provided",
|
||||
1,
|
||||
daprContainer.getSubscriptions().size());
|
||||
daprContainer.getSubscriptions().size(),
|
||||
"A subscription should be configured by default if none is provided");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateStore() throws Exception {
|
||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||
client.waitForSidecar(5000).block();
|
||||
client.waitForSidecar(1000).block();
|
||||
|
||||
String value = "value";
|
||||
// Save state
|
||||
|
@ -127,7 +125,7 @@ public class DaprContainerTest {
|
|||
public void testPlacement() throws Exception {
|
||||
// Here we are just waiting for Dapr to be ready
|
||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||
client.waitForSidecar(5000).block();
|
||||
client.waitForSidecar(1000).block();
|
||||
}
|
||||
|
||||
OkHttpClient client = new OkHttpClient.Builder().build();
|
||||
|
@ -143,13 +141,12 @@ public class DaprContainerTest {
|
|||
throw new IOException("Unexpected response: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPubSub() throws Exception {
|
||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||
client.waitForSidecar(5000).block();
|
||||
client.waitForSidecar(1000).block();
|
||||
|
||||
String message = "message content";
|
||||
Map<String, String> metadata = singletonMap(Metadata.TTL_IN_SECONDS, MESSAGE_TTL_IN_SECONDS);
|
||||
|
|
|
@ -11,19 +11,23 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package io.dapr.testcontainers;
|
||||
package io.dapr.it.testcontainers;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import io.dapr.testcontainers.DaprPlacementContainer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@Testcontainers
|
||||
public class DaprPlacementContainerTest {
|
||||
|
||||
@ClassRule
|
||||
public static DaprPlacementContainer placement = new DaprPlacementContainer("daprio/placement");
|
||||
@Container
|
||||
private static final DaprPlacementContainer PLACEMENT_CONTAINER = new DaprPlacementContainer("daprio/placement");
|
||||
|
||||
@Test
|
||||
public void testDaprPlacementContainerDefaults() {
|
||||
Assert.assertEquals("The default port is set", 50005, placement.getPort());
|
||||
assertEquals(50005, PLACEMENT_CONTAINER.getPort(), "The default port is set");
|
||||
}
|
||||
}
|
|
@ -15,6 +15,11 @@
|
|||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
|
|
|
@ -15,6 +15,8 @@ package io.dapr.testcontainers;
|
|||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.Network;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.containers.wait.strategy.WaitStrategy;
|
||||
import org.testcontainers.images.builder.Transferable;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
|
@ -38,6 +40,10 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
|
||||
private static final int DAPRD_DEFAULT_HTTP_PORT = 3500;
|
||||
private static final int DAPRD_DEFAULT_GRPC_PORT = 50001;
|
||||
private static final WaitStrategy WAIT_STRATEGY = Wait.forHttp("/v1.0/healthz/outbound")
|
||||
.forPort(DAPRD_DEFAULT_HTTP_PORT)
|
||||
.forStatusCodeMatching(statusCode -> statusCode >= 200 && statusCode <= 399);
|
||||
|
||||
private final Set<Component> components = new HashSet<>();
|
||||
private final Set<Subscription> subscriptions = new HashSet<>();
|
||||
private DaprProtocol protocol = DaprProtocol.HTTP;
|
||||
|
@ -59,23 +65,9 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
public DaprContainer(DockerImageName dockerImageName) {
|
||||
super(dockerImageName);
|
||||
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
|
||||
// For susbcriptions the container needs to access the app channel
|
||||
withAccessToHost(true);
|
||||
// Here we don't want to wait for the Dapr sidecar to be ready, as the sidecar
|
||||
// needs to
|
||||
// connect with the application for susbcriptions
|
||||
|
||||
withExposedPorts(DAPRD_DEFAULT_HTTP_PORT, DAPRD_DEFAULT_GRPC_PORT);
|
||||
|
||||
}
|
||||
|
||||
private static Yaml getYamlMapper() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setPrettyFlow(true);
|
||||
Representer representer = new Representer(options);
|
||||
representer.addClassTag(MetadataEntry.class, Tag.MAP);
|
||||
return new Yaml(representer);
|
||||
setWaitStrategy(WAIT_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,8 +116,6 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a Dapr component from a YAML file.
|
||||
* @param path Path to the YAML file.
|
||||
|
@ -197,6 +187,7 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
if (!component.getMetadata().isEmpty()) {
|
||||
componentSpec.put("metadata", component.getMetadata());
|
||||
}
|
||||
|
||||
componentProps.put("spec", componentSpec);
|
||||
return Collections.unmodifiableMap(componentProps);
|
||||
}
|
||||
|
@ -231,6 +222,7 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
if (getNetwork() == null) {
|
||||
withNetwork(Network.newNetwork());
|
||||
}
|
||||
|
||||
if (this.placementContainer == null) {
|
||||
this.placementContainer = new DaprPlacementContainer(this.placementDockerImageName)
|
||||
.withNetwork(getNetwork())
|
||||
|
@ -253,10 +245,12 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
cmds.add("--app-channel-address");
|
||||
cmds.add(appChannelAddress);
|
||||
}
|
||||
|
||||
if (appPort != null) {
|
||||
cmds.add("--app-port");
|
||||
cmds.add(Integer.toString(appPort));
|
||||
}
|
||||
|
||||
cmds.add("--log-level");
|
||||
cmds.add(daprLogLevel.toString());
|
||||
cmds.add("-components-path");
|
||||
|
@ -338,4 +332,13 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
|
|||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
private static Yaml getYamlMapper() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setPrettyFlow(true);
|
||||
Representer representer = new Representer(options);
|
||||
representer.addClassTag(MetadataEntry.class, Tag.MAP);
|
||||
return new Yaml(representer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public enum DaprProtocol {
|
|||
HTTP("http"),
|
||||
GRPC("grpc");
|
||||
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
DaprProtocol(String name) {
|
||||
this.name = name;
|
||||
|
|
|
@ -14,10 +14,10 @@ limitations under the License.
|
|||
package io.dapr.testcontainers;
|
||||
|
||||
public class Subscription {
|
||||
private String name;
|
||||
private String pubsubName;
|
||||
private String topic;
|
||||
private String route;
|
||||
private final String name;
|
||||
private final String pubsubName;
|
||||
private final String topic;
|
||||
private final String route;
|
||||
|
||||
/**
|
||||
* Creates a new subscription.
|
||||
|
|
|
@ -13,8 +13,7 @@ limitations under the License.
|
|||
|
||||
package io.dapr.testcontainers;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
|
@ -22,7 +21,9 @@ import java.nio.file.Paths;
|
|||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class DaprComponentTest {
|
||||
|
||||
|
@ -39,10 +40,10 @@ public class DaprComponentTest {
|
|||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Component> components = dapr.getComponents();
|
||||
Assert.assertEquals(1, components.size());
|
||||
assertEquals(1, components.size());
|
||||
|
||||
Component kvstore = components.iterator().next();
|
||||
Assert.assertEquals(false, kvstore.getMetadata().isEmpty());
|
||||
assertFalse(kvstore.getMetadata().isEmpty());
|
||||
|
||||
String componentYaml = dapr.componentToYaml(kvstore);
|
||||
String expectedComponentYaml = "metadata:\n" + " name: statestore\n"
|
||||
|
@ -55,25 +56,21 @@ public class DaprComponentTest {
|
|||
+ " type: state.in-memory\n"
|
||||
+ " version: v1\n";
|
||||
|
||||
Assert.assertEquals(expectedComponentYaml, componentYaml);
|
||||
assertEquals(expectedComponentYaml, componentYaml);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containerConfigurationTest() {
|
||||
DaprContainer dapr = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withDaprLogLevel(DaprLogLevel.DEBUG)
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withDaprLogLevel(DaprLogLevel.DEBUG)
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
dapr.configure();
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> { dapr.getHttpEndpoint(); });
|
||||
assertThrows(IllegalStateException.class, () -> { dapr.getGrpcPort(); });
|
||||
|
||||
|
||||
|
||||
|
||||
assertThrows(IllegalStateException.class, dapr::getHttpEndpoint);
|
||||
assertThrows(IllegalStateException.class, dapr::getGrpcPort);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -85,7 +82,7 @@ public class DaprComponentTest {
|
|||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Subscription> subscriptions = dapr.getSubscriptions();
|
||||
Assert.assertEquals(1, subscriptions.size());
|
||||
assertEquals(1, subscriptions.size());
|
||||
|
||||
String subscriptionYaml = dapr.subscriptionToYaml(subscriptions.iterator().next());
|
||||
String expectedSubscriptionYaml = "metadata:\n" + " name: my-subscription\n"
|
||||
|
@ -95,7 +92,7 @@ public class DaprComponentTest {
|
|||
+ " route: /events\n"
|
||||
+ " pubsubname: pubsub\n"
|
||||
+ " topic: topic\n";
|
||||
Assert.assertEquals(expectedSubscriptionYaml, subscriptionYaml);
|
||||
assertEquals(expectedSubscriptionYaml, subscriptionYaml);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -110,9 +107,9 @@ public class DaprComponentTest {
|
|||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Component> components = dapr.getComponents();
|
||||
Assert.assertEquals(1, components.size());
|
||||
assertEquals(1, components.size());
|
||||
Component kvstore = components.iterator().next();
|
||||
Assert.assertEquals(false, kvstore.getMetadata().isEmpty());
|
||||
assertFalse(kvstore.getMetadata().isEmpty());
|
||||
|
||||
String componentYaml = dapr.componentToYaml(kvstore);
|
||||
String expectedComponentYaml = "metadata:\n"
|
||||
|
@ -136,6 +133,6 @@ public class DaprComponentTest {
|
|||
+ " type: null\n"
|
||||
+ " version: v1\n";
|
||||
|
||||
Assert.assertEquals(expectedComponentYaml, componentYaml);
|
||||
assertEquals(expectedComponentYaml, componentYaml);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue