mirror of https://github.com/dapr/java-sdk.git
Initial Testcontainers integration for Dapr (#1085)
* initial testcontainers pr Signed-off-by: salaboy <Salaboy@gmail.com> * fixing variable reference Signed-off-by: salaboy <Salaboy@gmail.com> * adding equals to spotbug issues Signed-off-by: salaboy <Salaboy@gmail.com> * adding http port to run tests Signed-off-by: salaboy <Salaboy@gmail.com> * updating pom Signed-off-by: salaboy <Salaboy@gmail.com> * fixing style Signed-off-by: salaboy <Salaboy@gmail.com> * extracting classes Signed-off-by: salaboy <Salaboy@gmail.com> * removing restassured dependency Signed-off-by: salaboy <Salaboy@gmail.com> * refactoring IT out to sdk-tests Signed-off-by: salaboy <Salaboy@gmail.com> * adding correct wiremock dep version Signed-off-by: salaboy <Salaboy@gmail.com> * missing header Signed-off-by: salaboy <Salaboy@gmail.com> * fixing spotbugs issue Signed-off-by: salaboy <Salaboy@gmail.com> * adding hashcode too Signed-off-by: salaboy <Salaboy@gmail.com> * testing configure method Signed-off-by: salaboy <Salaboy@gmail.com> * making inmutable collections and maps Signed-off-by: salaboy <Salaboy@gmail.com> * checkstyle Signed-off-by: salaboy <Salaboy@gmail.com> * removing space Signed-off-by: salaboy <Salaboy@gmail.com> * Refactor tracking of alpha artifact version Signed-off-by: Artur Souza <asouza.pro@gmail.com> Signed-off-by: salaboy <Salaboy@gmail.com> * Use Usage: docker compose [OPTIONS] COMMAND Define and run multi-container applications with Docker Options: --all-resources Include all resources, even those not used by services --ansi string Control when to print ANSI control characters ("never"|"always"|"auto") (default "auto") --compatibility Run compose in backward compatibility mode --dry-run Execute command in dry run mode --env-file stringArray Specify an alternate environment file -f, --file stringArray Compose configuration files --parallel int Control max parallelism, -1 for unlimited (default -1) --profile stringArray Specify a profile to enable --progress string Set type of progress output (auto, tty, plain, quiet) (default "auto") --project-directory string Specify an alternate working directory (default: the path of the, first specified, Compose file) -p, --project-name string Project name Commands: attach Attach local standard input, output, and error streams to a service's running container build Build or rebuild services config Parse, resolve and render compose file in canonical format cp Copy files/folders between a service container and the local filesystem create Creates containers for a service down Stop and remove containers, networks events Receive real time events from containers exec Execute a command in a running container images List images used by the created containers kill Force stop service containers logs View output from containers ls List running compose projects pause Pause services port Print the public port for a port binding ps List containers pull Pull service images push Push service images restart Restart service containers rm Removes stopped service containers run Run a one-off command on a service scale Scale services start Start services stats Display a live stream of container(s) resource usage statistics stop Stop services top Display the running processes unpause Unpause services up Create and start containers version Show the Docker Compose version information wait Block until the first service container stops watch Watch build context for service and rebuild/refresh containers when files are updated Run 'docker compose COMMAND --help' for more information on a command. instead of docker-compose Signed-off-by: Artur Souza <asouza.pro@gmail.com> Signed-off-by: salaboy <Salaboy@gmail.com> * removing version from docker compose Signed-off-by: salaboy <Salaboy@gmail.com> * Update README.md Signed-off-by: Artur Souza <asouza.pro@gmail.com> --------- Signed-off-by: salaboy <Salaboy@gmail.com> Signed-off-by: Artur Souza <asouza.pro@gmail.com> Co-authored-by: Artur Souza <asouza.pro@gmail.com>
This commit is contained in:
parent
5618af5ed9
commit
e30dc2df28
|
@ -4,14 +4,23 @@ set -uex
|
|||
|
||||
DAPR_JAVA_SDK_VERSION=$1
|
||||
|
||||
# The workflows sdk tracks the regular SDK minor and patch versions, just not the major.
|
||||
# Replaces the workflows SDK major version to 0 until it is stable.
|
||||
DAPR_JAVA_WORKFLOWS_SDK_VERSION=`echo $DAPR_JAVA_SDK_VERSION | sed 's/^[0-9]*\./0./'`
|
||||
# Alpha artifacts of the sdk tracks the regular SDK minor and patch versions, just not the major.
|
||||
# Replaces the SDK major version to 0 for alpha artifacts.
|
||||
DAPR_JAVA_SDK_ALPHA_VERSION=`echo $DAPR_JAVA_SDK_VERSION | sed 's/^[0-9]*\./0./'`
|
||||
|
||||
mvn versions:set -DnewVersion=$DAPR_JAVA_SDK_VERSION
|
||||
mvn versions:set-property -Dproperty=dapr.sdk.alpha.version -DnewVersion=$DAPR_JAVA_SDK_ALPHA_VERSION
|
||||
mvn versions:set-property -Dproperty=dapr.sdk.version -DnewVersion=$DAPR_JAVA_SDK_VERSION -f sdk-tests/pom.xml
|
||||
mvn versions:set-property -Dproperty=dapr.sdk.alpha.version -DnewVersion=$DAPR_JAVA_SDK_ALPHA_VERSION -f sdk-tests/pom.xml
|
||||
|
||||
mvn versions:set -DnewVersion=$DAPR_JAVA_WORKFLOWS_SDK_VERSION -f sdk-workflows/pom.xml
|
||||
mvn versions:set-property -Dproperty=dapr.sdk-workflows.version -DnewVersion=$DAPR_JAVA_WORKFLOWS_SDK_VERSION
|
||||
###################
|
||||
# Alpha artifacts #
|
||||
###################
|
||||
|
||||
# sdk-workflows
|
||||
mvn versions:set -DnewVersion=$DAPR_JAVA_SDK_ALPHA_VERSION -f sdk-workflows/pom.xml
|
||||
|
||||
# testcontainers-dapr
|
||||
mvn versions:set -DnewVersion=$DAPR_JAVA_SDK_ALPHA_VERSION -f testcontainers-dapr/pom.xml
|
||||
|
||||
git clean -f
|
||||
|
|
|
@ -99,7 +99,7 @@ jobs:
|
|||
./dist/linux_amd64/release/placement &
|
||||
- name: Spin local environment
|
||||
run: |
|
||||
docker-compose -f ./sdk-tests/deploy/local-test.yml up -d mongo kafka
|
||||
docker compose -f ./sdk-tests/deploy/local-test.yml up -d mongo kafka
|
||||
docker ps
|
||||
- name: Install local ToxiProxy to simulate connectivity issues to Dapr sidecar
|
||||
run: |
|
||||
|
|
|
@ -237,13 +237,13 @@ Similarly, all of these need to be run for running the ITs either individually o
|
|||
Run the following commands from the root of the repo to start all the docker containers that the tests depend on.
|
||||
|
||||
```bash
|
||||
docker-compose -f ./sdk-tests/deploy/local-test.yml up -d
|
||||
docker compose -f ./sdk-tests/deploy/local-test.yml up -d
|
||||
```
|
||||
|
||||
To stop the containers and services, run the following commands.
|
||||
|
||||
```bash
|
||||
docker-compose -f ./sdk-tests/deploy/local-test.yml down
|
||||
docker compose -f ./sdk-tests/deploy/local-test.yml down
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>dapr-sdk-workflows</artifactId>
|
||||
<version>${dapr.sdk-workflows.version}</version>
|
||||
<version>${dapr.sdk.alpha.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
|
|
|
@ -58,13 +58,11 @@ Before getting into the application code, follow these steps in order to set up
|
|||
|
||||
<!-- STEP
|
||||
name: Setup kafka container
|
||||
expected_stderr_lines:
|
||||
- 'Creating network "http_default" with the default driver'
|
||||
sleep: 20
|
||||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/bindings/http/docker-compose-single-kafka.yml up -d
|
||||
docker compose -f ./src/main/java/io/dapr/examples/bindings/http/docker-compose-single-kafka.yml up -d
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
@ -248,7 +246,7 @@ name: Cleanup Kafka containers
|
|||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/bindings/http/docker-compose-single-kafka.yml down
|
||||
docker compose -f ./src/main/java/io/dapr/examples/bindings/http/docker-compose-single-kafka.yml down
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3'
|
||||
services:
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:7.4.4
|
||||
|
|
|
@ -44,7 +44,7 @@ sleep: 5
|
|||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml up -d
|
||||
docker compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml up -d
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
@ -305,7 +305,7 @@ name: Cleanup MongoDB containers
|
|||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml down
|
||||
docker compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml down
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3'
|
||||
services:
|
||||
mongo:
|
||||
image: mongo
|
||||
|
|
|
@ -44,7 +44,7 @@ sleep: 5
|
|||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml up -d
|
||||
docker compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml up -d
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
@ -227,7 +227,7 @@ name: Cleanup MongoDB container
|
|||
-->
|
||||
|
||||
```bash
|
||||
docker-compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml down
|
||||
docker compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml down
|
||||
```
|
||||
|
||||
<!-- END_STEP -->
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
version: '3'
|
||||
services:
|
||||
mongo:
|
||||
image: mongo
|
||||
|
|
6
pom.xml
6
pom.xml
|
@ -17,7 +17,7 @@
|
|||
<grpc.version>1.59.0</grpc.version>
|
||||
<protobuf.version>3.17.3</protobuf.version>
|
||||
<dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/v1.13.0-rc.5/dapr/proto</dapr.proto.baseurl>
|
||||
<dapr.sdk-workflows.version>0.12.0-SNAPSHOT</dapr.sdk-workflows.version>
|
||||
<dapr.sdk.alpha.version>0.12.0-SNAPSHOT</dapr.sdk.alpha.version>
|
||||
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
|
||||
<maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
|
||||
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>
|
||||
|
@ -38,6 +38,8 @@
|
|||
<failsafe.version>3.2.2</failsafe.version>
|
||||
<surefire.version>3.2.2</surefire.version>
|
||||
<junit-bom.version>5.8.2</junit-bom.version>
|
||||
<snakeyaml.version>2.0</snakeyaml.version>
|
||||
<testcontainers.version>1.20.0</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
<distributionManagement>
|
||||
|
@ -330,6 +332,8 @@
|
|||
<module>sdk-workflows</module>
|
||||
<module>sdk-springboot</module>
|
||||
<module>examples</module>
|
||||
<!-- We are following test containers artifact convention on purpose, don't rename -->
|
||||
<module>testcontainers-dapr</module>
|
||||
<!-- don't add sdk-tests to the build,
|
||||
it's only used for CI testing by github action
|
||||
<module>sdk-tests</module>
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
<dapr.sdk.version>1.12.0-SNAPSHOT</dapr.sdk.version>
|
||||
<dapr.sdk.alpha.version>0.12.0-SNAPSHOT</dapr.sdk.alpha.version>
|
||||
<protobuf.output.directory>${project.build.directory}/generated-sources</protobuf.output.directory>
|
||||
<protobuf.input.directory>${project.basedir}/proto</protobuf.input.directory>
|
||||
<grpc.version>1.59.0</grpc.version>
|
||||
<protobuf.version>3.17.3</protobuf.version>
|
||||
<opentelemetry.version>1.39.0</opentelemetry.version>
|
||||
<spring-boot.version>3.3.1</spring-boot.version>
|
||||
<logback-classic.version>1.4.12</logback-classic.version>
|
||||
<wiremock.version>3.9.1</wiremock.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -130,6 +133,12 @@
|
|||
<version>${dapr.sdk.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>testcontainers-dapr</artifactId>
|
||||
<version>${dapr.sdk.alpha.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>dapr-sdk-actors</artifactId>
|
||||
|
@ -147,6 +156,18 @@
|
|||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wiremock</groupId>
|
||||
<artifactId>wiremock-standalone</artifactId>
|
||||
<version>${wiremock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback-classic.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.it.testcontainers;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import io.dapr.client.DaprClient;
|
||||
import io.dapr.client.DaprClientBuilder;
|
||||
import io.dapr.client.domain.Metadata;
|
||||
import io.dapr.client.domain.State;
|
||||
|
||||
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 java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.any;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.configureFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
|
||||
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 java.util.Collections.singletonMap;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DaprContainerTest {
|
||||
|
||||
// Time-to-live for messages published.
|
||||
private static final String MESSAGE_TTL_IN_SECONDS = "1000";
|
||||
private static final String STATE_STORE_NAME = "kvstore";
|
||||
private static final String KEY = "my-key";
|
||||
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
|
||||
public static DaprContainer daprContainer = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
/**
|
||||
* Sets the Dapr properties for the test.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void setDaprProperties() {
|
||||
configStub();
|
||||
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)));
|
||||
|
||||
stubFor(get(urlMatching("/dapr/config"))
|
||||
.willReturn(aResponse().withBody("[]").withStatus(200)));
|
||||
|
||||
stubFor(any(urlMatching("/([a-z1-9]*)"))
|
||||
.willReturn(aResponse().withBody("[]").withStatus(200)));
|
||||
|
||||
// create a stub
|
||||
stubFor(post(urlEqualTo("/events"))
|
||||
.willReturn(aResponse().withBody("event received!").withStatus(200)));
|
||||
|
||||
configureFor("localhost", 8081);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDaprContainerDefaults() {
|
||||
assertEquals(
|
||||
"The pubsub and kvstore component should be configured by default",
|
||||
2,
|
||||
daprContainer.getComponents().size());
|
||||
assertEquals(
|
||||
"A subscription should be configured by default if none is provided",
|
||||
1,
|
||||
daprContainer.getSubscriptions().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateStore() throws Exception {
|
||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||
client.waitForSidecar(5000).block();
|
||||
|
||||
String value = "value";
|
||||
// Save state
|
||||
client.saveState(STATE_STORE_NAME, KEY, value).block();
|
||||
|
||||
// Get the state back from the state store
|
||||
State<String> retrievedState = client.getState(STATE_STORE_NAME, KEY, String.class).block();
|
||||
|
||||
assertEquals("The value retrieved should be the same as the one stored", value, retrievedState.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
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();
|
||||
}
|
||||
|
||||
OkHttpClient client = new OkHttpClient.Builder().build();
|
||||
|
||||
String url = "http://" + daprContainer.getHost() + ":" + daprContainer.getMappedPort(3500);
|
||||
Request request = new Request.Builder().url(url + "/v1.0/metadata").build();
|
||||
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
if (response.isSuccessful()) {
|
||||
assertTrue(response.body().string().contains("placement: connected"));
|
||||
|
||||
} else {
|
||||
throw new IOException("Unexpected response: " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPubSub() throws Exception {
|
||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
||||
client.waitForSidecar(5000).block();
|
||||
|
||||
String message = "message content";
|
||||
Map<String, String> metadata = singletonMap(Metadata.TTL_IN_SECONDS, MESSAGE_TTL_IN_SECONDS);
|
||||
client.publishEvent(PUBSUB_NAME, PUBSUB_TOPIC_NAME, message, metadata).block();
|
||||
}
|
||||
|
||||
verify(getRequestedFor(urlMatching("/dapr/config")));
|
||||
verify(postRequestedFor(urlEqualTo("/events")).withHeader("Content-Type", equalTo("application/cloudevents+json")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>dapr-sdk-parent</artifactId>
|
||||
<version>1.12.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>testcontainers-dapr</artifactId>
|
||||
<name>testcontainers-dapr</name>
|
||||
<description>Testcontainers Dapr Module</description>
|
||||
<version>0.12.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>${snakeyaml.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dapr</groupId>
|
||||
<artifactId>dapr-sdk</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.11</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target/jacoco-report/</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>check</id>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<rule>
|
||||
<element>BUNDLE</element>
|
||||
<limits>
|
||||
<limit>
|
||||
<counter>LINE</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>80%</minimum>
|
||||
</limit>
|
||||
</limits>
|
||||
</rule>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a Dapr component.
|
||||
*/
|
||||
public class Component {
|
||||
private String name;
|
||||
private String type;
|
||||
private String version;
|
||||
private List<MetadataEntry> metadata;
|
||||
|
||||
/**
|
||||
* Creates a new component.
|
||||
*
|
||||
* @param name Component name.
|
||||
* @param type Component type.
|
||||
* @param version Component version.
|
||||
* @param metadata Metadata.
|
||||
*/
|
||||
public Component(String name, String type, String version, Map<String, String> metadata) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.version = version;
|
||||
|
||||
List<MetadataEntry> entries = new ArrayList<>();
|
||||
if (!metadata.isEmpty()) {
|
||||
for (Map.Entry<String, String> entry : metadata.entrySet()) {
|
||||
entries.add(new MetadataEntry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
this.metadata = Collections.unmodifiableList(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new component.
|
||||
*
|
||||
* @param name Component name.
|
||||
* @param type Component type.
|
||||
* @param version Component version.
|
||||
* @param metadataEntries Component metadata entries.
|
||||
*/
|
||||
public Component(String name, String type, String version, List<MetadataEntry> metadataEntries) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.version = version;
|
||||
metadata = Objects.requireNonNull(metadataEntries);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<MetadataEntry> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.Network;
|
||||
import org.testcontainers.images.builder.Transferable;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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 final Set<Component> components = new HashSet<>();
|
||||
private final Set<Subscription> subscriptions = new HashSet<>();
|
||||
private DaprProtocol protocol = DaprProtocol.HTTP;
|
||||
private String appName;
|
||||
private Integer appPort = null;
|
||||
private DaprLogLevel daprLogLevel = DaprLogLevel.INFO;
|
||||
private String appChannelAddress = "localhost";
|
||||
private String placementService = "placement";
|
||||
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("daprio/daprd");
|
||||
private static final Yaml yaml = getYamlMapper();
|
||||
private DaprPlacementContainer placementContainer;
|
||||
private String placementDockerImageName = "daprio/placement";
|
||||
private boolean shouldReusePlacement;
|
||||
|
||||
/**
|
||||
* Creates a new Dapr container.
|
||||
* @param dockerImageName Docker image name.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Dapr container.
|
||||
* @param image Docker image name.
|
||||
*/
|
||||
public DaprContainer(String image) {
|
||||
this(DockerImageName.parse(image));
|
||||
}
|
||||
|
||||
public Set<Component> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public Set<Subscription> getSubscriptions() {
|
||||
return subscriptions;
|
||||
}
|
||||
|
||||
public DaprContainer withAppPort(Integer port) {
|
||||
this.appPort = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withPlacementService(String placementService) {
|
||||
this.placementService = placementService;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withAppName(String appName) {
|
||||
this.appName = appName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withDaprLogLevel(DaprLogLevel daprLogLevel) {
|
||||
this.daprLogLevel = daprLogLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withSubscription(Subscription subscription) {
|
||||
subscriptions.add(subscription);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withComponent(Component component) {
|
||||
components.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a Dapr component from a YAML file.
|
||||
* @param path Path to the YAML file.
|
||||
* @return This container.
|
||||
*/
|
||||
public DaprContainer withComponent(Path path) {
|
||||
try {
|
||||
Map<String, Object> component = this.yaml.loadAs(Files.newInputStream(path), Map.class);
|
||||
|
||||
String type = (String) component.get("type");
|
||||
Map<String, Object> metadata = (Map<String, Object>) component.get("metadata");
|
||||
String name = (String) metadata.get("name");
|
||||
|
||||
Map<String, Object> spec = (Map<String, Object>) component.get("spec");
|
||||
String version = (String) spec.get("version");
|
||||
List<Map<String, String>> specMetadata =
|
||||
(List<Map<String, String>>) spec.getOrDefault("metadata", Collections.emptyMap());
|
||||
|
||||
ArrayList<MetadataEntry> metadataEntries = new ArrayList<>();
|
||||
|
||||
for (Map<String, String> specMetadataItem : specMetadata) {
|
||||
for (Map.Entry<String, String> metadataItem : specMetadataItem.entrySet()) {
|
||||
metadataEntries.add(new MetadataEntry(metadataItem.getKey(), metadataItem.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return withComponent(new Component(name, type, version, metadataEntries));
|
||||
} catch (IOException e) {
|
||||
logger().warn("Error while reading component from {}", path.toAbsolutePath());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getHttpPort() {
|
||||
return getMappedPort(DAPRD_DEFAULT_HTTP_PORT);
|
||||
}
|
||||
|
||||
public String getHttpEndpoint() {
|
||||
return "http://" + getHost() + ":" + getMappedPort(DAPRD_DEFAULT_HTTP_PORT);
|
||||
}
|
||||
|
||||
public int getGrpcPort() {
|
||||
return getMappedPort(DAPRD_DEFAULT_GRPC_PORT);
|
||||
}
|
||||
|
||||
public DaprContainer withAppChannelAddress(String appChannelAddress) {
|
||||
this.appChannelAddress = appChannelAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of Dapr component details.
|
||||
* @param component A Dapr Component.
|
||||
* @return Map of component details.
|
||||
*/
|
||||
public Map<String, Object> componentToMap(Component component) {
|
||||
Map<String, Object> componentProps = new HashMap<>();
|
||||
componentProps.put("apiVersion", "dapr.io/v1alpha1");
|
||||
componentProps.put("kind", "Component");
|
||||
|
||||
Map<String, String> componentMetadata = new LinkedHashMap<>();
|
||||
componentMetadata.put("name", component.getName());
|
||||
componentProps.put("metadata", componentMetadata);
|
||||
|
||||
Map<String, Object> componentSpec = new HashMap<>();
|
||||
componentSpec.put("type", component.getType());
|
||||
componentSpec.put("version", component.getVersion());
|
||||
|
||||
if (!component.getMetadata().isEmpty()) {
|
||||
componentSpec.put("metadata", component.getMetadata());
|
||||
}
|
||||
componentProps.put("spec", componentSpec);
|
||||
return Collections.unmodifiableMap(componentProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of Dapr subscription details.
|
||||
* @param subscription A Dapr Subscription.
|
||||
* @return Map of subscription details.
|
||||
*/
|
||||
public Map<String, Object> subscriptionToMap(Subscription subscription) {
|
||||
Map<String, Object> subscriptionProps = new HashMap<>();
|
||||
subscriptionProps.put("apiVersion", "dapr.io/v1alpha1");
|
||||
subscriptionProps.put("kind", "Subscription");
|
||||
|
||||
Map<String, String> subscriptionMetadata = new LinkedHashMap<>();
|
||||
subscriptionMetadata.put("name", subscription.getName());
|
||||
subscriptionProps.put("metadata", subscriptionMetadata);
|
||||
|
||||
Map<String, Object> subscriptionSpec = new HashMap<>();
|
||||
subscriptionSpec.put("pubsubname", subscription.getPubsubName());
|
||||
subscriptionSpec.put("topic", subscription.getTopic());
|
||||
subscriptionSpec.put("route", subscription.getRoute());
|
||||
|
||||
subscriptionProps.put("spec", subscriptionSpec);
|
||||
return Collections.unmodifiableMap(subscriptionProps);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
|
||||
if (getNetwork() == null) {
|
||||
withNetwork(Network.newNetwork());
|
||||
}
|
||||
if (this.placementContainer == null) {
|
||||
this.placementContainer = new DaprPlacementContainer(this.placementDockerImageName)
|
||||
.withNetwork(getNetwork())
|
||||
.withNetworkAliases(placementService)
|
||||
.withReuse(this.shouldReusePlacement);
|
||||
this.placementContainer.start();
|
||||
}
|
||||
|
||||
List<String> cmds = new ArrayList<>();
|
||||
cmds.add("./daprd");
|
||||
cmds.add("-app-id");
|
||||
cmds.add(appName);
|
||||
cmds.add("--dapr-listen-addresses=0.0.0.0");
|
||||
cmds.add("--app-protocol");
|
||||
cmds.add(protocol.getName());
|
||||
cmds.add("-placement-host-address");
|
||||
cmds.add(placementService + ":50005");
|
||||
|
||||
if (appChannelAddress != null && !appChannelAddress.isEmpty()) {
|
||||
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");
|
||||
cmds.add("/dapr-resources");
|
||||
withCommand(cmds.toArray(new String[]{}));
|
||||
|
||||
if (components.isEmpty()) {
|
||||
components.add(new Component("kvstore", "state.in-memory", "v1", Collections.emptyMap()));
|
||||
components.add(new Component("pubsub", "pubsub.in-memory", "v1", Collections.emptyMap()));
|
||||
}
|
||||
|
||||
if (subscriptions.isEmpty() && !components.isEmpty()) {
|
||||
subscriptions.add(new Subscription("local", "pubsub", "topic", "/events"));
|
||||
}
|
||||
|
||||
for (Component component : components) {
|
||||
String componentYaml = componentToYaml(component);
|
||||
withCopyToContainer(Transferable.of(componentYaml), "/dapr-resources/" + component.getName() + ".yaml");
|
||||
}
|
||||
|
||||
for (Subscription subscription : subscriptions) {
|
||||
String subscriptionYaml = subscriptionToYaml(subscription);
|
||||
withCopyToContainer(Transferable.of(subscriptionYaml), "/dapr-resources/" + subscription.getName() + ".yaml");
|
||||
}
|
||||
}
|
||||
|
||||
public String subscriptionToYaml(Subscription subscription) {
|
||||
Map<String, Object> subscriptionMap = subscriptionToMap(subscription);
|
||||
return yaml.dumpAsMap(subscriptionMap);
|
||||
}
|
||||
|
||||
public String componentToYaml(Component component) {
|
||||
Map<String, Object> componentMap = componentToMap(component);
|
||||
return yaml.dumpAsMap(componentMap);
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public Integer getAppPort() {
|
||||
return appPort;
|
||||
}
|
||||
|
||||
public String getAppChannelAddress() {
|
||||
return appChannelAddress;
|
||||
}
|
||||
|
||||
public String getPlacementService() {
|
||||
return placementService;
|
||||
}
|
||||
|
||||
public static DockerImageName getDefaultImageName() {
|
||||
return DEFAULT_IMAGE_NAME;
|
||||
}
|
||||
|
||||
public DaprContainer withPlacementImage(String placementDockerImageName) {
|
||||
this.placementDockerImageName = placementDockerImageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withReusablePlacement(boolean reuse) {
|
||||
this.shouldReusePlacement = reuse;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaprContainer withPlacementContainer(DaprPlacementContainer placementContainer) {
|
||||
this.placementContainer = placementContainer;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Required by spotbugs plugin
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
public enum DaprLogLevel {
|
||||
ERROR,
|
||||
WARN,
|
||||
INFO,
|
||||
DEBUG
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
/**
|
||||
* Test container for Dapr placement service.
|
||||
*/
|
||||
public class DaprPlacementContainer extends GenericContainer<DaprPlacementContainer> {
|
||||
|
||||
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("daprio/placement");
|
||||
private int placementPort = 50005;
|
||||
|
||||
/**
|
||||
* Creates a new Dapr placement container.
|
||||
* @param dockerImageName Docker image name.
|
||||
*/
|
||||
public DaprPlacementContainer(DockerImageName dockerImageName) {
|
||||
super(dockerImageName);
|
||||
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
|
||||
|
||||
withExposedPorts(placementPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Dapr placement container.
|
||||
* @param image Docker image name.
|
||||
*/
|
||||
public DaprPlacementContainer(String image) {
|
||||
this(DockerImageName.parse(image));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
withCommand("./placement", "-port", Integer.toString(placementPort));
|
||||
}
|
||||
|
||||
public static DockerImageName getDefaultImageName() {
|
||||
return DEFAULT_IMAGE_NAME;
|
||||
}
|
||||
|
||||
public DaprPlacementContainer withPort(Integer port) {
|
||||
this.placementPort = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return placementPort;
|
||||
}
|
||||
|
||||
// Required by spotbugs plugin
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
public enum DaprProtocol {
|
||||
HTTP("http"),
|
||||
GRPC("grpc");
|
||||
|
||||
private String name;
|
||||
|
||||
DaprProtocol(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
public class MetadataEntry {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public MetadataEntry(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
public class Subscription {
|
||||
private String name;
|
||||
private String pubsubName;
|
||||
private String topic;
|
||||
private String route;
|
||||
|
||||
/**
|
||||
* Creates a new subscription.
|
||||
*
|
||||
* @param name Subscription name.
|
||||
* @param pubsubName PubSub name.
|
||||
* @param topic Topic name.
|
||||
* @param route Route.
|
||||
*/
|
||||
public Subscription(String name, String pubsubName, String topic, String route) {
|
||||
this.name = name;
|
||||
this.pubsubName = pubsubName;
|
||||
this.topic = topic;
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPubsubName() {
|
||||
return pubsubName;
|
||||
}
|
||||
|
||||
public String getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
public String getRoute() {
|
||||
return route;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class DaprComponentTest {
|
||||
|
||||
@Test
|
||||
public void componentStateStoreSerializationTest() {
|
||||
DaprContainer dapr = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withComponent(new Component(
|
||||
"statestore",
|
||||
"state.in-memory",
|
||||
"v1",
|
||||
Collections.singletonMap("actorStateStore", "true")))
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Component> components = dapr.getComponents();
|
||||
Assert.assertEquals(1, components.size());
|
||||
|
||||
Component kvstore = components.iterator().next();
|
||||
Assert.assertEquals(false, kvstore.getMetadata().isEmpty());
|
||||
|
||||
String componentYaml = dapr.componentToYaml(kvstore);
|
||||
String expectedComponentYaml = "metadata:\n" + " name: statestore\n"
|
||||
+ "apiVersion: dapr.io/v1alpha1\n"
|
||||
+ "kind: Component\n"
|
||||
+ "spec:\n"
|
||||
+ " metadata:\n"
|
||||
+ " - name: actorStateStore\n"
|
||||
+ " value: 'true'\n"
|
||||
+ " type: state.in-memory\n"
|
||||
+ " version: v1\n";
|
||||
|
||||
Assert.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");
|
||||
|
||||
dapr.configure();
|
||||
|
||||
assertThrows(IllegalStateException.class, () -> { dapr.getHttpEndpoint(); });
|
||||
assertThrows(IllegalStateException.class, () -> { dapr.getGrpcPort(); });
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subscriptionSerializationTest() {
|
||||
DaprContainer dapr = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withSubscription(new Subscription("my-subscription", "pubsub", "topic", "/events"))
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Subscription> subscriptions = dapr.getSubscriptions();
|
||||
Assert.assertEquals(1, subscriptions.size());
|
||||
|
||||
String subscriptionYaml = dapr.subscriptionToYaml(subscriptions.iterator().next());
|
||||
String expectedSubscriptionYaml = "metadata:\n" + " name: my-subscription\n"
|
||||
+ "apiVersion: dapr.io/v1alpha1\n"
|
||||
+ "kind: Subscription\n"
|
||||
+ "spec:\n"
|
||||
+ " route: /events\n"
|
||||
+ " pubsubname: pubsub\n"
|
||||
+ " topic: topic\n";
|
||||
Assert.assertEquals(expectedSubscriptionYaml, subscriptionYaml);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withComponentFromPath() {
|
||||
URL stateStoreYaml = this.getClass().getClassLoader().getResource("dapr-resources/statestore.yaml");
|
||||
Path path = Paths.get(stateStoreYaml.getPath());
|
||||
|
||||
DaprContainer dapr = new DaprContainer("daprio/daprd")
|
||||
.withAppName("dapr-app")
|
||||
.withAppPort(8081)
|
||||
.withComponent(path)
|
||||
.withAppChannelAddress("host.testcontainers.internal");
|
||||
|
||||
Set<Component> components = dapr.getComponents();
|
||||
Assert.assertEquals(1, components.size());
|
||||
Component kvstore = components.iterator().next();
|
||||
Assert.assertEquals(false, kvstore.getMetadata().isEmpty());
|
||||
|
||||
String componentYaml = dapr.componentToYaml(kvstore);
|
||||
String expectedComponentYaml = "metadata:\n"
|
||||
+ " name: statestore\n"
|
||||
+ "apiVersion: dapr.io/v1alpha1\n"
|
||||
+ "kind: Component\n"
|
||||
+ "spec:\n"
|
||||
+ " metadata:\n"
|
||||
+ " - name: name\n"
|
||||
+ " value: keyPrefix\n"
|
||||
+ " - name: value\n"
|
||||
+ " value: name\n"
|
||||
+ " - name: name\n"
|
||||
+ " value: redisHost\n"
|
||||
+ " - name: value\n"
|
||||
+ " value: redis:6379\n"
|
||||
+ " - name: name\n"
|
||||
+ " value: redisPassword\n"
|
||||
+ " - name: value\n"
|
||||
+ " value: ''\n"
|
||||
+ " type: null\n"
|
||||
+ " version: v1\n";
|
||||
|
||||
Assert.assertEquals(expectedComponentYaml, componentYaml);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2024 The Dapr Authors
|
||||
* 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.dapr.testcontainers;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DaprPlacementContainerTest {
|
||||
|
||||
@ClassRule
|
||||
public static DaprPlacementContainer placement = new DaprPlacementContainer("daprio/placement");
|
||||
|
||||
@Test
|
||||
public void testDaprPlacementContainerDefaults() {
|
||||
Assert.assertEquals("The default port is set", 50005, placement.getPort());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: dapr.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: statestore
|
||||
spec:
|
||||
type: state.redis
|
||||
version: v1
|
||||
metadata:
|
||||
- name: keyPrefix
|
||||
value: name
|
||||
- name: redisHost
|
||||
value: redis:6379
|
||||
- name: redisPassword
|
||||
value: ""
|
Loading…
Reference in New Issue