From 15da2eaf36287b482a5a3e7b7b1b1601e15a170c Mon Sep 17 00:00:00 2001 From: Cassie Coyle Date: Tue, 15 Jul 2025 15:42:43 -0500 Subject: [PATCH] [1.15] support for api token (#1453) * supporting spring boot property for API TOKEN on workflow interceptor (#1452) Signed-off-by: salaboy * Supporting placement and scheduler custom images (#1450) * supporting placement and scheduler custom images Signed-off-by: salaboy * Bump org.apache.commons:commons-lang3 from 3.9 to 3.18.0 (#1446) Bumps org.apache.commons:commons-lang3 from 3.9 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: artur-ciocanu Signed-off-by: salaboy * Update dapr docs for Hugo upgrade (#1443) Signed-off-by: Marc Duiker Co-authored-by: Cassie Coyle Signed-off-by: salaboy * Adds note about workflow start time (#1444) Signed-off-by: joshvanl Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com> Co-authored-by: artur-ciocanu Signed-off-by: salaboy * adding test to validate canonical names with substitutes Signed-off-by: salaboy * Migrate PubSub removing flaky test (#1407) * Migrate PubSub removing flaky test Signed-off-by: Matheus Cruz * Adjust assertion Signed-off-by: Matheus Cruz * Change assert Signed-off-by: Matheus Cruz * Apply pull request suggestions Signed-off-by: Matheus Cruz * Use custom ObjectSerializer Signed-off-by: Matheus Cruz --------- Signed-off-by: Matheus Cruz Co-authored-by: artur-ciocanu Signed-off-by: salaboy * adding tests for coverage Signed-off-by: salaboy --------- Signed-off-by: salaboy Signed-off-by: dependabot[bot] Signed-off-by: Marc Duiker Signed-off-by: joshvanl Signed-off-by: Matheus Cruz Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: artur-ciocanu Co-authored-by: Marc Duiker Co-authored-by: Cassie Coyle Co-authored-by: Josh van Leeuwen Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com> Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com> --------- Signed-off-by: salaboy Signed-off-by: dependabot[bot] Signed-off-by: Marc Duiker Signed-off-by: joshvanl Signed-off-by: Matheus Cruz Co-authored-by: salaboy Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: artur-ciocanu Co-authored-by: Marc Duiker Co-authored-by: Josh van Leeuwen Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com> Co-authored-by: Matheus Cruz <56329339+mcruzdev@users.noreply.github.com> Signed-off-by: siri-varma --- .../client/DaprClientAutoConfiguration.java | 10 ++++ .../client/DaprClientProperties.java | 15 +++++- .../client/DaprConnectionDetails.java | 4 ++ .../PropertiesDaprConnectionDetails.java | 6 +++ .../client/DaprClientPropertiesTest.java | 5 +- ...DaprContainerConnectionDetailsFactory.java | 8 +++ .../workflows/client/DaprWorkflowClient.java | 5 +- .../internal/ApiTokenClientInterceptor.java | 9 +++- .../runtime/WorkflowRuntimeBuilder.java | 6 ++- .../io/dapr/testcontainers/DaprContainer.java | 49 +++++++++++++------ .../testcontainers/DaprContainerTest.java | 46 +++++++++++++++++ 11 files changed, 140 insertions(+), 23 deletions(-) create mode 100644 testcontainers-dapr/src/test/java/io/dapr/testcontainers/DaprContainerTest.java diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java index 11e7d6c15..d003e09fd 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientAutoConfiguration.java @@ -68,6 +68,11 @@ public class DaprClientAutoConfiguration { builder.withPropertyOverride(Properties.GRPC_PORT, String.valueOf(grpcPort)); } + String apiToken = daprConnectionDetails.getApiToken(); + if (apiToken != null) { + builder.withPropertyOverride(Properties.API_TOKEN, apiToken); + } + return builder; } @@ -145,6 +150,11 @@ public class DaprClientAutoConfiguration { propertyOverrides.put(Properties.GRPC_PORT.getName(), String.valueOf(grpcPort)); } + String apiToken = daprConnectionDetails.getApiToken(); + if (apiToken != null) { + propertyOverrides.put(Properties.API_TOKEN.getName(), apiToken); + } + return new Properties(propertyOverrides); } diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientProperties.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientProperties.java index 135416946..1e1a114e5 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientProperties.java +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprClientProperties.java @@ -13,7 +13,6 @@ limitations under the License. package io.dapr.spring.boot.autoconfigure.client; -import io.dapr.spring.data.DaprKeyValueAdapterResolver; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "dapr.client") @@ -22,6 +21,7 @@ public class DaprClientProperties { private String grpcEndpoint; private Integer httpPort; private Integer grpcPort; + private String apiToken; /** @@ -36,12 +36,15 @@ public class DaprClientProperties { * @param grpcEndpoint grpc endpoint to interact with the Dapr Sidecar * @param httpPort http port to interact with the Dapr Sidecar * @param grpcPort grpc port to interact with the Dapr Sidecar + * @param apiToken dapr API token to interact with the Dapr Sidecar */ - public DaprClientProperties(String httpEndpoint, String grpcEndpoint, Integer httpPort, Integer grpcPort) { + public DaprClientProperties(String httpEndpoint, String grpcEndpoint, Integer httpPort, Integer grpcPort, + String apiToken) { this.httpEndpoint = httpEndpoint; this.grpcEndpoint = grpcEndpoint; this.httpPort = httpPort; this.grpcPort = grpcPort; + this.apiToken = apiToken; } public String getHttpEndpoint() { @@ -75,4 +78,12 @@ public class DaprClientProperties { public void setGrpcPort(Integer grpcPort) { this.grpcPort = grpcPort; } + + public String getApiToken() { + return apiToken; + } + + public void setApiToken(String apiToken) { + this.apiToken = apiToken; + } } diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprConnectionDetails.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprConnectionDetails.java index a2b3ddaff..b45dcd21e 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprConnectionDetails.java +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/DaprConnectionDetails.java @@ -16,6 +16,7 @@ package io.dapr.spring.boot.autoconfigure.client; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; public interface DaprConnectionDetails extends ConnectionDetails { + String getHttpEndpoint(); String getGrpcEndpoint(); @@ -23,4 +24,7 @@ public interface DaprConnectionDetails extends ConnectionDetails { Integer getHttpPort(); Integer getGrpcPort(); + + String getApiToken(); + } diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/PropertiesDaprConnectionDetails.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/PropertiesDaprConnectionDetails.java index ec46dde99..fd1f01f3a 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/PropertiesDaprConnectionDetails.java +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/main/java/io/dapr/spring/boot/autoconfigure/client/PropertiesDaprConnectionDetails.java @@ -40,4 +40,10 @@ class PropertiesDaprConnectionDetails implements DaprConnectionDetails { public Integer getGrpcPort() { return this.daprClientProperties.getGrpcPort(); } + + @Override + public String getApiToken() { + return this.daprClientProperties.getApiToken(); + } + } diff --git a/dapr-spring/dapr-spring-boot-autoconfigure/src/test/java/io/dapr/spring/boot/autoconfigure/client/DaprClientPropertiesTest.java b/dapr-spring/dapr-spring-boot-autoconfigure/src/test/java/io/dapr/spring/boot/autoconfigure/client/DaprClientPropertiesTest.java index 85bd605a7..7a1781d13 100644 --- a/dapr-spring/dapr-spring-boot-autoconfigure/src/test/java/io/dapr/spring/boot/autoconfigure/client/DaprClientPropertiesTest.java +++ b/dapr-spring/dapr-spring-boot-autoconfigure/src/test/java/io/dapr/spring/boot/autoconfigure/client/DaprClientPropertiesTest.java @@ -31,7 +31,7 @@ public class DaprClientPropertiesTest { public void shouldCreateDaprClientPropertiesCorrectly() { DaprClientProperties properties = new DaprClientProperties( - "http://localhost", "localhost", 3500, 50001 + "http://localhost", "localhost", 3500, 50001, "ABC" ); SoftAssertions.assertSoftly(softly -> { @@ -39,6 +39,7 @@ public class DaprClientPropertiesTest { softly.assertThat(properties.getHttpEndpoint()).isEqualTo("http://localhost"); softly.assertThat(properties.getHttpPort()).isEqualTo(3500); softly.assertThat(properties.getGrpcPort()).isEqualTo(50001); + softly.assertThat(properties.getApiToken()).isEqualTo("ABC"); }); } @@ -52,12 +53,14 @@ public class DaprClientPropertiesTest { properties.setGrpcPort(50001); properties.setHttpEndpoint("http://localhost"); properties.setHttpPort(3500); + properties.setApiToken("ABC"); SoftAssertions.assertSoftly(softAssertions -> { softAssertions.assertThat(properties.getGrpcEndpoint()).isEqualTo("localhost"); softAssertions.assertThat(properties.getHttpEndpoint()).isEqualTo("http://localhost"); softAssertions.assertThat(properties.getHttpPort()).isEqualTo(3500); softAssertions.assertThat(properties.getGrpcPort()).isEqualTo(50001); + softAssertions.assertThat(properties.getApiToken()).isEqualTo("ABC"); }); } diff --git a/dapr-spring/dapr-spring-boot-tests/src/main/java/io/dapr/spring/boot/testcontainers/service/connection/DaprContainerConnectionDetailsFactory.java b/dapr-spring/dapr-spring-boot-tests/src/main/java/io/dapr/spring/boot/testcontainers/service/connection/DaprContainerConnectionDetailsFactory.java index 12a822966..3f7d27e49 100644 --- a/dapr-spring/dapr-spring-boot-tests/src/main/java/io/dapr/spring/boot/testcontainers/service/connection/DaprContainerConnectionDetailsFactory.java +++ b/dapr-spring/dapr-spring-boot-tests/src/main/java/io/dapr/spring/boot/testcontainers/service/connection/DaprContainerConnectionDetailsFactory.java @@ -41,5 +41,13 @@ public class DaprContainerConnectionDetailsFactory public Integer getGrpcPort() { return getContainer().getGrpcPort(); } + + /* + * No API Token for local container + */ + @Override + public String getApiToken() { + return ""; + } } } diff --git a/sdk-workflows/src/main/java/io/dapr/workflows/client/DaprWorkflowClient.java b/sdk-workflows/src/main/java/io/dapr/workflows/client/DaprWorkflowClient.java index b24c8bcc9..d8b94edbe 100644 --- a/sdk-workflows/src/main/java/io/dapr/workflows/client/DaprWorkflowClient.java +++ b/sdk-workflows/src/main/java/io/dapr/workflows/client/DaprWorkflowClient.java @@ -37,8 +37,7 @@ import java.util.concurrent.TimeoutException; */ public class DaprWorkflowClient implements AutoCloseable { - private static final ClientInterceptor WORKFLOW_INTERCEPTOR = new ApiTokenClientInterceptor(); - + private ClientInterceptor workflowApiTokenInterceptor; private DurableTaskClient innerClient; private ManagedChannel grpcChannel; @@ -55,7 +54,7 @@ public class DaprWorkflowClient implements AutoCloseable { * @param properties Properties for the GRPC Channel. */ public DaprWorkflowClient(Properties properties) { - this(NetworkUtils.buildGrpcManagedChannel(properties, WORKFLOW_INTERCEPTOR)); + this(NetworkUtils.buildGrpcManagedChannel(properties, new ApiTokenClientInterceptor(properties))); } /** diff --git a/sdk-workflows/src/main/java/io/dapr/workflows/internal/ApiTokenClientInterceptor.java b/sdk-workflows/src/main/java/io/dapr/workflows/internal/ApiTokenClientInterceptor.java index 97f12c331..e5b4209d7 100644 --- a/sdk-workflows/src/main/java/io/dapr/workflows/internal/ApiTokenClientInterceptor.java +++ b/sdk-workflows/src/main/java/io/dapr/workflows/internal/ApiTokenClientInterceptor.java @@ -24,6 +24,13 @@ import io.grpc.Metadata; import io.grpc.MethodDescriptor; public class ApiTokenClientInterceptor implements ClientInterceptor { + + private Properties properties; + + public ApiTokenClientInterceptor(Properties properties) { + this.properties = properties; + } + @Override public ClientCall interceptCall( MethodDescriptor methodDescriptor, @@ -34,7 +41,7 @@ public class ApiTokenClientInterceptor implements ClientInterceptor { return new ForwardingClientCall.SimpleForwardingClientCall(clientCall) { @Override public void start(final Listener responseListener, final Metadata metadata) { - String daprApiToken = Properties.API_TOKEN.get(); + String daprApiToken = properties.getValue(Properties.API_TOKEN); if (daprApiToken != null) { metadata.put(Metadata.Key.of(Headers.DAPR_API_TOKEN, Metadata.ASCII_STRING_MARSHALLER), daprApiToken); } diff --git a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java index 7f1147a0d..5daff7747 100644 --- a/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java +++ b/sdk-workflows/src/main/java/io/dapr/workflows/runtime/WorkflowRuntimeBuilder.java @@ -23,6 +23,7 @@ import io.grpc.ClientInterceptor; import io.grpc.ManagedChannel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -30,7 +31,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class WorkflowRuntimeBuilder { - private static final ClientInterceptor WORKFLOW_INTERCEPTOR = new ApiTokenClientInterceptor(); + private ClientInterceptor workflowApiTokenInterceptor; private static volatile WorkflowRuntime instance; private final Logger logger; private final Set workflows = new HashSet<>(); @@ -62,7 +63,8 @@ public class WorkflowRuntimeBuilder { } private WorkflowRuntimeBuilder(Properties properties, Logger logger) { - this.managedChannel = NetworkUtils.buildGrpcManagedChannel(properties, WORKFLOW_INTERCEPTOR); + this.workflowApiTokenInterceptor = new ApiTokenClientInterceptor(properties); + this.managedChannel = NetworkUtils.buildGrpcManagedChannel(properties, workflowApiTokenInterceptor); this.builder = new DurableTaskGrpcWorkerBuilder().grpcChannel(this.managedChannel); this.logger = logger; } diff --git a/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainer.java b/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainer.java index dd008ed33..8d22f0b0b 100644 --- a/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainer.java +++ b/testcontainers-dapr/src/main/java/io/dapr/testcontainers/DaprContainer.java @@ -56,10 +56,10 @@ public class DaprContainer extends GenericContainer { private static final YamlConverter SUBSCRIPTION_CONVERTER = new SubscriptionYamlConverter(YAML_MAPPER); private static final YamlConverter HTTPENDPOINT_CONVERTER = new HttpEndpointYamlConverter(YAML_MAPPER); private static final YamlConverter CONFIGURATION_CONVERTER = new ConfigurationYamlConverter( - YAML_MAPPER); + YAML_MAPPER); private static final WaitStrategy WAIT_STRATEGY = Wait.forHttp("/v1.0/healthz/outbound") - .forPort(DAPRD_DEFAULT_HTTP_PORT) - .forStatusCodeMatching(statusCode -> statusCode >= 200 && statusCode <= 399); + .forPort(DAPRD_DEFAULT_HTTP_PORT) + .forStatusCodeMatching(statusCode -> statusCode >= 200 && statusCode <= 399); private final Set components = new HashSet<>(); private final Set subscriptions = new HashSet<>(); @@ -68,8 +68,8 @@ public class DaprContainer extends GenericContainer { private String appChannelAddress = "localhost"; private String placementService = "placement"; private String schedulerService = "scheduler"; - private String placementDockerImageName = DAPR_PLACEMENT_IMAGE_TAG; - private String schedulerDockerImageName = DAPR_SCHEDULER_IMAGE_TAG; + private DockerImageName placementDockerImageName = DockerImageName.parse(DAPR_PLACEMENT_IMAGE_TAG); + private DockerImageName schedulerDockerImageName = DockerImageName.parse(DAPR_SCHEDULER_IMAGE_TAG); private Configuration configuration; private DaprPlacementContainer placementContainer; @@ -82,6 +82,7 @@ public class DaprContainer extends GenericContainer { /** * Creates a new Dapr container. + * * @param dockerImageName Docker image name. */ public DaprContainer(DockerImageName dockerImageName) { @@ -94,6 +95,7 @@ public class DaprContainer extends GenericContainer { /** * Creates a new Dapr container. + * * @param image Docker image name. */ public DaprContainer(String image) { @@ -166,16 +168,26 @@ public class DaprContainer extends GenericContainer { return this; } - public DaprContainer withPlacementImage(String placementDockerImageName) { + public DaprContainer withPlacementImage(DockerImageName placementDockerImageName) { this.placementDockerImageName = placementDockerImageName; return this; } - public DaprContainer withSchedulerImage(String schedulerDockerImageName) { + public DaprContainer withPlacementImage(String placementDockerImageName) { + this.placementDockerImageName = DockerImageName.parse(placementDockerImageName); + return this; + } + + public DaprContainer withSchedulerImage(DockerImageName schedulerDockerImageName) { this.schedulerDockerImageName = schedulerDockerImageName; return this; } + public DaprContainer withSchedulerImage(String schedulerDockerImageName) { + this.schedulerDockerImageName = DockerImageName.parse(schedulerDockerImageName); + return this; + } + public DaprContainer withReusablePlacement(boolean shouldReusePlacement) { this.shouldReusePlacement = shouldReusePlacement; return this; @@ -203,6 +215,7 @@ public class DaprContainer extends GenericContainer { /** * Adds a Dapr component from a YAML file. + * * @param path Path to the YAML file. * @return This container. */ @@ -217,7 +230,7 @@ public class DaprContainer extends GenericContainer { Map spec = (Map) component.get("spec"); String version = (String) spec.get("version"); List> specMetadata = - (List>) spec.getOrDefault("metadata", Collections.emptyMap()); + (List>) spec.getOrDefault("metadata", Collections.emptyList()); ArrayList metadataEntries = new ArrayList<>(); @@ -260,17 +273,17 @@ public class DaprContainer extends GenericContainer { if (this.placementContainer == null) { this.placementContainer = new DaprPlacementContainer(this.placementDockerImageName) - .withNetwork(getNetwork()) - .withNetworkAliases(placementService) - .withReuse(this.shouldReusePlacement); + .withNetwork(getNetwork()) + .withNetworkAliases(placementService) + .withReuse(this.shouldReusePlacement); this.placementContainer.start(); } if (this.schedulerContainer == null) { this.schedulerContainer = new DaprSchedulerContainer(this.schedulerDockerImageName) - .withNetwork(getNetwork()) - .withNetworkAliases(schedulerService) - .withReuse(this.shouldReuseScheduler); + .withNetwork(getNetwork()) + .withNetworkAliases(schedulerService) + .withReuse(this.shouldReuseScheduler); this.schedulerContainer.start(); } @@ -386,6 +399,14 @@ public class DaprContainer extends GenericContainer { return DEFAULT_IMAGE_NAME; } + public DockerImageName getPlacementDockerImageName() { + return placementDockerImageName; + } + + public DockerImageName getSchedulerDockerImageName() { + return schedulerDockerImageName; + } + // Required by spotbugs plugin @Override public boolean equals(Object o) { diff --git a/testcontainers-dapr/src/test/java/io/dapr/testcontainers/DaprContainerTest.java b/testcontainers-dapr/src/test/java/io/dapr/testcontainers/DaprContainerTest.java new file mode 100644 index 000000000..680b1f4ee --- /dev/null +++ b/testcontainers-dapr/src/test/java/io/dapr/testcontainers/DaprContainerTest.java @@ -0,0 +1,46 @@ +package io.dapr.testcontainers; + +import org.junit.jupiter.api.Test; +import org.testcontainers.utility.DockerImageName; + +import static io.dapr.testcontainers.DaprContainerConstants.DAPR_RUNTIME_IMAGE_TAG; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DaprContainerTest { + + @Test + public void schedulerAndPlacementCustomImagesTest() { + + DaprContainer dapr = new DaprContainer(DAPR_RUNTIME_IMAGE_TAG) + .withAppName("dapr-app") + .withSchedulerImage(DockerImageName.parse("custom/scheduler:1.15.4") + .asCompatibleSubstituteFor("daprio/scheduler:1.15.4")) + .withPlacementImage(DockerImageName.parse("custom/placement:1.15.4") + .asCompatibleSubstituteFor("daprio/placement:1.15.4")) + .withAppPort(8081) + .withDaprLogLevel(DaprLogLevel.DEBUG) + .withAppChannelAddress("host.testcontainers.internal"); + + + assertEquals("custom/placement:1.15.4", dapr.getPlacementDockerImageName().asCanonicalNameString()); + assertEquals("custom/scheduler:1.15.4", dapr.getSchedulerDockerImageName().asCanonicalNameString()); + + } + + @Test + public void schedulerAndPlacementCustomImagesStringTest() { + + DaprContainer dapr = new DaprContainer(DAPR_RUNTIME_IMAGE_TAG) + .withAppName("dapr-app") + .withSchedulerImage("daprio/scheduler:1.15.4") + .withPlacementImage("daprio/placement:1.15.4") + .withAppPort(8081) + .withDaprLogLevel(DaprLogLevel.DEBUG) + .withAppChannelAddress("host.testcontainers.internal"); + + + assertEquals("daprio/placement:1.15.4", dapr.getPlacementDockerImageName().asCanonicalNameString()); + assertEquals("daprio/scheduler:1.15.4", dapr.getSchedulerDockerImageName().asCanonicalNameString()); + + } +}