From 12ebd6e43ab30071b9cb1691b8bd374d3433fadd Mon Sep 17 00:00:00 2001 From: K Siva Prasad Reddy Date: Wed, 8 Nov 2023 18:20:29 +0530 Subject: [PATCH] Update as per review suggestions --- step-1-getting-started.md | 14 +-- step-3-local-development-environment.md | 5 +- step-4-connect-to-services.md | 127 +----------------------- 3 files changed, 11 insertions(+), 135 deletions(-) diff --git a/step-1-getting-started.md b/step-1-getting-started.md index acb38c5..d67884c 100644 --- a/step-1-getting-started.md +++ b/step-1-getting-started.md @@ -7,15 +7,17 @@ Before getting started, let's make sure you have everything you need for this wo You'll need Java 17 or newer for this workshop. Testcontainers libraries are compatible with Java 8+, but this workshop uses a Spring Boot 3.x application which requires Java 17 or newer. -I would recommend using [SDKMAN](https://sdkman.io/) to install Java on your machine. +We would recommend using [SDKMAN](https://sdkman.io/) to install Java on your machine if you are using MacOS, Linux or Windows WSL. ### Install Docker +You need to have a Docker environment to use Testcontainers. -Make sure you have a Docker environment available on your machine. +* You can install any of **Docker Desktop**, **OrbStack**, etc. on your machine. +* You can use [Testcontainers Cloud](https://testcontainers.com/cloud). If you are going to use Testcontainers Cloud, then you need to install [Testcontainers Desktop](https://testcontainers.com/desktop/) app. +* If you are using MacOS, you can use Testcontainers Desktop Embedded Runtime. -* It can be [Testcontainers Cloud](https://testcontainers.com/cloud) recommended to avoid straining the conference network by pulling heavy Docker images. +* If you are using a local Docker, check by running: -* It can be a local Docker, which you can check by running: ```shell $ docker version @@ -40,7 +42,7 @@ Server: Docker Desktop 4.24.2 (124339) ``` ### Install Testcontainers Desktop -[Testcontainers Desktop](https://testcontainers.com/desktop/) is a companion app for the open source Testcontainers libraries +[Testcontainers Desktop](https://testcontainers.com/desktop/) is a companion app for the open-source Testcontainers libraries that makes local development and testing with real dependencies simple. Download the latest version of Testcontainers Desktop app from [https://testcontainers.com/desktop/](https://testcontainers.com/desktop/) @@ -66,7 +68,7 @@ With Maven: ``` ## \(optionally\) Pull the required images before doing the workshop - +If you are going to use a local Docker environment, you can pull the required images before the workshop to save time. This might be helpful if the internet connection at the workshop venue is somewhat slow. ```shell diff --git a/step-3-local-development-environment.md b/step-3-local-development-environment.md index 7b21dcb..97e6a39 100644 --- a/step-3-local-development-environment.md +++ b/step-3-local-development-environment.md @@ -86,7 +86,6 @@ Let's create `ContainersConfig` class under `src/test/java` to configure the req ```java package com.testcontainers.catalog; -import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SQS; import static org.testcontainers.utility.DockerImageName.parse; import com.testcontainers.catalog.domain.FileStorageService; @@ -121,7 +120,7 @@ public class ContainersConfig { registry.add("spring.cloud.aws.credentials.access-key", localStack::getAccessKey); registry.add("spring.cloud.aws.credentials.secret-key", localStack::getSecretKey); registry.add("spring.cloud.aws.region.static", localStack::getRegion); - registry.add("spring.cloud.aws.endpoint", () -> localStack.getEndpointOverride(SQS)); + registry.add("spring.cloud.aws.endpoint", localStack::getEndpoint); return localStack; } @@ -155,7 +154,7 @@ public class TestApplication { public static void main(String[] args) { SpringApplication - //note that we are using Application from src/main/java instead of TestApplication from src/test/java + //note that we are starting our actual Application from within our TestApplication .from(Application::main) .with(ContainersConfig.class) .run(args); diff --git a/step-4-connect-to-services.md b/step-4-connect-to-services.md index 3a0af53..9a3324a 100644 --- a/step-4-connect-to-services.md +++ b/step-4-connect-to-services.md @@ -38,132 +38,7 @@ with the following connection properties: psql -h localhost -p 5432 -U test -d test ``` -## Connect to Kafka -While you can use any of your existing tools to connect to these containerized services, -you can also run a helper container that will allow you to connect to the services. - -For example, you can start a **Kafka Control Center** container and connect to the Kafka instance via web browser. - -Let's update `KafkaContainer` configuration in `ContainersConfig` as follows: - -```java -package com.testcontainers.catalog; - -... -... -import static org.testcontainers.utility.DockerImageName.parse; - -import org.junit.runner.Description; -import org.junit.runners.model.Statement; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.DependsOn; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.testcontainers.DockerClientFactory; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.KafkaContainer; -import org.testcontainers.containers.Network; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.lifecycle.Startables; - -import java.time.Duration; -import java.time.temporal.ChronoUnit; -import java.util.List; - -@TestConfiguration(proxyBeanMethods = false) -public class ContainersConfig { - ... - ... - - @Bean - @ServiceConnection - KafkaContainer kafkaContainer() { - Network network = getNetwork(); - KafkaContainer kafka = new KafkaContainer(parse("confluentinc/cp-kafka:7.5.0")) - .withEnv("KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL", "http://schemaregistry:8085") - .withNetworkAliases("kafka") - .withNetwork(network); - - GenericContainer schemaRegistry = new GenericContainer<>("confluentinc/cp-schema-registry:7.5.0") - .withExposedPorts(8085) - .withNetworkAliases("schemaregistry").withNetwork(network) - .withEnv("SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS", "PLAINTEXT://kafka:9092") - .withEnv("SCHEMA_REGISTRY_LISTENERS", "http://0.0.0.0:8085") - .withEnv("SCHEMA_REGISTRY_HOST_NAME", "schemaregistry") - .withEnv("SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL", "PLAINTEXT") - .waitingFor(Wait.forHttp("/subjects")) - .withStartupTimeout(Duration.of(120, ChronoUnit.SECONDS)) - .dependsOn(kafka); - - GenericContainer controlCenter = - new GenericContainer<>("confluentinc/cp-enterprise-control-center:7.5.0") - .withExposedPorts(9021,9022) - .withNetwork(network) - .withEnv("CONTROL_CENTER_BOOTSTRAP_SERVERS", "BROKER://kafka:9092") - .withEnv("CONTROL_CENTER_REPLICATION_FACTOR", "1") - .withEnv("CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS", "1") - .withEnv("CONTROL_CENTER_SCHEMA_REGISTRY_SR1_URL", "http://schemaregistry:8085") - .withEnv("CONTROL_CENTER_SCHEMA_REGISTRY_URL", "http://schemaregistry:8085") - .dependsOn(kafka, schemaRegistry) - .waitingFor(Wait.forHttp("/clusters").forPort(9021).allowInsecure()) - .withStartupTimeout(Duration.of(120, ChronoUnit.SECONDS)) - .withLabel("com.testcontainers.desktop.service", "cp-control-center"); - Startables.deepStart(kafka, schemaRegistry, controlCenter).join(); - return kafka; - } - - private Network getNetwork() { - String networkId = "kafka"; - Network defaultNetwork = new Network() { - @Override - public String getId() { - return networkId; - } - - @Override - public void close() {} - - @Override - public Statement apply(Statement base, Description description) { - return null; - } - }; - - List - networks = DockerClientFactory.instance() - .client().listNetworksCmd().withNameFilter(networkId).exec(); - if (networks.isEmpty()) { - Network.builder().createNetworkCmdModifier(cmd -> cmd.withName(networkId)).build().getId(); - } - return defaultNetwork; - } -} -``` - -We are using the `confluentinc/cp-enterprise-control-center:7.5.0` image to start the Kafka Control Center container. -The Control Center is a web-based tool for managing and monitoring Apache Kafka clusters. -Let's map its port 9021 to the host's port 19021. - -Create `kafka-control-center.toml` file in the Testcontainers Desktop config directory with the following content: - -```toml -ports = [ - {local-port = 19021, container-port = 9021}, -] -selector.image-names = ["confluentinc/cp-enterprise-control-center"] -``` - -Now, if you restart the application, you should be able to connect to the Kafka Control Center at http://localhost:19021/. - -* Invoke the Product Image Upload API -* Go to the Kafka Control Center at http://localhost:19021/ -* Click on the **Cluster** tab -* Click on the **Topics** tab -* Click on the topic `product-image-updates` -* Click on the **Messages** tab - -You should be able to see the messages sent to Kafka. +Similarly, you can connect to any of your containers using the same approach by using the port-mapping feature of Testcontainers Desktop. ### [Next](step-5-use-reusable-containers.md)