diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchConnectionDetails.java index 33c499ebaa..eef66ee7cc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchConnectionDetails.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchConnectionDetails.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -21,6 +21,7 @@ import java.net.URISyntaxException; import java.util.List; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; +import org.springframework.boot.ssl.SslBundle; /** * Details required to establish a connection to an Elasticsearch service. @@ -63,6 +64,15 @@ public interface ElasticsearchConnectionDetails extends ConnectionDetails { return null; } + /** + * SSL bundle to use. + * @return the SSL bundle to use + * @since 3.5.0 + */ + default SslBundle getSslBundle() { + return null; + } + /** * An Elasticsearch node. * diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java index b18a14cb4d..79cd46cdb0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -44,12 +44,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails.Node; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails.Node.Protocol; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchProperties.Restclient.Ssl; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundles; import org.springframework.boot.ssl.SslOptions; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -75,8 +77,8 @@ class ElasticsearchRestClientConfigurations { @Bean @ConditionalOnMissingBean(ElasticsearchConnectionDetails.class) - PropertiesElasticsearchConnectionDetails elasticsearchConnectionDetails() { - return new PropertiesElasticsearchConnectionDetails(this.properties); + PropertiesElasticsearchConnectionDetails elasticsearchConnectionDetails(ObjectProvider sslBundles) { + return new PropertiesElasticsearchConnectionDetails(this.properties, sslBundles.getIfAvailable()); } @Bean @@ -87,16 +89,16 @@ class ElasticsearchRestClientConfigurations { @Bean RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchConnectionDetails connectionDetails, - ObjectProvider builderCustomizers, ObjectProvider sslBundles) { + ObjectProvider builderCustomizers) { RestClientBuilder builder = RestClient.builder(connectionDetails.getNodes() .stream() .map((node) -> new HttpHost(node.hostname(), node.port(), node.protocol().getScheme())) .toArray(HttpHost[]::new)); builder.setHttpClientConfigCallback((httpClientBuilder) -> { builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder)); - String sslBundleName = this.properties.getRestclient().getSsl().getBundle(); - if (StringUtils.hasText(sslBundleName)) { - configureSsl(httpClientBuilder, sslBundles.getObject().getBundle(sslBundleName)); + SslBundle sslBundle = connectionDetails.getSslBundle(); + if (sslBundle != null) { + configureSsl(httpClientBuilder, sslBundle); } return httpClientBuilder; }); @@ -236,8 +238,11 @@ class ElasticsearchRestClientConfigurations { private final ElasticsearchProperties properties; - PropertiesElasticsearchConnectionDetails(ElasticsearchProperties properties) { + private final SslBundles sslBundles; + + PropertiesElasticsearchConnectionDetails(ElasticsearchProperties properties, SslBundles sslBundles) { this.properties = properties; + this.sslBundles = sslBundles; } @Override @@ -260,6 +265,16 @@ class ElasticsearchRestClientConfigurations { return this.properties.getPathPrefix(); } + @Override + public SslBundle getSslBundle() { + Ssl ssl = this.properties.getRestclient().getSsl(); + if (StringUtils.hasLength(ssl.getBundle())) { + Assert.notNull(this.sslBundles, "SSL bundle name has been set but no SSL bundles found in context"); + return this.sslBundles.getBundle(ssl.getBundle()); + } + return null; + } + private Node createNode(String uri) { if (!(uri.startsWith("http://") || uri.startsWith("https://"))) { uri = "http://" + uri; diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java index eb2719a026..1f8d23c62e 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 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. @@ -16,15 +16,26 @@ package org.springframework.boot.testcontainers.service.connection.elasticsearch; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.util.List; import org.testcontainers.elasticsearch.ElasticsearchContainer; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails.Node.Protocol; +import org.springframework.boot.ssl.SslBundle; +import org.springframework.boot.ssl.SslStoreBundle; import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testcontainers.service.connection.Ssl; /** * {@link ContainerConnectionDetailsFactory} to create @@ -53,15 +64,83 @@ class ElasticsearchContainerConnectionDetailsFactory private static final class ElasticsearchContainerConnectionDetails extends ContainerConnectionDetails implements ElasticsearchConnectionDetails { + private volatile SslBundle sslBundle; + private ElasticsearchContainerConnectionDetails(ContainerConnectionSource source) { super(source); } + @Override + public String getUsername() { + return "elastic"; + } + + @Override + public String getPassword() { + return getContainer().getEnvMap().get("ELASTIC_PASSWORD"); + } + @Override public List getNodes() { String host = getContainer().getHost(); Integer port = getContainer().getMappedPort(DEFAULT_PORT); - return List.of(new Node(host, port, Protocol.HTTP, null, null)); + return List.of(new Node(host, port, (getSslBundle() != null) ? Protocol.HTTPS : Protocol.HTTP, + getUsername(), getPassword())); + } + + @Override + public SslBundle getSslBundle() { + if (this.sslBundle != null) { + return this.sslBundle; + } + SslBundle sslBundle = super.getSslBundle(); + if (sslBundle != null) { + this.sslBundle = sslBundle; + return sslBundle; + } + if (hasAnnotation(Ssl.class)) { + byte[] caCertificate = getContainer().caCertAsBytes().orElse(null); + if (caCertificate != null) { + KeyStore trustStore = createTrustStore(caCertificate); + sslBundle = createSslBundleWithTrustStore(trustStore); + this.sslBundle = sslBundle; + return sslBundle; + } + } + return null; + } + + private SslBundle createSslBundleWithTrustStore(KeyStore trustStore) { + return SslBundle.of(new SslStoreBundle() { + @Override + public KeyStore getKeyStore() { + return null; + } + + @Override + public String getKeyStorePassword() { + return null; + } + + @Override + public KeyStore getTrustStore() { + return trustStore; + } + }); + } + + private KeyStore createTrustStore(byte[] caCertificate) { + try { + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(null, null); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + Certificate certificate = certFactory.generateCertificate(new ByteArrayInputStream(caCertificate)); + keyStore.setCertificateEntry("ca", certificate); + return keyStore; + } + catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException ex) { + throw new IllegalStateException("Failed to create keystore from CA certificate", ex); + } } } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/build.gradle new file mode 100644 index 0000000000..d5650c243c --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/build.gradle @@ -0,0 +1,22 @@ +plugins { + id "java" + id "org.springframework.boot.conventions" + id "org.springframework.boot.docker-test" +} + +description = "Spring Boot Data ElasticSearch smoke test" + +dependencies { + dockerTestImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + dockerTestImplementation(project(":spring-boot-project:spring-boot-test")) + dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker")) + dockerTestImplementation(project(":spring-boot-project:spring-boot-testcontainers")) + dockerTestImplementation("org.junit.jupiter:junit-jupiter") + dockerTestImplementation("org.junit.platform:junit-platform-engine") + dockerTestImplementation("org.junit.platform:junit-platform-launcher") + dockerTestImplementation("org.testcontainers:junit-jupiter") + dockerTestImplementation("org.testcontainers:elasticsearch") + dockerTestImplementation("org.testcontainers:testcontainers") + + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-elasticsearch")) +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearch8ApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearch8ApplicationTests.java new file mode 100644 index 0000000000..2954b48799 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearch8ApplicationTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testcontainers.service.connection.Ssl; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Smoke tests for Elasticsearch 8. + * + * @author Moritz Halbritter + */ +@Testcontainers(disabledWithoutDocker = true) +@DataElasticsearchTest +class SampleElasticSearch8ApplicationTests { + + @Container + @ServiceConnection + @Ssl + static final ElasticsearchContainer elasticSearch = new ElasticsearchContainer(TestImage.ELASTICSEARCH_8.toString()) + .withPassword("my-custom-password"); + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Autowired + private SampleRepository exampleRepository; + + @Test + void testRepository() { + SampleDocument document = new SampleDocument(); + document.setText("Look, new @DataElasticsearchTest!"); + String id = UUID.randomUUID().toString(); + document.setId(id); + SampleDocument savedDocument = this.exampleRepository.save(document); + SampleDocument getDocument = this.elasticsearchTemplate.get(id, SampleDocument.class); + assertThat(getDocument).isNotNull(); + assertThat(getDocument.getId()).isNotNull(); + assertThat(getDocument.getId()).isEqualTo(savedDocument.getId()); + this.exampleRepository.deleteAll(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchApplicationTests.java new file mode 100644 index 0000000000..357a7fad24 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchApplicationTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Smoke tests for Elasticsearch. + * + * @author Moritz Halbritter + */ +@Testcontainers(disabledWithoutDocker = true) +@DataElasticsearchTest +class SampleElasticSearchApplicationTests { + + @Container + @ServiceConnection + static final ElasticsearchContainer elasticSearch = TestImage.container(ElasticsearchContainer.class); + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Autowired + private SampleRepository exampleRepository; + + @Test + void testRepository() { + SampleDocument document = new SampleDocument(); + document.setText("Look, new @DataElasticsearchTest!"); + String id = UUID.randomUUID().toString(); + document.setId(id); + SampleDocument savedDocument = this.exampleRepository.save(document); + SampleDocument getDocument = this.elasticsearchTemplate.get(id, SampleDocument.class); + assertThat(getDocument).isNotNull(); + assertThat(getDocument.getId()).isNotNull(); + assertThat(getDocument.getId()).isEqualTo(savedDocument.getId()); + this.exampleRepository.deleteAll(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchSslApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchSslApplicationTests.java new file mode 100644 index 0000000000..7b092a265d --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SampleElasticSearchSslApplicationTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest; +import org.springframework.boot.testcontainers.service.connection.PemTrustStore; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Smoke tests for Elasticsearch with SSL. + * + * @author Moritz Halbritter + */ +@Testcontainers(disabledWithoutDocker = true) +@DataElasticsearchTest( + properties = { "spring.elasticsearch.connection-timeout=120s", "spring.elasticsearch.socket-timeout=120s" }) +class SampleElasticSearchSslApplicationTests { + + @Container + @ServiceConnection + @PemTrustStore(certificate = "classpath:ssl.crt") + static final ElasticsearchContainer elasticSearch = TestImage.container(SecureElasticsearchContainer.class); + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Autowired + private SampleRepository exampleRepository; + + @Test + void testRepository() { + SampleDocument document = new SampleDocument(); + document.setText("Look, new @DataElasticsearchTest!"); + String id = UUID.randomUUID().toString(); + document.setId(id); + SampleDocument savedDocument = this.exampleRepository.save(document); + SampleDocument getDocument = this.elasticsearchTemplate.get(id, SampleDocument.class); + assertThat(getDocument).isNotNull(); + assertThat(getDocument.getId()).isNotNull(); + assertThat(getDocument.getId()).isEqualTo(savedDocument.getId()); + this.exampleRepository.deleteAll(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SecureElasticsearchContainer.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SecureElasticsearchContainer.java new file mode 100644 index 0000000000..a6f8420557 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/java/smoketest/data/elasticsearch/SecureElasticsearchContainer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import java.util.Map; + +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; + +/** + * A {@link ElasticsearchContainer} for Elasticsearch with SSL configuration. + * + * @author Moritz Halbritter + */ +class SecureElasticsearchContainer extends ElasticsearchContainer { + + SecureElasticsearchContainer(DockerImageName dockerImageName) { + super(dockerImageName); + } + + @Override + public void configure() { + // See + // https://www.elastic.co/guide/en/elastic-stack-get-started/7.5/get-started-docker.html#get-started-docker-tls + withEnv(Map.of("xpack.security.http.ssl.enabled", "true", "xpack.security.http.ssl.key", + "/usr/share/elasticsearch/config/ssl.key", "xpack.security.http.ssl.certificate", + "/usr/share/elasticsearch/config/ssl.crt", "xpack.security.transport.ssl.enabled", "true", + "xpack.security.transport.ssl.verification_mode", "certificate", "xpack.security.transport.ssl.key", + "/usr/share/elasticsearch/config/ssl.key", "xpack.security.transport.ssl.certificate", + "/usr/share/elasticsearch/config/ssl.crt")); + withCopyFileToContainer(MountableFile.forClasspathResource("/ssl.crt"), + "/usr/share/elasticsearch/config/ssl.crt"); + withCopyFileToContainer(MountableFile.forClasspathResource("/ssl.key"), + "/usr/share/elasticsearch/config/ssl.key"); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.crt b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.crt new file mode 100644 index 0000000000..a45ed17cf7 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICpjCCAY6gAwIBAgIUd1pIGeth3t+uXRwJqQgBkX6RqVwwDQYJKoZIhvcNAQEL +BQAwDDEKMAgGA1UEAwwBKjAgFw0yNDA4MjMwOTI5MjBaGA8yMTI0MDgyMzA5Mjky +MFowDDEKMAgGA1UEAwwBKjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMvuy3afu6umnCgEBElfgboa2M1O7RWwuvA0OIWdEzxYYQmc9QUihd2l68pIu9jT +hR+2CENL4iY2HNtELJ8kFSGgUGPGrsjLj/qqULG1/r2f18tPavMD7Hxo0AGA+yyX +nECCfHGPJ7P88fWwoMfdp8Y4s/BW7QcC7vB9kQGjUOb4V/WUWI7c27Yxj6/nCPRr +Gkb5YkEvsw6TPeBfZbx7kjWaYtd8eKjVHf40lu0AhXGK+lFuaLrY9VYBYoiMRtIZ +3/EKf2gKQiIIR7tN3DUa5zi6vYvQNaUaK14yomfyynUzGPbIcMq8V+c6j3gI7jqf +ITqaaBn5NIM0W7ox6hhr+UUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEApgal5rth +5y94hnwgNt0/+PuVj5vwxUIi0WgV6b1GE+3033h+l57hKcIRem4l3xEQnAs3NyLK +BnbBgnnUfSOgPZhiP8s3VHSvGeJda7z2IQhCBe+cUnx6UHs8wgN4Nh1rkbEUzBvZ +xm98B/bcbTsiSnIRTHBvIYhySDuCmyYOZwH8HC6rct6U3PODmJ6OjtWC43kjO0jT +4/T/1PBJnVnN0r1Xu/P+GNDgDnzifIYr5ofY0zGsOC1GhRWyqbiIfe5hgZ//q81U +1tFbSlLNvoi3C4jf2Fj9lYo8Ylkxk7QE5dFbRmBDffCo2sD8g6wyZN3PhaIyckG5 +E0uZHTBFFpFKjQ== +-----END CERTIFICATE----- diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.key b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.key new file mode 100644 index 0000000000..e56802c64a --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/dockerTest/resources/ssl.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDL7st2n7urppwo +BARJX4G6GtjNTu0VsLrwNDiFnRM8WGEJnPUFIoXdpevKSLvY04UftghDS+ImNhzb +RCyfJBUhoFBjxq7Iy4/6qlCxtf69n9fLT2rzA+x8aNABgPssl5xAgnxxjyez/PH1 +sKDH3afGOLPwVu0HAu7wfZEBo1Dm+Ff1lFiO3Nu2MY+v5wj0axpG+WJBL7MOkz3g +X2W8e5I1mmLXfHio1R3+NJbtAIVxivpRbmi62PVWAWKIjEbSGd/xCn9oCkIiCEe7 +Tdw1Guc4ur2L0DWlGiteMqJn8sp1Mxj2yHDKvFfnOo94CO46nyE6mmgZ+TSDNFu6 +MeoYa/lFAgMBAAECggEAHdNp/Ip2Fy/B7PRRcC3AumhMxxJBCIgVfyYUEi6b7pp6 +br5+82ZOL9Ghf69NkfO1p6Km6LjDdZU6eTMqV4gecxGQUFdxnrpu71lTffpBLJih +JgISgUJUpwlpSp8DnUz7NFAhRTaLtv5KoQVZLoITlKEcaA0+k2Txb0jeGWA6Z90t +ocHJb9MTeWU7SSaVttNshoJPj272CXExuOCSi+NziSiuCnZbKSZDQKDEe9+jMVhL +OqvXYyp+FWoL60DuLb2BgKet5UcsVaYZNfETRY7vn5LThFpRJnOpZ6Um8JydP60+ +3gtuKpsZ8kVKcif4cawAfzpGobra9BBFOc6IqbZMrQKBgQDmVkd1LHdLGOOAd5C+ +pwHqxftsh1qyJQ2PAQn6VwAPGkl6c9P/hC3eS6gWMXAf++QlqNUrQR8SvPXlOcXH +LirqVLd/+gLAD4aRhGTKPjBK07NryGvMQO2pRCPd1n5xnd4Xpp9gt10JJlwZUaIY +dItvGcV+5TXUMqnEl+GaNKs35wKBgQDip2iUZCwpG1mGn4Pbvs+hLTZQD3+oXPMh +NYpe9vaStv5YxkFBXM9M+XWH2MDKSMTBZxuTV8GY4pipQwBB32UOtlVVWhOJh1go +Qh7NQOt8yPWb+ynu/i30THfgYMARrqRXXB4o/l9R0J7gW3yjyQDBSuBz5xUIQlpt +adhg+fmv8wKBgQDjZv75YcMMsy+4H1MZxswPuxK0XRVfl1FBg+cT7lyyjGNKr5v3 +Qcn/E3aJIpnuGcNuoraCE7LXzxJ9EoJ+WMgpvSXFBVE9yJY0iB7xxF/tIACdQqua +Zee9GvbGBwOirBceBnSHCcCiTerTXFLKDhWyxCDFXQm9y57r5n7mvWTktQKBgQCW +sJ7DKeaCXgCjlKJiEvaQPjMB/4vsMAAlcCdTA/bjjG6GLylrf30DvEb7zow+8Sp/ +O0IGMC4yq1S8FCOzqAbURT1uxbh/k1B1U6CO7j6idCl3TwGON8ftyHla4HhSST5S +JpiWwKg3CPDYUXsImba6zEF2TYiaOSNN4zVNJGVxKQKBgB2aOa93jTHxx4BWCqz1 +q8EWxbSItNHoTLfe4PgRhu3Ow2I2zi+XAfpW5XIrkNfQ09iDeZLsovaZ35fRcwMB +LWwDlujb5OkJZ4eLgYQqHEwJaYsoR5O6OfpW4IW79t1pzYbGkR0hqY5bcGcI/Tm5 +ZZg8ZonNdwagmoihBFAZ+wpB +-----END PRIVATE KEY----- diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleDocument.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleDocument.java new file mode 100644 index 0000000000..d48e3f2658 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleDocument.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; + +/** + * Sample document. + * + * @author Moritz Halbritter + */ +@Document(indexName = "examples") +public class SampleDocument { + + @Id + private String id; + + private String text; + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + + @Override + public String toString() { + return "SampleDocument{" + "id='" + this.id + '\'' + ", text='" + this.text + '\'' + '}'; + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleElasticsearchApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleElasticsearchApplication.java new file mode 100644 index 0000000000..77c462203c --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleElasticsearchApplication.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import java.util.UUID; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * Sample application. + * + * @author Moritz Halbritter + */ +@SpringBootApplication +public class SampleElasticsearchApplication { + + public static void main(String[] args) { + ConfigurableApplicationContext context = SpringApplication.run(SampleElasticsearchApplication.class, args); + SampleRepository repository = context.getBean(SampleRepository.class); + createDocument(repository); + listDocuments(repository); + repository.deleteAll(); + context.close(); + } + + private static void listDocuments(SampleRepository repository) { + System.out.println("Documents:"); + for (SampleDocument foundDocument : repository.findAll()) { + System.out.println(" " + foundDocument); + } + } + + private static void createDocument(SampleRepository repository) { + SampleDocument document = new SampleDocument(); + document.setText("Look, new @DataElasticsearchTest!"); + String id = UUID.randomUUID().toString(); + document.setId(id); + SampleDocument savedDocument = repository.save(document); + System.out.println("Saved document " + savedDocument); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleRepository.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleRepository.java new file mode 100644 index 0000000000..22a45b29d3 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-elasticsearch/src/main/java/smoketest/data/elasticsearch/SampleRepository.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2025 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 smoketest.data.elasticsearch; + +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * Sample repository. + * + * @author Moritz Halbritter + */ +interface SampleRepository extends ElasticsearchRepository { + +}