From 43b42eca49bb00286d9d0a0a1c48cc2f31c850d0 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Tue, 25 Apr 2023 16:06:34 -0500 Subject: [PATCH] Add Docker Compose service connection support for Cassandra Closes gh-35136 --- ...DockerComposeConnectionDetailsFactory.java | 76 +++++++++++++++++++ .../cassandra/CassandraEnvironment.java | 38 ++++++++++ .../connection/cassandra/package-info.java | 20 +++++ .../main/resources/META-INF/spring.factories | 1 + ...nectionDetailsFactoryIntegrationTests.java | 53 +++++++++++++ .../cassandra/CassandraEnvironmentTests.java | 45 +++++++++++ .../cassandra/cassandra-compose.yaml | 7 ++ .../asciidoc/features/docker-compose.adoc | 3 + 8 files changed, 243 insertions(+) create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactory.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironment.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/package-info.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactoryIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironmentTests.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/cassandra/cassandra-compose.yaml diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactory.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactory.java new file mode 100644 index 00000000000..aa5d86d8b89 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactory.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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 org.springframework.boot.docker.compose.service.connection.cassandra; + +import java.util.List; + +import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails; +import org.springframework.boot.docker.compose.core.RunningService; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; + +/** + * {@link DockerComposeConnectionDetailsFactory} to create + * {@link CassandraConnectionDetails} for a {@code Cassandra} service. + * + * @author Scott Frederick + */ +class CassandraDockerComposeConnectionDetailsFactory + extends DockerComposeConnectionDetailsFactory { + + private static final int CASSANDRA_PORT = 9042; + + CassandraDockerComposeConnectionDetailsFactory() { + super("cassandra"); + } + + @Override + protected CassandraConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) { + return new CassandraDockerComposeConnectionDetails(source.getRunningService()); + } + + /** + * {@link CassandraConnectionDetails} backed by a {@code Cassandra} + * {@link RunningService}. + */ + static class CassandraDockerComposeConnectionDetails extends DockerComposeConnectionDetails + implements CassandraConnectionDetails { + + private final List contactPoints; + + private final String datacenter; + + CassandraDockerComposeConnectionDetails(RunningService service) { + super(service); + CassandraEnvironment cassandraEnvironment = new CassandraEnvironment(service.env()); + this.contactPoints = List.of(new Node(service.host(), service.ports().get(CASSANDRA_PORT))); + this.datacenter = cassandraEnvironment.getDatacenter(); + } + + @Override + public List getContactPoints() { + return this.contactPoints; + } + + @Override + public String getLocalDatacenter() { + return this.datacenter; + } + + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironment.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironment.java new file mode 100644 index 00000000000..84ed5f97044 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironment.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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 org.springframework.boot.docker.compose.service.connection.cassandra; + +import java.util.Map; + +/** + * Cassandra environment details. + * + * @author Scott Frederick + */ +class CassandraEnvironment { + + private final String datacenter; + + CassandraEnvironment(Map env) { + this.datacenter = env.getOrDefault("CASSANDRA_DC", "datacenter1"); + } + + String getDatacenter() { + return this.datacenter; + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/package-info.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/package-info.java new file mode 100644 index 00000000000..86d5788526e --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/cassandra/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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. + */ + +/** + * Auto-configuration for docker compose Cassandra service connections. + */ +package org.springframework.boot.docker.compose.service.connection.cassandra; diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories index c0ca1bb615c..d3b47a99a75 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories @@ -5,6 +5,7 @@ org.springframework.boot.docker.compose.service.connection.DockerComposeServiceC # Connection Detail Factories org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ +org.springframework.boot.docker.compose.service.connection.cassandra.CassandraDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.elasticsearch.ElasticsearchDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.mariadb.MariaDbJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.mariadb.MariaDbR2dbcDockerComposeConnectionDetailsFactory,\ diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..c4cf1c637b2 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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 org.springframework.boot.docker.compose.service.connection.cassandra; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails; +import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails.Node; +import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration test for {@link CassandraDockerComposeConnectionDetailsFactory}. + * + * @author Scott Frederick + */ +class CassandraDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests { + + CassandraDockerComposeConnectionDetailsFactoryIntegrationTests() { + super("cassandra-compose.yaml"); + } + + @Test + void runCreatesConnectionDetails() { + CassandraConnectionDetails connectionDetails = run(CassandraConnectionDetails.class); + List contactPoints = connectionDetails.getContactPoints(); + assertThat(contactPoints.size()).isEqualTo(1); + Node node = contactPoints.get(0); + assertThat(node.host()).isNotNull(); + assertThat(node.port()).isGreaterThan(0); + assertThat(connectionDetails.getUsername()).isNull(); + assertThat(connectionDetails.getPassword()).isNull(); + assertThat(connectionDetails.getLocalDatacenter()).isEqualTo("dc1"); + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironmentTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironmentTests.java new file mode 100644 index 00000000000..9344df66548 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/cassandra/CassandraEnvironmentTests.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://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 org.springframework.boot.docker.compose.service.connection.cassandra; + +import java.util.Collections; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CassandraEnvironment}. + * + * @author Scott Frederick + */ +class CassandraEnvironmentTests { + + @Test + void getDatacenterWhenDatacenterIsNotSet() { + CassandraEnvironment environment = new CassandraEnvironment(Collections.emptyMap()); + assertThat(environment.getDatacenter()).isEqualTo("datacenter1"); + } + + @Test + void getDatacenterWhenDatacenterIsSet() { + CassandraEnvironment environment = new CassandraEnvironment(Map.of("CASSANDRA_DC", "dc1")); + assertThat(environment.getDatacenter()).isEqualTo("dc1"); + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/cassandra/cassandra-compose.yaml b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/cassandra/cassandra-compose.yaml new file mode 100644 index 00000000000..b1d466ebdce --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/cassandra/cassandra-compose.yaml @@ -0,0 +1,7 @@ +services: + cassandra: + image: 'cassandra:3.11.10' + ports: + - '9042' + environment: + - 'CASSANDRA_DC=dc1' diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc index 82d07177454..314f152b2ee 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc @@ -37,6 +37,9 @@ The following service connections are currently supported: |=== | Connection Details | Matched on +| `CassandraConnectionDetails` +| Containers named "cassandra" + | `ElasticsearchConnectionDetails` | Containers named "elasticsearch"