├── spring-cloud-bindings-tests ├── src │ └── test │ │ ├── resources │ │ └── bindings │ │ │ └── redis │ │ │ ├── port │ │ │ ├── type │ │ │ └── host │ │ └── java │ │ └── org │ │ └── springframework │ │ └── cloud │ │ ├── SpringBoot3Application.java │ │ ├── IntegrationTest.java │ │ └── RedisServerTestConfiguration.java ├── README.md └── pom.xml ├── spring-cloud-bindings └── src │ ├── test │ ├── resources │ │ ├── k8s │ │ │ ├── test-k8s │ │ │ │ ├── type │ │ │ │ ├── .hidden-data │ │ │ │ ├── provider │ │ │ │ ├── .hidden-data-1 │ │ │ │ │ ├── type │ │ │ │ │ ├── provider │ │ │ │ │ └── test-secret-key │ │ │ │ └── test-secret-key │ │ │ ├── test-name-1 │ │ │ │ ├── type │ │ │ │ ├── provider │ │ │ │ └── test-secret-key │ │ │ └── test-name-2 │ │ │ │ ├── type │ │ │ │ ├── provider │ │ │ │ └── test-secret-key │ │ ├── pem │ │ │ ├── test-banner.txt │ │ │ ├── test-ec-key.pem │ │ │ ├── test-cert.pem │ │ │ ├── test-key.pem │ │ │ └── test-cert-chain.pem │ │ └── cnb │ │ │ ├── test-k8s │ │ │ ├── metadata │ │ │ │ ├── kind │ │ │ │ ├── .hidden-data │ │ │ │ ├── provider │ │ │ │ ├── .hidden-data-1 │ │ │ │ │ ├── kind │ │ │ │ │ ├── provider │ │ │ │ │ └── test-metadata-key │ │ │ │ └── test-metadata-key │ │ │ └── secret │ │ │ │ ├── .hidden-data │ │ │ │ ├── test-secret-key │ │ │ │ └── .hidden-data-1 │ │ │ │ └── test-secret-key │ │ │ ├── test-name-1 │ │ │ ├── metadata │ │ │ │ ├── kind │ │ │ │ ├── provider │ │ │ │ └── test-metadata-key │ │ │ └── secret │ │ │ │ └── test-secret-key │ │ │ └── test-name-2 │ │ │ ├── metadata │ │ │ ├── kind │ │ │ ├── provider │ │ │ └── test-metadata-key │ │ │ └── secret │ │ │ └── test-secret-key │ └── java │ │ └── org │ │ └── springframework │ │ └── cloud │ │ └── bindings │ │ ├── boot │ │ ├── TestHelper.java │ │ ├── pem │ │ │ ├── PemCertificateParserTests.java │ │ │ ├── PemPrivateKeyParserTests.java │ │ │ ├── PemSslStoreHelperTests.java │ │ │ └── PemContentTests.java │ │ ├── PropertySourceContributorTest.java │ │ ├── WavefrontBindingsPropertiesProcessorTest.java │ │ ├── Neo4JBindingsPropertiesProcessorTest.java │ │ ├── ElasticsearchBindingsPropertiesProcessorTest.java │ │ ├── LDAPBindingsPropertiesProcessorTest.java │ │ ├── ArtemisBindingsPropertiesProcessorTest.java │ │ ├── CouchbaseBindingsPropertiesProcessorTest.java │ │ ├── GuardsTest.java │ │ ├── KafkaBindingsPropertiesProcessorTest.java │ │ ├── RabbitMqBindingsPropertiesProcessorTest.java │ │ ├── MongoDbBindingsPropertiesProcessorTest.java │ │ ├── BindingFlattenedEnvironmentPostProcessorTest.java │ │ ├── RedisBindingsPropertiesProcessorTest.java │ │ ├── CassandraBindingsPropertiesProcessorTest.java │ │ ├── BindingSpecificEnvironmentPostProcessorTest.java │ │ ├── Db2BindingsPropertiesProcessorTest.java │ │ ├── MySqlBindingsPropertiesProcessorTest.java │ │ ├── OracleBindingsPropertiesProcessorTest.java │ │ ├── SapHanaBindingsPropertiesProcessorTest.java │ │ └── SqlServerBindingsPropertiesProcessorTest.java │ │ ├── FluentMap.java │ │ └── BindingTest.java │ └── main │ ├── java │ └── org │ │ └── springframework │ │ └── cloud │ │ └── bindings │ │ ├── boot │ │ ├── package-info.java │ │ ├── pem │ │ │ ├── package-info.java │ │ │ ├── PemContent.java │ │ │ ├── PemCertificateParser.java │ │ │ └── PemSslStoreHelper.java │ │ ├── Guards.java │ │ ├── BindingsPropertiesProcessor.java │ │ ├── PropertySourceContributor.java │ │ ├── WavefrontBindingsPropertiesProcessor.java │ │ ├── Neo4JBindingsPropertiesProcessor.java │ │ ├── ElasticsearchBindingsPropertiesProcessor.java │ │ ├── LDAPBindingsPropertiesProcessor.java │ │ ├── CouchbaseBindingsPropertiesProcessor.java │ │ ├── KafkaBindingsPropertiesProcessor.java │ │ ├── RabbitMqBindingsPropertiesProcessor.java │ │ ├── MongoDbBindingsPropertiesProcessor.java │ │ ├── RedisBindingsPropertiesProcessor.java │ │ ├── SapHanaBindingsPropertiesProcessor.java │ │ ├── CassandraBindingsPropertiesProcessor.java │ │ ├── OracleBindingsPropertiesProcessor.java │ │ ├── Db2BindingsPropertiesProcessor.java │ │ ├── SqlServerBindingsPropertiesProcessor.java │ │ ├── ArtemisBindingsPropertiesProcessor.java │ │ ├── BindingFlattenedEnvironmentPostProcessor.java │ │ ├── ConfigServerBindingsPropertiesProcessor.java │ │ ├── MapMapper.java │ │ ├── MySqlBindingsPropertiesProcessor.java │ │ ├── BindingSpecificEnvironmentPostProcessor.java │ │ └── SpringSecurityOAuth2BindingsPropertiesProcessor.java │ │ └── package-info.java │ └── resources │ └── META-INF │ └── spring.factories ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── scripts ├── Dockerfile ├── test.sh ├── promote-to-maven-central.sh ├── test.yml ├── deploy.yml ├── bump-major.yml ├── bump-minor.yml ├── bump-patch.yml ├── release-version.yml ├── release-version.sh ├── deploy.sh └── bump-version.sh ├── .gitignore └── pom.xml /spring-cloud-bindings-tests/src/test/resources/bindings/redis/port: -------------------------------------------------------------------------------- 1 | 4343 -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/src/test/resources/bindings/redis/type: -------------------------------------------------------------------------------- 1 | redis -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/src/test/resources/bindings/redis/host: -------------------------------------------------------------------------------- 1 | localhost -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/type: -------------------------------------------------------------------------------- 1 | .hidden-data/type -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-1/type: -------------------------------------------------------------------------------- 1 | test-type-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-2/type: -------------------------------------------------------------------------------- 1 | test-type-2 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/pem/test-banner.txt: -------------------------------------------------------------------------------- 1 | Running a Test! -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/.hidden-data: -------------------------------------------------------------------------------- 1 | .hidden-data-1 -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/provider: -------------------------------------------------------------------------------- 1 | .hidden-data/provider -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/kind: -------------------------------------------------------------------------------- 1 | .hidden-data/kind -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/secret/.hidden-data: -------------------------------------------------------------------------------- 1 | .hidden-data-1 -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-1/metadata/kind: -------------------------------------------------------------------------------- 1 | test-kind-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-2/metadata/kind: -------------------------------------------------------------------------------- 1 | test-kind-2 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-1/provider: -------------------------------------------------------------------------------- 1 | test-provider-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-2/provider: -------------------------------------------------------------------------------- 1 | test-provider-2 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/.hidden-data: -------------------------------------------------------------------------------- 1 | .hidden-data-1 -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/provider: -------------------------------------------------------------------------------- 1 | .hidden-data/provider -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/.hidden-data-1/type: -------------------------------------------------------------------------------- 1 | test-type-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/.hidden-data-1/kind: -------------------------------------------------------------------------------- 1 | test-kind-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-1/metadata/provider: -------------------------------------------------------------------------------- 1 | test-provider-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-2/metadata/provider: -------------------------------------------------------------------------------- 1 | test-provider-2 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/.hidden-data-1/provider: -------------------------------------------------------------------------------- 1 | test-provider-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/test-secret-key: -------------------------------------------------------------------------------- 1 | .hidden-data/test-secret-key -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-1/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-name-2/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-1/secret/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-2/secret/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/.hidden-data-1/provider: -------------------------------------------------------------------------------- 1 | test-provider-1 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/secret/test-secret-key: -------------------------------------------------------------------------------- 1 | .hidden-data/test-secret-key -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-1/metadata/test-metadata-key: -------------------------------------------------------------------------------- 1 | test-metadata-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-name-2/metadata/test-metadata-key: -------------------------------------------------------------------------------- 1 | test-metadata-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/k8s/test-k8s/.hidden-data-1/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/test-metadata-key: -------------------------------------------------------------------------------- 1 | .hidden-data/test-metadata-key -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/secret/.hidden-data-1/test-secret-key: -------------------------------------------------------------------------------- 1 | test-secret-value 2 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/cnb/test-k8s/metadata/.hidden-data-1/test-metadata-key: -------------------------------------------------------------------------------- 1 | test-metadata-value 2 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-bindings/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG base_image=ubuntu:bionic 2 | FROM ${base_image} 3 | 4 | RUN apt-get update && apt-get install --no-install-recommends -y \ 5 | git gnupg \ 6 | && rm -rf /var/lib/apt/lists/* 7 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | [[ -d "${PWD}"/maven && ! -d "${HOME}"/.m2 ]] && ln -s "${PWD}"/maven "${HOME}"/.m2 6 | 7 | cd source 8 | 9 | ./mvnw test 10 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /scripts/promote-to-maven-central.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | export BUILD_INFO_LOCATION=$(pwd)/repository/build-info.json 6 | 7 | java -jar /concourse-release-scripts.jar publishToCentral 'RELEASE' "$BUILD_INFO_LOCATION" repository 8 | 9 | echo "Sync complete" -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/src/test/java/org/springframework/cloud/SpringBoot3Application.java: -------------------------------------------------------------------------------- 1 | package org.springframework.cloud; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | 5 | @SpringBootApplication 6 | public class SpringBoot3Application { 7 | } 8 | -------------------------------------------------------------------------------- /scripts/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | run: 16 | path: source/scripts/test.sh 17 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/pem/test-ec-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIBEZhSR+d8kwL5L/K0f/eNBm4RfzyyA1jfg+dV1/8WvqoAoGCCqGSM49 3 | AwEHoUQDQgAEBbfdBTSUWuui7O2R+W9mDPjAHjgdBJsjrjnvkjnq8f/k4U/OqvjK 4 | qnHEZwYgdaF2WqYdqBYMns0n+tSMgBoonQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /scripts/deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | outputs: 16 | - name: repository 17 | 18 | run: 19 | path: source/scripts/deploy.sh 20 | -------------------------------------------------------------------------------- /scripts/bump-major.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | outputs: 16 | - name: source 17 | 18 | run: 19 | path: source/scripts/bump-version.sh 20 | args: 21 | - major 22 | -------------------------------------------------------------------------------- /scripts/bump-minor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | outputs: 16 | - name: source 17 | 18 | run: 19 | path: source/scripts/bump-version.sh 20 | args: 21 | - minor 22 | -------------------------------------------------------------------------------- /scripts/bump-patch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | outputs: 16 | - name: source 17 | 18 | run: 19 | path: source/scripts/bump-version.sh 20 | args: 21 | - patch 22 | -------------------------------------------------------------------------------- /scripts/release-version.yml: -------------------------------------------------------------------------------- 1 | --- 2 | platform: linux 3 | 4 | image_resource: 5 | type: registry-image 6 | source: 7 | repository: cfje/spring-cloud-bindings 8 | 9 | inputs: 10 | - name: source 11 | 12 | caches: 13 | - path: maven 14 | 15 | outputs: 16 | - name: source 17 | - name: version 18 | 19 | run: 20 | path: source/scripts/release-version.sh 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/TestHelper.java: -------------------------------------------------------------------------------- 1 | package org.springframework.cloud.bindings.boot; 2 | 3 | import org.springframework.core.io.ClassPathResource; 4 | import org.springframework.util.FileCopyUtils; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.io.Reader; 9 | import java.nio.charset.StandardCharsets; 10 | 11 | public class TestHelper { 12 | public static String resourceAsString(ClassPathResource resource) throws IOException { 13 | Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8); 14 | return FileCopyUtils.copyToString(reader); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /scripts/release-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | [[ -d "${PWD}"/maven && ! -d "${HOME}"/.m2 ]] && ln -s "${PWD}"/maven "${HOME}"/.m2 6 | 7 | cd source 8 | 9 | ./mvnw versions:set -DremoveSnapshot=true -DgenerateBackupPoms=false 10 | VERSION=$(./mvnw --quiet help:evaluate -DforceStdout -Dexpression=project.version) 11 | 12 | git add pom.xml 13 | git add spring-cloud-bindings/pom.xml 14 | git add spring-cloud-bindings-tests/pom.xml 15 | 16 | git checkout -- . 17 | 18 | git \ 19 | -c user.name='Paketo Robot' \ 20 | -c user.email='robot@paketo.io' \ 21 | commit \ 22 | --signoff \ 23 | --message "v${VERSION} Release" 24 | 25 | echo -n "${VERSION}" > ../version/version 26 | -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/src/test/java/org/springframework/cloud/IntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.cloud; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.data.redis.core.RedisTemplate; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertTrue; 9 | 10 | @SpringBootTest(classes = RedisServerTestConfiguration.class) 11 | public class IntegrationTest { 12 | 13 | @Autowired 14 | private RedisTemplate redisTemplate; 15 | 16 | @Test 17 | public void shouldSaveUser_toRedis() { 18 | redisTemplate.opsForValue().set("hello", "world"); 19 | assertTrue(redisTemplate.hasKey("hello")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @NonNullApi 18 | package org.springframework.cloud.bindings.boot; 19 | 20 | import org.springframework.lang.NonNullApi; 21 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** */ @NonNullApi 18 | package org.springframework.cloud.bindings; 19 | 20 | import org.springframework.lang.NonNullApi; 21 | -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/README.md: -------------------------------------------------------------------------------- 1 | # Spring Cloud Bindings Test Boot 3 2 | 3 | ## Purpose of this module 4 | 5 | For several Spring Cloud Bindings integrations, the properties bindings need to be different between Spring Boot 2 and Spring Boot 3. 6 | 7 | In a Spring Boot 3 application, the mapping needs to be different because of changes with Spring Data Redis: 8 | 9 | | Property | Value | 10 | |--------------------------|----------| 11 | | `spring.data.redis.port` | `{port}` | 12 | | `spring.data.redis.host` | `{host}` | 13 | 14 | This module runs an application, based on Spring Boot 3, and checks whether the `RedisConnectionFactory` properly picked up the `spring.data.redis.port` and `spring.data.redis.host` values. 15 | 16 | Pay attention to the 2 environment variables set in the `pom.xml` that set `SERVICE_BINDING_ROOT` - they allow Spring Boot Bindings to load the proper configuration in `bindings/redis` -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/FluentMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings; 18 | 19 | import java.util.HashMap; 20 | 21 | public final class FluentMap extends HashMap { 22 | 23 | public FluentMap withEntry(String key, String value) { 24 | put(key, value); 25 | return this; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/pem/test-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICpDCCAYwCCQCDOqHKPjAhCTANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls 3 | b2NhbGhvc3QwHhcNMTQwOTEwMjE0MzA1WhcNMTQxMDEwMjE0MzA1WjAUMRIwEAYD 4 | VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR 5 | 0KfxUw7MF/8RB5/YXOM7yLnoHYb/M/6dyoulMbtEdKKhQhU28o5FiDkHcEG9PJQL 6 | gqrRgAjl3VmCC9omtfZJQ2EpfkTttkJjnKOOroXhYE51/CYSckapBYCVh8GkjUEJ 7 | uEfnp07cTfYZFqViIgIWPZyjkzl3w4girS7kCuzNdDntVJVx5F/EsFwMA8n3C0Qa 8 | zHQoM5s00Fer6aTwd6AW0JD5QkADavpfzZ554e4HrVGwHlM28WKQQkFzzGu44FFX 9 | yVuEF3HeyVPug8GRHAc8UU7ijVgJB5TmbvRGYowIErD5i4VvGLuOv9mgR3aVyN0S 10 | dJ1N7aJnXpeSQjAgf03jAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAE4yvwhbPldg 11 | Bpl7sBw/m2B3bfiNeSqa4tII1PQ7ysgWVb9HbFNKkriScwDWlqo6ljZfJ+SDFCoj 12 | bQz4fOFdMAOzRnpTrG2NAKMoJLY0/g/p7XO00PiC8T3h3BOJ5SHuW3gUyfGXmAYs 13 | DnJxJOrwPzj57xvNXjNSbDOJ3DRfCbB0CWBexOeGDiUokoEq3Gnz04Q4ZfHyAcpZ 14 | 3deMw8Od5p9WAoCh3oClpFyOSzXYKZd+3ppMMtfc4wnbfocnfSFxj0UCpOEJw4Ez 15 | +lGuHKdhNOVW9CmqPD1y76o6c8PQKuF7KZEoY2jvy3GeIfddBvqXgZ4PbWvFz1jO 16 | 32C9XWHwRA4= 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/src/test/java/org/springframework/cloud/RedisServerTestConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.springframework.cloud; 2 | 3 | import org.springframework.boot.test.context.TestConfiguration; 4 | import org.springframework.core.io.ClassPathResource; 5 | import redis.embedded.RedisServer; 6 | 7 | import javax.annotation.PostConstruct; 8 | import javax.annotation.PreDestroy; 9 | import java.io.IOException; 10 | import java.util.Scanner; 11 | 12 | @TestConfiguration 13 | public class RedisServerTestConfiguration { 14 | 15 | private final RedisServer redisServer; 16 | 17 | public RedisServerTestConfiguration() throws IOException { 18 | try (Scanner scanner = new Scanner(new ClassPathResource("bindings/redis/port").getInputStream())) { 19 | int port = scanner.nextInt(); 20 | this.redisServer = new RedisServer(port); 21 | } 22 | } 23 | 24 | @PostConstruct 25 | public void postConstruct() { 26 | redisServer.start(); 27 | } 28 | 29 | @PreDestroy 30 | public void preDestroy() { 31 | redisServer.stop(); 32 | } 33 | } -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | [[ -d "${PWD}"/maven && ! -d "${HOME}"/.m2 ]] && ln -s "${PWD}"/maven "${HOME}"/.m2 6 | 7 | function clean_gpg { 8 | FINGERPRINT=$(gpg --list-keys | head -4 | tail -1 | tr -d ' ') 9 | gpg --batch --yes --delete-secret-keys "$FINGERPRINT" 10 | gpg --batch --yes --delete-keys "$FINGERPRINT" 11 | } 12 | 13 | trap clean_gpg EXIT 14 | gpg --batch --import-options import-show --import <(echo "$MAVEN_GPG_PRIVATE_KEY") 15 | 16 | mkdir -p ~/.m2 17 | cat < ~/.m2/settings.xml 18 | 21 | 22 | 23 | gpg.passphrase 24 | ${MAVEN_GPG_PASSPHRASE} 25 | 26 | 27 | 28 | EOF 29 | 30 | REPOSITORY="${PWD}"/repository 31 | 32 | cd source 33 | ./mvnw deploy -Dmaven.test.skip=true -DaltDeploymentRepository="local::default::file://${REPOSITORY}" 34 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/pem/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * SSL trust material provider for PEM-encoded certificates. 19 | * 20 | * This package is copied from org.springframework.boot.ssl.pem introduced into spring-boot in v3.1.0. 21 | * It is simplified somewhat here, and modified for Java 8 compatibility. 22 | * We copied it because the spring-cloud-bindings library needs to work with older versions of spring boot, and must be 23 | * Java 8 compatible. 24 | */ 25 | package org.springframework.cloud.bindings.boot.pem; 26 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/Guards.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.core.env.Environment; 20 | 21 | final class Guards { 22 | 23 | static boolean isGlobalEnabled(Environment environment) { 24 | return environment.getProperty("org.springframework.cloud.bindings.boot.enable", Boolean.class, true); 25 | } 26 | 27 | static boolean isTypeEnabled(Environment environment, String type) { 28 | return environment.getProperty( 29 | String.format("org.springframework.cloud.bindings.boot.%s.enable", type), 30 | Boolean.class, true); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /scripts/bump-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | [[ -d "${PWD}"/maven && ! -d "${HOME}"/.m2 ]] && ln -s "${PWD}"/maven "${HOME}"/.m2 6 | 7 | if [[ "$#" -ne 1 ]]; then 8 | printf "%s [ major | minor | patch ]\n" "$(basename "$0")" 9 | exit 1 10 | fi 11 | 12 | case "$1" in 13 | major ) 14 | printf "Bumping major\n" 15 | VERSION_PATTERN='${parsedVersion.nextMajorVersion}.0.0-SNAPSHOT' 16 | ;; 17 | minor ) 18 | printf "Bumping minor\n" 19 | VERSION_PATTERN='${parsedVersion.majorVersion}.${parsedVersion.nextMinorVersion}.0-SNAPSHOT' 20 | ;; 21 | patch ) 22 | printf "Bumping patch\n" 23 | VERSION_PATTERN='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.nextIncrementalVersion}-SNAPSHOT' 24 | ;; 25 | * ) 26 | printf "Unknown bump type %s\n" "$1" 27 | exit 1 28 | ;; 29 | esac 30 | 31 | cd source 32 | 33 | ./mvnw build-helper:parse-version versions:set -DgenerateBackupPoms=false -DnewVersion="${VERSION_PATTERN}" 34 | VERSION=$(./mvnw --quiet help:evaluate -DforceStdout -Dexpression=project.version) 35 | 36 | git add pom.xml 37 | git add spring-cloud-bindings/pom.xml 38 | git add spring-cloud-bindings-tests/pom.xml 39 | 40 | git checkout -- . 41 | 42 | git \ 43 | -c user.name='Paketo Robot' \ 44 | -c user.email='robot@paketo.io' \ 45 | commit \ 46 | --signoff \ 47 | --message "v${VERSION} Development" 48 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/BindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Bindings; 20 | import org.springframework.core.env.Environment; 21 | 22 | import java.util.Map; 23 | 24 | /** 25 | * An interface for types that transform the contents of a {@link Bindings} into properties for injection into a 26 | * {@link org.springframework.core.env.PropertySource}. 27 | */ 28 | @FunctionalInterface 29 | public interface BindingsPropertiesProcessor { 30 | 31 | /** 32 | * Transform the currently accumulated {@link Bindings}-related properties. 33 | * 34 | * @param environment the {@link Environment} that the processor is executing with. 35 | * @param bindings the {@code Bindings} exposed to the application. 36 | * @param properties the currently accumulated properties. 37 | */ 38 | void process(Environment environment, Bindings bindings, Map properties); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/PropertySourceContributor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.core.env.ConfigurableEnvironment; 20 | import org.springframework.core.env.MapPropertySource; 21 | import org.springframework.core.env.MutablePropertySources; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.core.env.CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME; 26 | 27 | final class PropertySourceContributor { 28 | 29 | static void contributePropertySource(String name, Map properties, ConfigurableEnvironment environment) { 30 | MapPropertySource propertySource = new MapPropertySource(name, properties); 31 | 32 | MutablePropertySources propertySources = environment.getPropertySources(); 33 | if (propertySources.contains(COMMAND_LINE_PROPERTY_SOURCE_NAME)) { 34 | propertySources.addAfter(COMMAND_LINE_PROPERTY_SOURCE_NAME, propertySource); 35 | } else { 36 | propertySources.addFirst(propertySource); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/pem/test-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDR0KfxUw7MF/8R 3 | B5/YXOM7yLnoHYb/M/6dyoulMbtEdKKhQhU28o5FiDkHcEG9PJQLgqrRgAjl3VmC 4 | C9omtfZJQ2EpfkTttkJjnKOOroXhYE51/CYSckapBYCVh8GkjUEJuEfnp07cTfYZ 5 | FqViIgIWPZyjkzl3w4girS7kCuzNdDntVJVx5F/EsFwMA8n3C0QazHQoM5s00Fer 6 | 6aTwd6AW0JD5QkADavpfzZ554e4HrVGwHlM28WKQQkFzzGu44FFXyVuEF3HeyVPu 7 | g8GRHAc8UU7ijVgJB5TmbvRGYowIErD5i4VvGLuOv9mgR3aVyN0SdJ1N7aJnXpeS 8 | QjAgf03jAgMBAAECggEBAIhQyzwj3WJGWOZkkLqOpufJotcmj/Wwf0VfOdkq9WMl 9 | cB/bAlN/xWVxerPVgDCFch4EWBzi1WUaqbOvJZ2u7QNubmr56aiTmJCFTVI/GyZx 10 | XqiTGN01N6lKtN7xo6LYTyAUhUsBTWAemrx0FSErvTVb9C/mUBj6hbEZ2XQ5kN5t 11 | 7qYX4Lu0zyn7s1kX5SLtm5I+YRq7HSwB6wLy+DSroO71izZ/VPwME3SwT5SN+c87 12 | 3dkklR7fumNd9dOpSWKrLPnq4aMko00rvIGc63xD1HrEpXUkB5v24YEn7HwCLEH7 13 | b8jrp79j2nCvvR47inpf+BR8FIWAHEOUUqCEzjQkdiECgYEA6ifjMM0f02KPeIs7 14 | zXd1lI7CUmJmzkcklCIpEbKWf/t/PHv3QgqIkJzERzRaJ8b+GhQ4zrSwAhrGUmI8 15 | kDkXIqe2/2ONgIOX2UOHYHyTDQZHnlXyDecvHUTqs2JQZCGBZkXyZ9i0j3BnTymC 16 | iZ8DvEa0nxsbP+U3rgzPQmXiQVMCgYEA5WN2Y/RndbriNsNrsHYRldbPO5nfV9rp 17 | cDzcQU66HRdK5VIdbXT9tlMYCJIZsSqE0tkOwTgEB/sFvF/tIHSCY5iO6hpIyk6g 18 | kkUzPcld4eM0dEPAge7SYUbakB9CMvA7MkDQSXQNFyZ0mH83+UikwT6uYHFh7+ox 19 | N1P+psDhXzECgYEA1gXLVQnIcy/9LxMkgDMWV8j8uMyUZysDthpbK3/uq+A2dhRg 20 | 9g4msPd5OBQT65OpIjElk1n4HpRWfWqpLLHiAZ0GWPynk7W0D7P3gyuaRSdeQs0P 21 | x8FtgPVDCN9t13gAjHiWjnC26Py2kNbCKAQeJ/MAmQTvrUFX2VCACJKTcV0CgYAj 22 | xJWSUmrLfb+GQISLOG3Xim434e9keJsLyEGj4U29+YLRLTOvfJ2PD3fg5j8hU/rw 23 | Ea5uTHi8cdTcIa0M8X3fX8txD3YoLYh2JlouGTcNYOst8d6TpBSj3HN6I5Wj8beZ 24 | R2fy/CiKYpGtsbCdq0kdZNO18BgQW9kewncjs1GxEQKBgQCf8q34h6KuHpHSDh9h 25 | YkDTypk0FReWBAVJCzDNDUMhVLFivjcwtaMd2LiC3FMKZYodr52iKg60cj43vbYI 26 | frmFFxoL37rTmUocCTBKc0LhWj6MicI+rcvQYe1uwTrpWdFf1aZJMYRLRczeKtev 27 | OWaE/9hVZ5+9pild1NukGpOydw== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/WavefrontBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class WavefrontBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "wavefront"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | map.from("api-token").to("management.wavefront.api-token"); 46 | map.from("uri").to("management.wavefront.uri"); 47 | }); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/resources/pem/test-cert-chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN TRUSTED CERTIFICATE----- 2 | MIIClzCCAgACCQCPbjkRoMVEQDANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMC 3 | VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28x 4 | DTALBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxFDASBgNVBAMMC2V4YW1wbGUu 5 | Y29tMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1wbGUuY29tMB4XDTIwMDMyNzIx 6 | NTgwNFoXDTIxMDMyNzIxNTgwNFowgY8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD 7 | YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQKDARUZXN0 8 | MQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAtleGFtcGxlLmNvbTEfMB0GCSqGSIb3 9 | DQEJARYQdGVzdEBleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC 10 | gYEA1YzixWEoyzrd20C2R1gjyPCoPfFLlG6UYTyT0tueNy6yjv6qbJ8lcZg7616O 11 | 3I9LuOHhZh9U+fCDCgPfiDdyJfDEW/P+dsOMFyMUXPrJPze2yPpOnvV8iJ5DM93u 12 | fEVhCCyzLdYu0P2P3hU2W+T3/Im9DA7FOPA2vF1SrIJ2qtUCAwEAATANBgkqhkiG 13 | 9w0BAQUFAAOBgQBdShkwUv78vkn1jAdtfbB+7mpV9tufVdo29j7pmotTCz3ny5fc 14 | zLEfeu6JPugAR71JYbc2CqGrMneSk1zT91EH6ohIz8OR5VNvzB7N7q65Ci7OFMPl 15 | ly6k3rHpMCBtHoyNFhNVfPLxGJ9VlWFKLgIAbCmL4OIQm1l6Fr1MSM38Zw== 16 | -----END TRUSTED CERTIFICATE----- 17 | -----BEGIN CERTIFICATE----- 18 | MIICjzCCAfgCAQEwDQYJKoZIhvcNAQEFBQAwgY8xCzAJBgNVBAYTAlVTMRMwEQYD 19 | VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ0wCwYDVQQK 20 | DARUZXN0MQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAtleGFtcGxlLmNvbTEfMB0G 21 | CSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0yMDAzMjcyMjAxNDZaFw0y 22 | MTAzMjcyMjAxNDZaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p 23 | YTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwEVGVzdDENMAsGA1UE 24 | CwwEVGVzdDEUMBIGA1UEAwwLZXhhbXBsZS5jb20xHzAdBgkqhkiG9w0BCQEWEHRl 25 | c3RAZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM7kd2cj 26 | F49wm1+OQ7Q5GE96cXueWNPr/Nwei71tf6G4BmE0B+suXHEvnLpHTj9pdX/ZzBIK 27 | 8jIZ/x8RnSduK/Ky+zm1QMYUWZtWCAgCW8WzgB69Cn/hQG8KSX3S9bqODuQAvP54 28 | GQJD7+4kVuNBGjFb4DaD4nvMmPtALSZf8ZCZAgMBAAEwDQYJKoZIhvcNAQEFBQAD 29 | gYEAOn6X8+0VVlDjF+TvTgI0KIasA6nDm+KXe7LVtfvqWqQZH4qyd2uiwcDM3Aux 30 | a/OsPdOw0j+NqFDBd3mSMhSVgfvXdK6j9WaxY1VGXyaidLARgvn63wfzgr857sQW 31 | c8eSxbwEQxwlMvVxW6Os4VhCfUQr8VrBrvPa2zs+6IlK+Ug= 32 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/Neo4JBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | final class Neo4JBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | /** 32 | * The {@link Binding} type that this processor is interested in: {@value}. 33 | **/ 34 | public static final String TYPE = "neo4j"; 35 | 36 | @Override 37 | public void process(Environment environment, Bindings bindings, Map properties) { 38 | if (!isTypeEnabled(environment, TYPE)) { 39 | return; 40 | } 41 | 42 | bindings.filterBindings(TYPE).forEach(binding -> { 43 | MapMapper map = new MapMapper(binding.getSecret(), properties); 44 | map.from("password").to("spring.neo4j.authentication.password"); 45 | map.from("uri").to("spring.neo4j.uri"); 46 | map.from("username").to("spring.neo4j.authentication.username"); 47 | 48 | }); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/ElasticsearchBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | final class ElasticsearchBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "elasticsearch"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | map.from("password").to("spring.elasticsearch.password"); 46 | map.from("uris").to("spring.elasticsearch.uris"); 47 | map.from("username").to("spring.elasticsearch.username"); 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/LDAPBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class LDAPBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | /** 32 | * The {@link Binding} type that this processor is interested in: {@value}. 33 | **/ 34 | public static final String TYPE = "ldap"; 35 | 36 | @Override 37 | public void process(Environment environment, Bindings bindings, Map properties) { 38 | if (!isTypeEnabled(environment, TYPE)) { 39 | return; 40 | } 41 | 42 | bindings.filterBindings(TYPE).forEach(binding -> { 43 | MapMapper map = new MapMapper(binding.getSecret(), properties); 44 | map.from("base").to("spring.ldap.base"); 45 | map.from("password").to("spring.ldap.password"); 46 | map.from("urls").to("spring.ldap.urls"); 47 | map.from("username").to("spring.ldap.username"); 48 | }); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/pem/PemCertificateParserTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.IOException; 20 | import java.security.cert.X509Certificate; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.core.io.ClassPathResource; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | import static org.springframework.cloud.bindings.boot.TestHelper.resourceAsString; 28 | 29 | /** 30 | * Tests for {@link PemCertificateParser}. 31 | * 32 | * @author Scott Frederick 33 | */ 34 | class PemCertificateParserTests { 35 | 36 | @Test 37 | void parseCertificate() throws Exception { 38 | X509Certificate[] certificates = PemCertificateParser.parse(read("pem/test-cert.pem")); 39 | assertThat(certificates).isNotNull(); 40 | assertThat(certificates).hasSize(1); 41 | assertThat(certificates[0].getType()).isEqualTo("X.509"); 42 | } 43 | 44 | @Test 45 | void parseCertificateChain() throws Exception { 46 | X509Certificate[] certificates = PemCertificateParser.parse(read("pem/test-cert-chain.pem")); 47 | assertThat(certificates).isNotNull(); 48 | assertThat(certificates).hasSize(2); 49 | assertThat(certificates[0].getType()).isEqualTo("X.509"); 50 | assertThat(certificates[1].getType()).isEqualTo("X.509"); 51 | } 52 | 53 | private String read(String path) throws IOException { 54 | return resourceAsString(new ClassPathResource(path)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/CouchbaseBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | final class CouchbaseBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | /** 32 | * The {@link Binding} type that this processor is interested in: {@value}. 33 | **/ 34 | public static final String TYPE = "couchbase"; 35 | 36 | @Override 37 | public void process(Environment environment, Bindings bindings, Map properties) { 38 | if (!isTypeEnabled(environment, TYPE)) { 39 | return; 40 | } 41 | 42 | bindings.filterBindings(TYPE).forEach(binding -> { 43 | MapMapper map = new MapMapper(binding.getSecret(), properties); 44 | map.from("bucket-name").to("spring.data.couchbase.bucket-name"); 45 | map.from("connection-string").to("spring.couchbase.connection-string"); 46 | map.from("password").to("spring.couchbase.password"); 47 | map.from("username").to("spring.couchbase.username"); 48 | 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/KafkaBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | final class KafkaBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | /** 32 | * The {@link Binding} type that this processor is interested in: {@value}. 33 | **/ 34 | public static final String TYPE = "kafka"; 35 | 36 | @Override 37 | public void process(Environment environment, Bindings bindings, Map properties) { 38 | if (!isTypeEnabled(environment, TYPE)) { 39 | return; 40 | } 41 | 42 | bindings.filterBindings(TYPE).forEach(binding -> { 43 | MapMapper map = new MapMapper(binding.getSecret(), properties); 44 | 45 | map.from("bootstrap-servers").to("spring.kafka.bootstrap-servers"); 46 | map.from("consumer.bootstrap-servers").to("spring.kafka.consumer.bootstrap-servers"); 47 | map.from("producer.bootstrap-servers").to("spring.kafka.producer.bootstrap-servers"); 48 | map.from("streams.bootstrap-servers").to("spring.kafka.streams.bootstrap-servers"); 49 | }); 50 | 51 | }} 52 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/pem/PemContent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStreamReader; 21 | import java.io.Reader; 22 | import java.net.URL; 23 | import java.nio.charset.StandardCharsets; 24 | import java.util.regex.Pattern; 25 | 26 | import org.springframework.util.FileCopyUtils; 27 | import org.springframework.util.ResourceUtils; 28 | 29 | /** 30 | * Utility to load PEM content. 31 | * 32 | * @author Scott Frederick 33 | * @author Phillip Webb 34 | */ 35 | final class PemContent { 36 | 37 | private static final Pattern PEM_HEADER = Pattern.compile("-+BEGIN\\s+[^-]*-+", Pattern.CASE_INSENSITIVE); 38 | 39 | private static final Pattern PEM_FOOTER = Pattern.compile("-+END\\s+[^-]*-+", Pattern.CASE_INSENSITIVE); 40 | 41 | private PemContent() { 42 | } 43 | 44 | static String load(String content) { 45 | if (content == null || isPemContent(content)) { 46 | return content; 47 | } 48 | try { 49 | URL url = ResourceUtils.getURL(content); 50 | try (Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) { 51 | return FileCopyUtils.copyToString(reader); 52 | } 53 | } 54 | catch (IOException ex) { 55 | throw new IllegalStateException( 56 | "Error reading certificate or key from file '" + content + "':" + ex.getMessage(), ex); 57 | } 58 | } 59 | 60 | private static boolean isPemContent(String content) { 61 | return content != null && PEM_HEADER.matcher(content).find() && PEM_FOOTER.matcher(content).find(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/RabbitMqBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | final class RabbitMqBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "rabbitmq"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | 46 | map.from("addresses").to("spring.rabbitmq.addresses"); 47 | map.from("host").to("spring.rabbitmq.host"); 48 | map.from("password").to("spring.rabbitmq.password"); 49 | map.from("port").to("spring.rabbitmq.port"); 50 | map.from("username").to("spring.rabbitmq.username"); 51 | map.from("virtual-host").to("spring.rabbitmq.virtual-host"); 52 | }); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/pem/PemPrivateKeyParserTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.IOException; 20 | import java.security.PrivateKey; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | import org.springframework.core.io.ClassPathResource; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | import static org.assertj.core.api.Assertions.assertThatIllegalStateException; 28 | import static org.springframework.cloud.bindings.boot.TestHelper.resourceAsString; 29 | 30 | /** 31 | * Tests for {@link PemPrivateKeyParser}. 32 | * 33 | * @author Scott Frederick 34 | */ 35 | class PemPrivateKeyParserTests { 36 | 37 | @Test 38 | void parsePkcs8KeyFile() throws Exception { 39 | PrivateKey privateKey = PemPrivateKeyParser.parse(read("pem/test-key.pem")); 40 | assertThat(privateKey).isNotNull(); 41 | assertThat(privateKey.getFormat()).isEqualTo("PKCS#8"); 42 | assertThat(privateKey.getAlgorithm()).isEqualTo("RSA"); 43 | } 44 | 45 | @Test 46 | void parsePkcs8KeyFileWithEcdsa() throws Exception { 47 | PrivateKey privateKey = PemPrivateKeyParser.parse(read("pem/test-ec-key.pem")); 48 | assertThat(privateKey).isNotNull(); 49 | assertThat(privateKey.getFormat()).isEqualTo("PKCS#8"); 50 | assertThat(privateKey.getAlgorithm()).isEqualTo("EC"); 51 | } 52 | 53 | @Test 54 | void parseWithNonKeyTextWillThrowException() { 55 | assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("pem/test-banner.txt"))); 56 | } 57 | 58 | private String read(String path) throws IOException { 59 | return resourceAsString(new ClassPathResource(path)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/MongoDbBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class MongoDbBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "mongodb"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | 46 | map.from("authentication-database").to("spring.data.mongodb.authentication-database"); 47 | map.from("database").to("spring.data.mongodb.database"); 48 | map.from("grid-fs-database").to("spring.data.mongodb.gridfs.database"); 49 | map.from("host").to("spring.data.mongodb.host"); 50 | map.from("password").to("spring.data.mongodb.password"); 51 | map.from("port").to("spring.data.mongodb.port"); 52 | map.from("uri").to("spring.data.mongodb.uri"); 53 | map.from("username").to("spring.data.mongodb.username"); 54 | }); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.context.ApplicationListener=\ 2 | org.springframework.cloud.bindings.boot.BindingFlattenedEnvironmentPostProcessor, \ 3 | org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor, \ 4 | org.springframework.cloud.bindings.boot.SpringSecurityOAuth2BindingsPropertiesProcessor, \ 5 | org.springframework.cloud.bindings.boot.VaultBindingsPropertiesProcessor 6 | org.springframework.boot.env.EnvironmentPostProcessor=\ 7 | org.springframework.cloud.bindings.boot.BindingFlattenedEnvironmentPostProcessor, \ 8 | org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor 9 | # Included implementations 10 | org.springframework.cloud.bindings.boot.BindingsPropertiesProcessor=\ 11 | org.springframework.cloud.bindings.boot.ArtemisBindingsPropertiesProcessor, \ 12 | org.springframework.cloud.bindings.boot.CassandraBindingsPropertiesProcessor, \ 13 | org.springframework.cloud.bindings.boot.ConfigServerBindingsPropertiesProcessor, \ 14 | org.springframework.cloud.bindings.boot.CouchbaseBindingsPropertiesProcessor, \ 15 | org.springframework.cloud.bindings.boot.Db2BindingsPropertiesProcessor, \ 16 | org.springframework.cloud.bindings.boot.ElasticsearchBindingsPropertiesProcessor, \ 17 | org.springframework.cloud.bindings.boot.EurekaBindingsPropertiesProcessor, \ 18 | org.springframework.cloud.bindings.boot.KafkaBindingsPropertiesProcessor, \ 19 | org.springframework.cloud.bindings.boot.LDAPBindingsPropertiesProcessor, \ 20 | org.springframework.cloud.bindings.boot.MongoDbBindingsPropertiesProcessor, \ 21 | org.springframework.cloud.bindings.boot.MySqlBindingsPropertiesProcessor, \ 22 | org.springframework.cloud.bindings.boot.Neo4JBindingsPropertiesProcessor, \ 23 | org.springframework.cloud.bindings.boot.OracleBindingsPropertiesProcessor, \ 24 | org.springframework.cloud.bindings.boot.PostgreSqlBindingsPropertiesProcessor, \ 25 | org.springframework.cloud.bindings.boot.RabbitMqBindingsPropertiesProcessor, \ 26 | org.springframework.cloud.bindings.boot.RedisBindingsPropertiesProcessor, \ 27 | org.springframework.cloud.bindings.boot.SapHanaBindingsPropertiesProcessor, \ 28 | org.springframework.cloud.bindings.boot.SpringSecurityOAuth2BindingsPropertiesProcessor, \ 29 | org.springframework.cloud.bindings.boot.SqlServerBindingsPropertiesProcessor, \ 30 | org.springframework.cloud.bindings.boot.VaultBindingsPropertiesProcessor, \ 31 | org.springframework.cloud.bindings.boot.WavefrontBindingsPropertiesProcessor 32 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/RedisBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class RedisBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "redis"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | 46 | map.from("client-name").to("spring.data.redis.client-name"); 47 | map.from("cluster.max-redirects").to("spring.data.redis.cluster.max-redirects"); 48 | map.from("cluster.nodes").to("spring.data.redis.cluster.nodes"); 49 | map.from("database").to("spring.data.redis.database"); 50 | map.from("host").to("spring.data.redis.host"); 51 | map.from("password").to("spring.data.redis.password"); 52 | map.from("port").to("spring.data.redis.port"); 53 | map.from("sentinel.master").to("spring.data.redis.sentinel.master"); 54 | map.from("sentinel.nodes").to("spring.data.redis.sentinel.nodes"); 55 | map.from("ssl").to("spring.data.redis.ssl"); 56 | map.from("url").to("spring.data.redis.url"); 57 | }); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/PropertySourceContributorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.core.env.PropertySource; 22 | import org.springframework.core.env.SimpleCommandLinePropertySource; 23 | import org.springframework.mock.env.MockEnvironment; 24 | 25 | import java.util.Collections; 26 | 27 | import static org.assertj.core.api.Assertions.assertThat; 28 | import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource; 29 | 30 | @DisplayName("PropertySource Contributor") 31 | final class PropertySourceContributorTest { 32 | 33 | private final MockEnvironment environment = new MockEnvironment(); 34 | 35 | @Test 36 | @DisplayName("adds PropertySource after CommandLinePropertySource") 37 | void withCommandLinePropertySource() { 38 | environment.getPropertySources().addFirst(new SimpleCommandLinePropertySource()); 39 | 40 | contributePropertySource("test-name", Collections.singletonMap("test-key", "test-value"), environment); 41 | 42 | PropertySource propertySource = environment.getPropertySources().get("test-name"); 43 | assertThat(propertySource).isNotNull(); 44 | assertThat(propertySource.getProperty("test-key")).isEqualTo("test-value"); 45 | assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(1); 46 | } 47 | 48 | @Test 49 | @DisplayName("adds PropertySource first") 50 | void withoutCommandLinePropertySource() { 51 | contributePropertySource("test-name", Collections.singletonMap("test-key", "test-value"), environment); 52 | 53 | PropertySource propertySource = environment.getPropertySources().get("test-name"); 54 | assertThat(propertySource).isNotNull(); 55 | assertThat(propertySource.getProperty("test-key")).isEqualTo("test-value"); 56 | assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(0); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/WavefrontBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.WavefrontBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Wavefront BindingsPropertiesProcessor") 33 | final class WavefrontBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("api-token", "test-api-token") 40 | .withEntry("uri", "test-uri") 41 | ) 42 | ); 43 | 44 | private final MockEnvironment environment = new MockEnvironment(); 45 | 46 | private final HashMap properties = new HashMap<>(); 47 | 48 | @Test 49 | @DisplayName("contributes properties") 50 | void test() { 51 | new WavefrontBindingsPropertiesProcessor().process(environment, bindings, properties); 52 | assertThat(properties) 53 | .containsEntry("management.wavefront.api-token", "test-api-token") 54 | .containsEntry("management.wavefront.uri", "test-uri"); 55 | } 56 | 57 | @Test 58 | @DisplayName("can be disabled") 59 | void disabled() { 60 | environment.setProperty("org.springframework.cloud.bindings.boot.wavefront.enable", "false"); 61 | 62 | new WavefrontBindingsPropertiesProcessor().process(environment, bindings, properties); 63 | 64 | assertThat(properties).isEmpty(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/Neo4JBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.Neo4JBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Neo4J BindingsPropertiesProcessor") 33 | final class Neo4JBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("password", "test-password") 40 | .withEntry("uri", "test-uri") 41 | .withEntry("username", "test-username") 42 | ) 43 | ); 44 | 45 | private final MockEnvironment environment = new MockEnvironment(); 46 | 47 | private final HashMap properties = new HashMap<>(); 48 | 49 | @Test 50 | @DisplayName("contributes properties") 51 | void testSb3() { 52 | new Neo4JBindingsPropertiesProcessor().process(environment, bindings, properties); 53 | assertThat(properties) 54 | .containsEntry("spring.neo4j.authentication.password", "test-password") 55 | .containsEntry("spring.neo4j.uri", "test-uri") 56 | .containsEntry("spring.neo4j.authentication.username", "test-username"); 57 | } 58 | 59 | @Test 60 | @DisplayName("can be disabled") 61 | void disabled() { 62 | environment.setProperty("org.springframework.cloud.bindings.boot.neo4j.enable", "false"); 63 | 64 | new Neo4JBindingsPropertiesProcessor().process(environment, bindings, properties); 65 | assertThat(properties).isEmpty(); 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/SapHanaBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class SapHanaBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "hana"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | 46 | //jdbc properties 47 | map.from("password").to("spring.datasource.password"); 48 | map.from("host", "port", "database").to("spring.datasource.url", 49 | (host, port, database) -> String.format("jdbc:sap://%s:%s/%s", host, port, database)); 50 | map.from("username").to("spring.datasource.username"); 51 | 52 | // jdbcURL takes precedence 53 | map.from("jdbc-url").to("spring.datasource.url"); 54 | 55 | properties.put("spring.datasource.driver-class-name", "com.sap.db.jdbc.Driver"); 56 | 57 | //r2dbc properties 58 | map.from("password").to("spring.r2dbc.password"); 59 | map.from("host", "port", "database").to("spring.r2dbc.url", 60 | (host, port, database) -> String.format("r2dbc:sap://%s:%s/%s", host, port, database)); 61 | map.from("username").to("spring.r2dbc.username"); 62 | 63 | // r2dbcURL takes precedence 64 | map.from("r2dbc-url").to("spring.r2dbc.url"); 65 | }); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/CassandraBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class CassandraBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | /** 32 | * The {@link Binding} type that this processor is interested in: {@value}. 33 | **/ 34 | public static final String TYPE = "cassandra"; 35 | 36 | @Override 37 | public void process(Environment environment, Bindings bindings, Map properties) { 38 | if (!isTypeEnabled(environment, TYPE)) { 39 | return; 40 | } 41 | 42 | bindings.filterBindings(TYPE).forEach(binding -> { 43 | MapMapper map = new MapMapper(binding.getSecret(), properties); 44 | map.from("cluster-name").to("spring.cassandra.cluster-name"); 45 | map.from("compression").to("spring.cassandra.compression"); 46 | map.from("contact-points").to("spring.cassandra.contact-points"); 47 | map.from("keyspace-name").to("spring.cassandra.keyspace-name"); 48 | map.from("password").to("spring.cassandra.password"); 49 | map.from("port").to("spring.cassandra.port"); 50 | map.from("ssl").to("spring.cassandra.ssl"); 51 | map.from("username").to("spring.cassandra.username"); 52 | 53 | map.from("request.throttler.drain-interval").to("spring.cassandra.request.throttler.drain-interval"); 54 | map.from("request.throttler.max-concurrent-requests").to("spring.cassandra.request.throttler.max-concurrent-requests"); 55 | map.from("request.throttler.max-queue-size").to("spring.cassandra.request.throttler.max-queue-size"); 56 | map.from("request.throttler.max-requests-per-second").to("spring.cassandra.request.throttler.max-requests-per-second"); 57 | }); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /spring-cloud-bindings-tests/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.cloud 7 | spring-cloud-bindings-parent 8 | 2.0.4-SNAPSHOT 9 | ../pom.xml 10 | 11 | spring-cloud-bindings-tests 12 | Test project to verify Spring Cloud Bindings works properly with Spring Boot 2 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter 17 | ${spring-boot.version} 18 | test 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-data-redis 23 | ${spring-boot.version} 24 | test 25 | 26 | 27 | javax.annotation 28 | javax.annotation-api 29 | 1.3.1 30 | test 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-bindings 35 | ${project.version} 36 | test 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | ${spring-boot.version} 42 | test 43 | 44 | 45 | com.github.kstyrc 46 | embedded-redis 47 | 0.6 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-deploy-plugin 57 | ${maven-deploy-plugin.version} 58 | 59 | true 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 3.10.1 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-surefire-plugin 70 | 2.22.2 71 | 72 | 1 73 | false 74 | 75 | ${basedir}/src/test/resources/bindings 76 | 77 | -Xmx1024m 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/ElasticsearchBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.ElasticsearchBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Elasticsearch BindingsPropertiesProcessor") 33 | final class ElasticsearchBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindingsSpringBoot3 = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("password", "test-password") 40 | .withEntry("uris", "test-uris") 41 | .withEntry("username", "test-username") 42 | ) 43 | ); 44 | 45 | 46 | private final MockEnvironment environment = new MockEnvironment(); 47 | 48 | private final HashMap properties = new HashMap<>(); 49 | 50 | @Test 51 | @DisplayName("contributes properties - Spring Boot 2 flavor") 52 | void testSb3() { 53 | new ElasticsearchBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.elasticsearch.password", "test-password") 56 | .containsEntry("spring.elasticsearch.uris", "test-uris") 57 | .containsEntry("spring.elasticsearch.username", "test-username"); 58 | } 59 | 60 | @Test 61 | @DisplayName("can be disabled") 62 | void disabled() { 63 | environment.setProperty("org.springframework.cloud.bindings.boot.elasticsearch.enable", "false"); 64 | 65 | new ElasticsearchBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 66 | assertThat(properties).isEmpty(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/LDAPBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.LDAPBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("LDAP BindingsPropertiesProcessor") 33 | final class LDAPBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("urls", "test-urls") 40 | .withEntry("password", "test-password") 41 | .withEntry("username", "test-username") 42 | .withEntry("base", "test-base") 43 | ) 44 | ); 45 | 46 | private final MockEnvironment environment = new MockEnvironment(); 47 | 48 | private final HashMap properties = new HashMap<>(); 49 | 50 | @Test 51 | @DisplayName("contributes LDAP properties") 52 | void testJdbc() { 53 | new LDAPBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.ldap.urls", "test-urls") 56 | .containsEntry("spring.ldap.username", "test-username") 57 | .containsEntry("spring.ldap.password", "test-password") 58 | .containsEntry("spring.ldap.base", "test-base"); 59 | } 60 | 61 | @Test 62 | @DisplayName("can be disabled") 63 | void disabled() { 64 | environment.setProperty("org.springframework.cloud.bindings.boot.ldap.enable", "false"); 65 | 66 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 67 | 68 | assertThat(properties).isEmpty(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/pem/PemSslStoreHelperTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.nio.file.Path; 20 | import java.security.KeyStore; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 26 | import static org.junit.jupiter.api.Assertions.assertThrows; 27 | 28 | /** 29 | * Tests for {@link PemSslStoreHelper}. 30 | * 31 | */ 32 | class PemSslStoreHelperTests { 33 | @Test 34 | void createKeyStoreFileWhenNullValues() { 35 | assertThrows(java.lang.IllegalStateException.class, () -> { 36 | PemSslStoreHelper.createKeyStoreFile("key", "secret",null, null, "some-alias"); 37 | }); 38 | } 39 | 40 | @Test 41 | void createKeyStoreFileWhenHasKeyStoreDetailsCertAndKey() throws Exception { 42 | Path path = PemSslStoreHelper.createKeyStoreFile("key", "secret", "classpath:pem/test-cert.pem", "classpath:pem/test-key.pem", "some-alias"); 43 | KeyStore keyStore = KeyStore.getInstance(path.toFile(), "secret".toCharArray()); 44 | assertDoesNotThrow(() -> { 45 | assertThat(keyStore).isNotNull(); 46 | assertThat(keyStore.getType()).isEqualTo("PKCS12"); 47 | assertThat(keyStore.containsAlias("some-alias")).isTrue(); 48 | assertThat(keyStore.getCertificate("some-alias")).isNotNull(); 49 | assertThat(keyStore.getKey("some-alias", new char[]{})).isNotNull(); 50 | }); 51 | } 52 | 53 | @Test 54 | void createKeyStoreFileWhenHasTrustStoreDetailsWithoutKey() throws Exception { 55 | Path path = PemSslStoreHelper.createKeyStoreFile("trust", "secret", "classpath:pem/test-cert.pem", null, null); 56 | KeyStore keyStore = KeyStore.getInstance(path.toFile(), "secret".toCharArray()); 57 | assertDoesNotThrow(() -> { 58 | assertThat(keyStore).isNotNull(); 59 | assertThat(keyStore.getType()).isEqualTo("PKCS12"); 60 | assertThat(keyStore.containsAlias("ssl-0")).isTrue(); 61 | assertThat(keyStore.getCertificate("ssl-0")).isNotNull(); 62 | assertThat(keyStore.getKey("ssl-0", new char[]{})).isNull(); 63 | }); 64 | } 65 | 66 | @Test 67 | void generatePassword() { 68 | String s = PemSslStoreHelper.generatePassword(); 69 | assertThat(s).isNotNull(); 70 | assertThat(s.length()).isEqualTo(10); 71 | System.out.println(s); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/OracleBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | * 30 | * @see JDBC URL Format 31 | */ 32 | public final class OracleBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 33 | 34 | /** 35 | * The {@link Binding} type that this processor is interested in: {@value}. 36 | **/ 37 | public static final String TYPE = "oracle"; 38 | 39 | @Override 40 | public void process(Environment environment, Bindings bindings, Map properties) { 41 | if (!isTypeEnabled(environment, TYPE)) { 42 | return; 43 | } 44 | 45 | bindings.filterBindings(TYPE).forEach(binding -> { 46 | MapMapper map = new MapMapper(binding.getSecret(), properties); 47 | 48 | //jdbc properties 49 | map.from("username").to("spring.datasource.username"); 50 | map.from("password").to("spring.datasource.password"); 51 | map.from("host", "port", "database").to("spring.datasource.url", 52 | (host, port, database) -> String.format("jdbc:oracle://%s:%s/%s", host, port, database)); 53 | 54 | // jdbcURL takes precedence 55 | map.from("jdbc-url").to("spring.datasource.url"); 56 | 57 | properties.put("spring.datasource.driver-class-name", "oracle.jdbc.OracleDriver"); 58 | 59 | //r2dbc properties 60 | map.from("username").to("spring.r2dbc.username"); 61 | map.from("password").to("spring.r2dbc.password"); 62 | map.from("host", "port", "database").to("spring.r2dbc.url", 63 | (host, port, database) -> String.format("r2dbc:oracle://%s:%s/%s", host, port, database)); 64 | 65 | // r2dbcURL takes precedence 66 | map.from("r2dbc-url").to("spring.r2dbc.url"); 67 | }); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/Db2BindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | * 30 | * @see JDBC URL Format 31 | */ 32 | public final class Db2BindingsPropertiesProcessor implements BindingsPropertiesProcessor { 33 | 34 | /** 35 | * The {@link Binding} type that this processor is interested in: {@value}. 36 | **/ 37 | public static final String TYPE = "db2"; 38 | 39 | @Override 40 | public void process(Environment environment, Bindings bindings, Map properties) { 41 | if (!isTypeEnabled(environment, TYPE)) { 42 | return; 43 | } 44 | 45 | bindings.filterBindings(TYPE).forEach(binding -> { 46 | MapMapper map = new MapMapper(binding.getSecret(), properties); 47 | 48 | //jdbc properties 49 | map.from("username").to("spring.datasource.username"); 50 | map.from("password").to("spring.datasource.password"); 51 | map.from("host", "port", "database").to("spring.datasource.url", 52 | (host, port, database) -> String.format("jdbc:db2://%s:%s/%s", host, port, database)); 53 | 54 | // jdbcURL takes precedence 55 | map.from("jdbc-url").to("spring.datasource.url"); 56 | 57 | properties.put("spring.datasource.driver-class-name", "com.ibm.db2.jcc.DB2Driver"); 58 | 59 | //r2dbc properties 60 | map.from("username").to("spring.r2dbc.username"); 61 | map.from("password").to("spring.r2dbc.password"); 62 | map.from("host", "port", "database").to("spring.r2dbc.url", 63 | (host, port, database) -> String.format("r2dbc:db2://%s:%s/%s", host, port, database)); 64 | 65 | // r2dbcURL takes precedence 66 | map.from("r2dbc-url").to("spring.r2dbc.url"); 67 | }); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/ArtemisBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.ArtemisBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("ActiveMQ Artemis BindingsPropertiesProcessor") 33 | final class ArtemisBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindingsSpringBoot3 = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("mode", "EMBEDDED") 40 | .withEntry("broker-url", "tcp://test-host:test-port") 41 | .withEntry("user", "test-user") 42 | .withEntry("password", "test-password") 43 | ) 44 | ); 45 | 46 | private final MockEnvironment environment = new MockEnvironment(); 47 | 48 | private final HashMap properties = new HashMap<>(); 49 | 50 | @Test 51 | @DisplayName("contributes properties") 52 | void testSb3() { 53 | new ArtemisBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.artemis.mode", "EMBEDDED") 56 | .containsEntry("spring.artemis.broker-url", "tcp://test-host:test-port") 57 | .containsEntry("spring.artemis.password", "test-password") 58 | .containsEntry("spring.artemis.user", "test-user"); 59 | } 60 | 61 | @Test 62 | @DisplayName("can be disabled") 63 | void disabled() { 64 | environment.setProperty("org.springframework.cloud.bindings.boot.artemis.enable", "false"); 65 | 66 | new ArtemisBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 67 | assertThat(properties).isEmpty(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/SqlServerBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | * 30 | * @see JDBC URL Format 31 | */ 32 | public final class SqlServerBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 33 | 34 | /** 35 | * The {@link Binding} type that this processor is interested in: {@value}. 36 | **/ 37 | public static final String TYPE = "sqlserver"; 38 | 39 | @Override 40 | public void process(Environment environment, Bindings bindings, Map properties) { 41 | if (!isTypeEnabled(environment, TYPE)) { 42 | return; 43 | } 44 | 45 | bindings.filterBindings(TYPE).forEach(binding -> { 46 | MapMapper map = new MapMapper(binding.getSecret(), properties); 47 | 48 | //jdbc properties 49 | map.from("password").to("spring.datasource.password"); 50 | map.from("host", "port", "database").to("spring.datasource.url", 51 | (host, port, database) -> String.format("jdbc:sqlserver://%s:%s/%s", host, port, database)); 52 | map.from("username").to("spring.datasource.username"); 53 | 54 | // jdbcURL takes precedence 55 | map.from("jdbc-url").to("spring.datasource.url"); 56 | 57 | properties.put("spring.datasource.driver-class-name", "com.microsoft.sqlserver.jdbc.SQLServerDriver"); 58 | 59 | //r2dbc properties 60 | map.from("password").to("spring.r2dbc.password"); 61 | map.from("host", "port", "database").to("spring.r2dbc.url", 62 | (host, port, database) -> String.format("r2dbc:sqlserver://%s:%s/%s", host, port, database)); 63 | map.from("username").to("spring.r2dbc.username"); 64 | 65 | // r2dbcURL takes precedence 66 | map.from("r2dbc-url").to("spring.r2dbc.url"); 67 | }); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/CouchbaseBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.CouchbaseBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Couchbase BindingsPropertiesProcessor") 33 | final class CouchbaseBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindingsSpringBoot3 = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("connection-string", "test-connection-string") 40 | .withEntry("bucket-name", "test-bucket-name") 41 | .withEntry("username", "test-username") 42 | .withEntry("password", "test-password") 43 | ) 44 | ); 45 | 46 | private final MockEnvironment environment = new MockEnvironment(); 47 | 48 | private final HashMap properties = new HashMap<>(); 49 | 50 | @Test 51 | @DisplayName("contributes properties") 52 | void testSb3() { 53 | new CouchbaseBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.couchbase.connection-string", "test-connection-string") 56 | .containsEntry("spring.data.couchbase.bucket-name", "test-bucket-name") 57 | .containsEntry("spring.couchbase.username", "test-username") 58 | .containsEntry("spring.couchbase.password", "test-password"); 59 | } 60 | 61 | @Test 62 | @DisplayName("can be disabled") 63 | void disabled() { 64 | environment.setProperty("org.springframework.cloud.bindings.boot.couchbase.enable", "false"); 65 | 66 | new CouchbaseBindingsPropertiesProcessor().process(environment, bindingsSpringBoot3, properties); 67 | assertThat(properties).isEmpty(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/GuardsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Nested; 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.mock.env.MockEnvironment; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.springframework.cloud.bindings.boot.Guards.isGlobalEnabled; 26 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 27 | 28 | @DisplayName("Guards") 29 | final class GuardsTest { 30 | 31 | @Nested 32 | @DisplayName("Global Guard") 33 | final class GlobalGuard { 34 | 35 | private final MockEnvironment environment = new MockEnvironment(); 36 | 37 | @Test 38 | @DisplayName("returns true if unset") 39 | void unset() { 40 | assertThat(isGlobalEnabled(environment)).isTrue(); 41 | } 42 | 43 | @Test 44 | @DisplayName("returns the set value of true") 45 | void setTrue() { 46 | environment.setProperty("org.springframework.cloud.bindings.boot.enable", "true"); 47 | assertThat(isGlobalEnabled(environment)).isTrue(); 48 | } 49 | 50 | @Test 51 | @DisplayName("returns the set value of false") 52 | void setFalse() { 53 | environment.setProperty("org.springframework.cloud.bindings.boot.enable", "false"); 54 | assertThat(isGlobalEnabled(environment)).isFalse(); 55 | } 56 | 57 | } 58 | 59 | @Nested 60 | @DisplayName("Type Guard") 61 | final class TypeGuard { 62 | 63 | private final MockEnvironment environment = new MockEnvironment(); 64 | 65 | @Test 66 | @DisplayName("returns true if unset") 67 | void unset() { 68 | assertThat(isTypeEnabled(environment, "Test")).isTrue(); 69 | } 70 | 71 | @Test 72 | @DisplayName("returns the set value of true") 73 | void setTrue() { 74 | environment.setProperty("org.springframework.cloud.bindings.boot.test.enable", "true"); 75 | assertThat(isTypeEnabled(environment, "Test")).isTrue(); 76 | } 77 | 78 | @Test 79 | @DisplayName("returns the set value of false") 80 | void setFalse() { 81 | environment.setProperty("org.springframework.cloud.bindings.boot.test.enable", "false"); 82 | assertThat(isTypeEnabled(environment, "test")).isFalse(); 83 | } 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/KafkaBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.KafkaBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Kafka BindingsPropertiesProcessor") 33 | final class KafkaBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("bootstrap-servers", "test-bootstrap-servers") 40 | .withEntry("consumer.bootstrap-servers", "test-consumer-bootstrap-servers") 41 | .withEntry("producer.bootstrap-servers", "test-producer-bootstrap-servers") 42 | .withEntry("streams.bootstrap-servers", "test-streams-bootstrap-servers") 43 | ) 44 | ); 45 | 46 | private final MockEnvironment environment = new MockEnvironment(); 47 | 48 | private final HashMap properties = new HashMap<>(); 49 | 50 | @Test 51 | @DisplayName("contributes properties") 52 | void test() { 53 | new KafkaBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.kafka.bootstrap-servers", "test-bootstrap-servers") 56 | .containsEntry("spring.kafka.consumer.bootstrap-servers", "test-consumer-bootstrap-servers") 57 | .containsEntry("spring.kafka.producer.bootstrap-servers", "test-producer-bootstrap-servers") 58 | .containsEntry("spring.kafka.streams.bootstrap-servers", "test-streams-bootstrap-servers"); 59 | } 60 | 61 | @Test 62 | @DisplayName("can be disabled") 63 | void disabled() { 64 | environment.setProperty("org.springframework.cloud.bindings.boot.kafka.enable", "false"); 65 | 66 | new KafkaBindingsPropertiesProcessor().process(environment, bindings, properties); 67 | 68 | assertThat(properties).isEmpty(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/RabbitMqBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.RabbitMqBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("RabbitMQ BindingsPropertiesProcessor") 33 | final class RabbitMqBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("addresses", "test-addresses") 40 | .withEntry("host", "test-host") 41 | .withEntry("password", "test-password") 42 | .withEntry("port", "test-port") 43 | .withEntry("username", "test-username") 44 | .withEntry("virtual-host", "test-virtual-host") 45 | ) 46 | ); 47 | 48 | private final MockEnvironment environment = new MockEnvironment(); 49 | 50 | private final HashMap properties = new HashMap<>(); 51 | 52 | @Test 53 | @DisplayName("contributes properties") 54 | void test() { 55 | new RabbitMqBindingsPropertiesProcessor().process(environment, bindings, properties); 56 | assertThat(properties) 57 | .containsEntry("spring.rabbitmq.addresses", "test-addresses") 58 | .containsEntry("spring.rabbitmq.host", "test-host") 59 | .containsEntry("spring.rabbitmq.password", "test-password") 60 | .containsEntry("spring.rabbitmq.port", "test-port") 61 | .containsEntry("spring.rabbitmq.username", "test-username") 62 | .containsEntry("spring.rabbitmq.virtual-host", "test-virtual-host"); 63 | } 64 | 65 | @Test 66 | @DisplayName("can be disabled") 67 | void disabled() { 68 | environment.setProperty("org.springframework.cloud.bindings.boot.rabbitmq.enable", "false"); 69 | 70 | new RabbitMqBindingsPropertiesProcessor().process(environment, bindings, properties); 71 | 72 | assertThat(properties).isEmpty(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | org.springframework.cloud 8 | spring-cloud-bindings-parent 9 | 2.0.4-SNAPSHOT 10 | pom 11 | 12 | Spring Cloud Cloud Native Buildpacks Bindings Parent 13 | Java Library and Auto-configuration for Cloud Native Buildpack Bindings 14 | https://github.com/spring-cloud/spring-cloud-bindings 15 | 16 | 17 | UTF-8 18 | UTF-8 19 | 17 20 | ${java.version} 21 | ${java.version} 22 | 3.1.0 23 | 3.1.0 24 | 3.1.1 25 | 26 | 27 | 28 | 29 | Apache License, Version 2.0 30 | https://www.apache.org/licenses/LICENSE-2.0.txt 31 | 32 | 33 | 34 | 35 | spring-cloud-bindings 36 | spring-cloud-bindings-tests 37 | 38 | 39 | 40 | 41 | 42 | org.apache.maven.plugins 43 | maven-gpg-plugin 44 | ${maven-gpg-plugin.version} 45 | 46 | 47 | sign-artifacts 48 | verify 49 | 50 | sign 51 | 52 | 53 | 54 | --pinentry-mode 55 | loopback 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-deploy-plugin 64 | ${maven-deploy-plugin.version} 65 | 66 | 67 | 68 | 69 | 70 | https://github.com/spring-cloud/spring-cloud-bindings 71 | 72 | 73 | 74 | 75 | scb-team 76 | Spring Cloud Bindings Team 77 | https://github.com/spring-cloud/spring-cloud-bindings/graphs/contributors 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/ArtemisBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | */ 30 | public final class ArtemisBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 31 | 32 | /** 33 | * The {@link Binding} type that this processor is interested in: {@value}. 34 | **/ 35 | public static final String TYPE = "artemis"; 36 | 37 | @Override 38 | public void process(Environment environment, Bindings bindings, Map properties) { 39 | if (!isTypeEnabled(environment, TYPE)) { 40 | return; 41 | } 42 | 43 | bindings.filterBindings(TYPE).forEach(binding -> { 44 | MapMapper map = new MapMapper(binding.getSecret(), properties); 45 | map.from("broker-url").to("spring.artemis.broker-url"); 46 | 47 | map.from("pool.block-if-full").to("spring.artemis.pool.block-if-full"); 48 | map.from("pool.block-if-full-timeout").to("spring.artemis.pool.block-if-full-timeout"); 49 | map.from("pool.enabled").to("spring.artemis.pool.enabled"); 50 | map.from("pool.idle-timeout").to("spring.artemis.pool.idle-timeout"); 51 | map.from("pool.max-connections").to("spring.artemis.pool.max-connections"); 52 | map.from("pool.max-sessions-per-connection").to("spring.artemis.pool.max-sessions-per-connection"); 53 | map.from("pool.time-between-expiration-check").to("spring.artemis.pool.time-between-expiration-check"); 54 | map.from("pool.use-anonymous-producers").to("spring.artemis.pool.use-anonymous-producers"); 55 | 56 | map.from("mode").to("spring.artemis.mode"); 57 | map.from("password").to("spring.artemis.password"); 58 | map.from("user").to("spring.artemis.user"); 59 | 60 | map.from("embedded.cluster-password").to("spring.artemis.embedded.cluster-password"); 61 | map.from("embedded.data-directory").to("spring.artemis.embedded.data-directory"); 62 | map.from("embedded.enabled").to("spring.artemis.embedded.enabled"); 63 | map.from("embedded.persistent").to("spring.artemis.embedded.persistent"); 64 | map.from("embedded.queues").to("spring.artemis.embedded.queues"); 65 | map.from("embedded.server-id").to("spring.artemis.embedded.server-id"); 66 | map.from("embedded.topics").to("spring.artemis.embedded.topics"); 67 | }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/pem/PemCertificateParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.security.cert.CertificateException; 21 | import java.security.cert.CertificateFactory; 22 | import java.security.cert.X509Certificate; 23 | import java.util.ArrayList; 24 | import java.util.Base64; 25 | import java.util.List; 26 | import java.util.function.Consumer; 27 | import java.util.regex.Matcher; 28 | import java.util.regex.Pattern; 29 | 30 | /** 31 | * Parser for X.509 certificates in PEM format. 32 | * 33 | * @author Scott Frederick 34 | * @author Phillip Webb 35 | */ 36 | final class PemCertificateParser { 37 | 38 | private static final String HEADER = "-+BEGIN\\s+.*CERTIFICATE[^-]*-+(?:\\s|\\r|\\n)+"; 39 | 40 | private static final String BASE64_TEXT = "([a-z0-9+/=\\r\\n]+)"; 41 | 42 | private static final String FOOTER = "-+END\\s+.*CERTIFICATE[^-]*-+"; 43 | 44 | private static final Pattern PATTERN = Pattern.compile(HEADER + BASE64_TEXT + FOOTER, Pattern.CASE_INSENSITIVE); 45 | 46 | private PemCertificateParser() { 47 | } 48 | 49 | /** 50 | * Parse certificates from the specified string. 51 | * @param certificates the certificates to parse 52 | * @return the parsed certificates 53 | */ 54 | static X509Certificate[] parse(String certificates) { 55 | if (certificates == null) { 56 | return null; 57 | } 58 | CertificateFactory factory = getCertificateFactory(); 59 | List certs = new ArrayList<>(); 60 | readCertificates(certificates, factory, certs::add); 61 | return (!certs.isEmpty()) ? certs.stream().toArray(X509Certificate[]::new) : null; 62 | } 63 | 64 | private static CertificateFactory getCertificateFactory() { 65 | try { 66 | return CertificateFactory.getInstance("X.509"); 67 | } 68 | catch (CertificateException ex) { 69 | throw new IllegalStateException("Unable to get X.509 certificate factory", ex); 70 | } 71 | } 72 | 73 | private static void readCertificates(String text, CertificateFactory factory, Consumer consumer) { 74 | try { 75 | Matcher matcher = PATTERN.matcher(text); 76 | while (matcher.find()) { 77 | String encodedText = matcher.group(1); 78 | byte[] decodedBytes = decodeBase64(encodedText); 79 | ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedBytes); 80 | while (inputStream.available() > 0) { 81 | consumer.accept((X509Certificate) factory.generateCertificate(inputStream)); 82 | } 83 | } 84 | } 85 | catch (CertificateException ex) { 86 | throw new IllegalStateException("Error reading certificate: " + ex.getMessage(), ex); 87 | } 88 | } 89 | 90 | private static byte[] decodeBase64(String content) { 91 | byte[] bytes = content.replaceAll("\r", "").replaceAll("\n", "").getBytes(); 92 | return Base64.getDecoder().decode(bytes); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/pem/PemContentTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStreamReader; 21 | import java.io.Reader; 22 | import java.nio.charset.StandardCharsets; 23 | 24 | import org.junit.jupiter.api.Test; 25 | 26 | import org.springframework.core.io.ClassPathResource; 27 | import org.springframework.util.FileCopyUtils; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | 31 | /** 32 | * Tests for {@link PemContent}. 33 | * 34 | * @author Phillip Webb 35 | */ 36 | class PemContentTests { 37 | 38 | @Test 39 | void loadWhenContentIsNullReturnsNull() { 40 | assertThat(PemContent.load(null)).isNull(); 41 | } 42 | 43 | @Test 44 | void loadWhenContentIsPemContentReturnsContent() { 45 | String content = "-----BEGIN CERTIFICATE-----\n" + 46 | "MIICpDCCAYwCCQCDOqHKPjAhCTANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls\n" + 47 | "b2NhbGhvc3QwHhcNMTQwOTEwMjE0MzA1WhcNMTQxMDEwMjE0MzA1WjAUMRIwEAYD\n" + 48 | "VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR\n" + 49 | "0KfxUw7MF/8RB5/YXOM7yLnoHYb/M/6dyoulMbtEdKKhQhU28o5FiDkHcEG9PJQL\n" + 50 | "gqrRgAjl3VmCC9omtfZJQ2EpfkTttkJjnKOOroXhYE51/CYSckapBYCVh8GkjUEJ\n" + 51 | "uEfnp07cTfYZFqViIgIWPZyjkzl3w4girS7kCuzNdDntVJVx5F/EsFwMA8n3C0Qa\n" + 52 | "zHQoM5s00Fer6aTwd6AW0JD5QkADavpfzZ554e4HrVGwHlM28WKQQkFzzGu44FFX\n" + 53 | "yVuEF3HeyVPug8GRHAc8UU7ijVgJB5TmbvRGYowIErD5i4VvGLuOv9mgR3aVyN0S\n" + 54 | "dJ1N7aJnXpeSQjAgf03jAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAE4yvwhbPldg\n" + 55 | "Bpl7sBw/m2B3bfiNeSqa4tII1PQ7ysgWVb9HbFNKkriScwDWlqo6ljZfJ+SDFCoj\n" + 56 | "bQz4fOFdMAOzRnpTrG2NAKMoJLY0/g/p7XO00PiC8T3h3BOJ5SHuW3gUyfGXmAYs\n" + 57 | "DnJxJOrwPzj57xvNXjNSbDOJ3DRfCbB0CWBexOeGDiUokoEq3Gnz04Q4ZfHyAcpZ\n" + 58 | "3deMw8Od5p9WAoCh3oClpFyOSzXYKZd+3ppMMtfc4wnbfocnfSFxj0UCpOEJw4Ez\n" + 59 | "+lGuHKdhNOVW9CmqPD1y76o6c8PQKuF7KZEoY2jvy3GeIfddBvqXgZ4PbWvFz1jO\n" + 60 | "32C9XWHwRA4=\n" + 61 | "-----END CERTIFICATE-----"; 62 | assertThat(PemContent.load(content)).isEqualTo(content); 63 | } 64 | 65 | @Test 66 | void loadWhenClasspathLocationReturnsContent() throws IOException { 67 | String actual = PemContent.load("classpath:pem/test-cert.pem"); 68 | String expected = asString(new ClassPathResource("pem/test-cert.pem")); 69 | assertThat(actual).isEqualTo(expected); 70 | } 71 | 72 | @Test 73 | void loadWhenFileLocationReturnsContent() throws IOException { 74 | String actual = PemContent.load("src/test/resources/pem/test-cert.pem"); 75 | String expected = asString(new ClassPathResource("pem/test-cert.pem")); 76 | assertThat(actual).isEqualTo(expected); 77 | } 78 | 79 | public static String asString(ClassPathResource resource) throws IOException { 80 | Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8); 81 | return FileCopyUtils.copyToString(reader); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/MongoDbBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.MongoDbBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("MongoDB BindingsPropertiesProcessor") 33 | final class MongoDbBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("authentication-database", "test-authentication-database") 40 | .withEntry("database", "test-database") 41 | .withEntry("grid-fs-database", "test-grid-fs-database") 42 | .withEntry("host", "test-host") 43 | .withEntry("password", "test-password") 44 | .withEntry("port", "test-port") 45 | .withEntry("uri", "test-uri") 46 | .withEntry("username", "test-username") 47 | ) 48 | ); 49 | 50 | private final MockEnvironment environment = new MockEnvironment(); 51 | 52 | private final HashMap properties = new HashMap<>(); 53 | 54 | @Test 55 | @DisplayName("contributes properties") 56 | void test() { 57 | new MongoDbBindingsPropertiesProcessor().process(environment, bindings, properties); 58 | assertThat(properties) 59 | .containsEntry("spring.data.mongodb.authentication-database", "test-authentication-database") 60 | .containsEntry("spring.data.mongodb.database", "test-database") 61 | .containsEntry("spring.data.mongodb.gridfs.database", "test-grid-fs-database") 62 | .containsEntry("spring.data.mongodb.host", "test-host") 63 | .containsEntry("spring.data.mongodb.password", "test-password") 64 | .containsEntry("spring.data.mongodb.port", "test-port") 65 | .containsEntry("spring.data.mongodb.uri", "test-uri") 66 | .containsEntry("spring.data.mongodb.username", "test-username"); 67 | } 68 | 69 | @Test 70 | @DisplayName("can be disabled") 71 | void disabled() { 72 | environment.setProperty("org.springframework.cloud.bindings.boot.mongodb.enable", "false"); 73 | 74 | new MongoDbBindingsPropertiesProcessor().process(environment, bindings, properties); 75 | 76 | assertThat(properties).isEmpty(); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/BindingFlattenedEnvironmentPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import org.springframework.boot.SpringApplication; 23 | import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor; 24 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 25 | import org.springframework.boot.env.EnvironmentPostProcessor; 26 | import org.springframework.boot.logging.DeferredLog; 27 | import org.springframework.cloud.bindings.Bindings; 28 | import org.springframework.context.ApplicationListener; 29 | import org.springframework.core.Ordered; 30 | import org.springframework.core.env.ConfigurableEnvironment; 31 | 32 | import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource; 33 | 34 | /** 35 | * An implementation of {@link EnvironmentPostProcessor} that generates properties from {@link Bindings} with a 36 | * flattened format: {@code k8s.bindings.{name}.*}. 37 | */ 38 | public final class BindingFlattenedEnvironmentPostProcessor implements ApplicationListener, 39 | EnvironmentPostProcessor, Ordered { 40 | 41 | public static final String BINDING_FLATTENED_PROPERTY_SOURCE_NAME = "kubernetesServiceBindingFlattened"; 42 | 43 | private final DeferredLog log = new DeferredLog(); 44 | 45 | private final Bindings bindings; 46 | 47 | /** 48 | * Creates a new instance of {@code BindingFlattenedEnvironmentPostProcessor} using the {@link Bindings} available 49 | * in the environment. 50 | */ 51 | public BindingFlattenedEnvironmentPostProcessor() { 52 | this(new Bindings()); 53 | } 54 | 55 | BindingFlattenedEnvironmentPostProcessor(Bindings bindings) { 56 | this.bindings = bindings; 57 | } 58 | 59 | @Override 60 | public int getOrder() { 61 | // Before ConfigFileApplicationListener so values there can use values from {@link Bindings}. 62 | return ConfigDataEnvironmentPostProcessor.ORDER - 1; 63 | } 64 | 65 | @Override 66 | public void onApplicationEvent(ApplicationPreparedEvent event) { 67 | this.log.replayTo(getClass()); 68 | } 69 | 70 | @Override 71 | public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { 72 | Map properties = new HashMap<>(); 73 | bindings.getBindings().forEach(binding -> { 74 | binding.getSecret().forEach((key, value) -> { 75 | properties.put(String.format("k8s.bindings.%s.%s", binding.getName(), key), value); 76 | }); 77 | }); 78 | 79 | if (properties.isEmpty()) { 80 | log.debug("No properties set from Kubernetes Service Bindings. Skipping PropertySource creation."); 81 | return; 82 | } 83 | 84 | log.info("Creating flattened PropertySource from Kubernetes Service Bindings"); 85 | contributePropertySource(BINDING_FLATTENED_PROPERTY_SOURCE_NAME, properties, environment); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/BindingFlattenedEnvironmentPostProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import java.nio.file.Paths; 20 | 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.SpringApplication; 24 | import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor; 25 | import org.springframework.cloud.bindings.Binding; 26 | import org.springframework.cloud.bindings.Bindings; 27 | import org.springframework.cloud.bindings.FluentMap; 28 | import org.springframework.mock.env.MockEnvironment; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @DisplayName("Binding-flattened EnvironmentPostProcessor") 33 | final class BindingFlattenedEnvironmentPostProcessorTest { 34 | 35 | private final SpringApplication application = new SpringApplication(); 36 | 37 | private final MockEnvironment environment = new MockEnvironment() 38 | .withProperty("org.springframework.cloud.bindings.boot.enable", "true"); 39 | 40 | @Test 41 | @DisplayName("is disabled by default") 42 | void disabledByDefault() { 43 | new BindingFlattenedEnvironmentPostProcessor( 44 | new Bindings( 45 | new Binding("test-name", Paths.get("test-path"), 46 | new FluentMap() 47 | .withEntry(Binding.TYPE, "test-type") 48 | ) 49 | ) 50 | ).postProcessEnvironment(new MockEnvironment(), application); 51 | 52 | assertThat(environment.getPropertySources()).hasSize(1); 53 | } 54 | 55 | 56 | @Test 57 | @DisplayName("does not create PropertySource if no bindings") 58 | void noBindings() { 59 | new BindingFlattenedEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application); 60 | 61 | assertThat(environment.getPropertySources()).hasSize(1); 62 | } 63 | 64 | @Test 65 | @DisplayName("creates PropertySource with properties") 66 | void containsProperties() { 67 | new BindingFlattenedEnvironmentPostProcessor( 68 | new Bindings( 69 | new Binding("test-name", Paths.get("test-path"), 70 | new FluentMap() 71 | .withEntry(Binding.TYPE, "test-type") 72 | .withEntry("test-secret-key", "test-secret-value") 73 | ) 74 | ) 75 | ).postProcessEnvironment(environment, application); 76 | 77 | assertThat(environment.getPropertySources()).hasSize(2); 78 | assertThat(environment.getProperty("k8s.bindings.test-name.test-secret-key")).isEqualTo("test-secret-value"); 79 | } 80 | 81 | @Test 82 | @DisplayName("has order before ConfigFileApplicationListener") 83 | void order() { 84 | assertThat(new BindingFlattenedEnvironmentPostProcessor(new Bindings()).getOrder()) 85 | .isLessThan(ConfigDataEnvironmentPostProcessor.ORDER); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/RedisBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.RedisBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Redis BindingsPropertiesProcessor") 33 | final class RedisBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("client-name", "test-client-name") 40 | .withEntry("cluster.max-redirects", "test-cluster-max-redirects") 41 | .withEntry("cluster.nodes", "test-cluster-nodes") 42 | .withEntry("database", "test-database") 43 | .withEntry("host", "test-host") 44 | .withEntry("password", "test-password") 45 | .withEntry("port", "test-port") 46 | .withEntry("sentinel.master", "test-sentinel-master") 47 | .withEntry("sentinel.nodes", "test-sentinel-nodes") 48 | .withEntry("ssl", "test-ssl") 49 | .withEntry("url", "test-url") 50 | ) 51 | ); 52 | 53 | private final MockEnvironment environment = new MockEnvironment(); 54 | 55 | private final HashMap properties = new HashMap<>(); 56 | 57 | @Test 58 | @DisplayName("contributes properties") 59 | void testSb3() { 60 | new RedisBindingsPropertiesProcessor().process(environment, bindings, properties); 61 | 62 | assertThat(properties) 63 | .containsEntry("spring.data.redis.client-name", "test-client-name") 64 | .containsEntry("spring.data.redis.cluster.max-redirects", "test-cluster-max-redirects") 65 | .containsEntry("spring.data.redis.cluster.nodes", "test-cluster-nodes") 66 | .containsEntry("spring.data.redis.database", "test-database") 67 | .containsEntry("spring.data.redis.host", "test-host") 68 | .containsEntry("spring.data.redis.password", "test-password") 69 | .containsEntry("spring.data.redis.port", "test-port") 70 | .containsEntry("spring.data.redis.sentinel.master", "test-sentinel-master") 71 | .containsEntry("spring.data.redis.sentinel.nodes", "test-sentinel-nodes") 72 | .containsEntry("spring.data.redis.ssl", "test-ssl") 73 | .containsEntry("spring.data.redis.url", "test-url"); 74 | } 75 | 76 | @Test 77 | @DisplayName("can be disabled") 78 | void disabled() { 79 | environment.setProperty("org.springframework.cloud.bindings.boot.redis.enable", "false"); 80 | 81 | new RedisBindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties).isEmpty(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/ConfigServerBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.cloud.bindings.boot.pem.PemSslStoreHelper; 22 | import org.springframework.core.env.Environment; 23 | import org.springframework.util.StringUtils; 24 | 25 | import java.nio.file.Path; 26 | import java.util.Map; 27 | 28 | 29 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 30 | 31 | /** 32 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 33 | */ 34 | final class ConfigServerBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 35 | /** 36 | * The {@link Binding} type that this processor is interested in: {@value}. 37 | **/ 38 | public static final String TYPE = "config"; 39 | 40 | @Override 41 | public void process(Environment environment, Bindings bindings, Map properties) { 42 | if (!isTypeEnabled(environment, TYPE)) { 43 | return; 44 | } 45 | 46 | bindings.filterBindings(TYPE).forEach(binding -> { 47 | Map secret = binding.getSecret(); 48 | MapMapper map = new MapMapper(secret, properties); 49 | map.from("uri").to("spring.cloud.config.uri"); 50 | map.from("client-id").to("spring.cloud.config.client.oauth2.clientId"); 51 | map.from("client-secret").to("spring.cloud.config.client.oauth2.clientSecret"); 52 | map.from("access-token-uri").to("spring.cloud.config.client.oauth2.accessTokenUri"); 53 | 54 | // When tls.crt and tls.key are set, enable mTLS for config client. 55 | String clientKey = secret.get("tls.key"); 56 | String clientCert = secret.get("tls.crt"); 57 | if (StringUtils.hasText(clientCert) != StringUtils.hasText(clientKey)) { 58 | throw new IllegalArgumentException("binding secret error: tls.key and tls.crt must both be set if either is set"); 59 | } 60 | 61 | if (clientKey != null && !clientKey.isEmpty()) { 62 | String generatedPassword = PemSslStoreHelper.generatePassword(); 63 | 64 | // Create a keystore 65 | Path keyFilePath = PemSslStoreHelper.createKeyStoreFile("config-keystore", generatedPassword, clientCert, clientKey, "config"); 66 | 67 | properties.put("spring.cloud.config.tls.enabled", true); 68 | properties.put("spring.cloud.config.tls.key-alias", "config"); 69 | properties.put("spring.cloud.config.tls.key-store", "file:" + keyFilePath); 70 | properties.put("spring.cloud.config.tls.key-store-type", PemSslStoreHelper.PKCS12_STORY_TYPE); 71 | properties.put("spring.cloud.config.tls.key-store-password", generatedPassword); 72 | properties.put("spring.cloud.config.tls.key-password", ""); 73 | 74 | String caCert = secret.get("ca.crt"); 75 | if (caCert != null && !caCert.isEmpty()) { 76 | // Create a truststore from the CA cert 77 | Path trustFilePath = PemSslStoreHelper.createKeyStoreFile("config-truststore", generatedPassword, caCert, null, "ca"); 78 | properties.put("spring.cloud.config.tls.trust-store", "file:" + trustFilePath); 79 | properties.put("spring.cloud.config.tls.trust-store-type", PemSslStoreHelper.PKCS12_STORY_TYPE); 80 | properties.put("spring.cloud.config.tls.trust-store-password", generatedPassword); 81 | } 82 | } 83 | }); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/CassandraBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.CassandraBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Cassandra BindingsPropertiesProcessor") 33 | final class CassandraBindingsPropertiesProcessorTest { 34 | 35 | private final Bindings bindings = new Bindings( 36 | new Binding("test-name", Paths.get("test-path"), 37 | new FluentMap() 38 | .withEntry(Binding.TYPE, TYPE) 39 | .withEntry("cluster-name", "test-cluster-name") 40 | .withEntry("compression", "test-compression") 41 | .withEntry("contact-points", "test-contact-points") 42 | .withEntry("keyspace-name", "test-keyspace-name") 43 | .withEntry("password", "test-password") 44 | .withEntry("port", "test-port") 45 | .withEntry("ssl", "test-ssl") 46 | .withEntry("username", "test-username") 47 | .withEntry("request.throttler.drain-interval", "test-drain-interval") 48 | .withEntry("request.throttler.max-concurrent-requests", "test-max-concurrent-requests") 49 | .withEntry("request.throttler.max-queue-size", "test-max-queue-size") 50 | .withEntry("request.throttler.max-requests-per-second", "test-max-requests-per-second") 51 | ) 52 | ); 53 | 54 | private final MockEnvironment environment = new MockEnvironment(); 55 | 56 | private final HashMap properties = new HashMap<>(); 57 | 58 | @Test 59 | @DisplayName("contributes properties") 60 | void testSb3() { 61 | new CassandraBindingsPropertiesProcessor().process(environment, bindings, properties); 62 | assertThat(properties) 63 | .containsEntry("spring.cassandra.cluster-name", "test-cluster-name") 64 | .containsEntry("spring.cassandra.compression", "test-compression") 65 | .containsEntry("spring.cassandra.contact-points", "test-contact-points") 66 | .containsEntry("spring.cassandra.keyspace-name", "test-keyspace-name") 67 | .containsEntry("spring.cassandra.password", "test-password") 68 | .containsEntry("spring.cassandra.port", "test-port") 69 | .containsEntry("spring.cassandra.ssl", "test-ssl") 70 | .containsEntry("spring.cassandra.username", "test-username") 71 | .containsEntry("spring.cassandra.request.throttler.drain-interval", "test-drain-interval") 72 | .containsEntry("spring.cassandra.request.throttler.max-concurrent-requests", "test-max-concurrent-requests") 73 | .containsEntry("spring.cassandra.request.throttler.max-queue-size", "test-max-queue-size") 74 | .containsEntry("spring.cassandra.request.throttler.max-requests-per-second", "test-max-requests-per-second"); 75 | } 76 | 77 | @Test 78 | @DisplayName("can be disabled") 79 | void disabled() { 80 | environment.setProperty("org.springframework.cloud.bindings.boot.cassandra.enable", "false"); 81 | 82 | new CassandraBindingsPropertiesProcessor().process(environment, bindings, properties); 83 | assertThat(properties).isEmpty(); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/BindingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.cloud.bindings; 17 | 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Nested; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import java.io.IOException; 24 | import java.nio.file.Files; 25 | import java.nio.file.Path; 26 | import java.nio.file.Paths; 27 | 28 | import static org.assertj.core.api.Assertions.assertThat; 29 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 30 | 31 | @DisplayName("Binding") 32 | final class BindingTest { 33 | 34 | @Test 35 | @DisplayName("fails to create invalid binding") 36 | void testInvalid() throws IOException { 37 | Path path = Files.createTempDirectory("invalid-binding"); 38 | 39 | assertThatIllegalArgumentException().isThrownBy(() -> new Binding(path)); 40 | } 41 | 42 | @Nested 43 | @DisplayName("CNB Bindings") 44 | final class CNBBindings { 45 | 46 | private final Path root = Paths.get("src/test/resources/cnb"); 47 | 48 | @Test 49 | @DisplayName("populates content from filesystem") 50 | void test() { 51 | Binding binding = new Binding(root.resolve("test-name-1")); 52 | 53 | assertThat(binding.getType()).isEqualTo("test-kind-1"); 54 | assertThat(binding.getProvider()).isEqualTo("test-provider-1"); 55 | assertThat(binding.getSecretFilePath("test-metadata-key")) 56 | .isEqualTo(root.resolve("test-name-1/metadata/test-metadata-key")); 57 | assertThat(binding.getSecretFilePath("test-secret-key")) 58 | .isEqualTo(root.resolve("test-name-1/secret/test-secret-key")); 59 | } 60 | 61 | @Test 62 | @DisplayName("populates k8s style content from filesystem") 63 | void testK8s() { 64 | //When bindings are provided as a k8s configmap secret pairs data files will be symlinks to hidden directories 65 | Binding binding = new Binding(root.resolve("test-k8s")); 66 | 67 | assertThat(binding.getType()).isEqualTo("test-kind-1"); 68 | assertThat(binding.getProvider()).isEqualTo("test-provider-1"); 69 | assertThat(binding.getSecretFilePath("test-metadata-key")) 70 | .isEqualTo(root.resolve("test-k8s/metadata/test-metadata-key")); 71 | assertThat(binding.getSecretFilePath("test-secret-key")) 72 | .isEqualTo(root.resolve("test-k8s/secret/test-secret-key")); 73 | } 74 | } 75 | 76 | @Nested 77 | @DisplayName("Kubernetes Bindings") 78 | final class KubernetesBindings { 79 | 80 | private final Path root = Paths.get("src/test/resources/k8s"); 81 | 82 | @Test 83 | @DisplayName("populates content from filesystem") 84 | void test() { 85 | Binding binding = new Binding(root.resolve("test-name-1")); 86 | 87 | assertThat(binding.getType()).isEqualTo("test-type-1"); 88 | assertThat(binding.getProvider()).isEqualTo("test-provider-1"); 89 | assertThat(binding.getSecretFilePath("test-secret-key")) 90 | .isEqualTo(root.resolve("test-name-1/test-secret-key")); 91 | } 92 | 93 | @Test 94 | @DisplayName("populates k8s style content from filesystem") 95 | void testK8s() { 96 | //When bindings are provided as a k8s configmap secret pairs data files will be symlinks to hidden directories 97 | Binding binding = new Binding(root.resolve("test-k8s")); 98 | 99 | assertThat(binding.getType()).isEqualTo("test-type-1"); 100 | assertThat(binding.getProvider()).isEqualTo("test-provider-1"); 101 | assertThat(binding.getSecretFilePath("test-secret-key")) 102 | .isEqualTo(root.resolve("test-k8s/test-secret-key")); 103 | } 104 | 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/MapMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import java.util.Arrays; 20 | import java.util.Map; 21 | import java.util.function.Function; 22 | import java.util.function.Predicate; 23 | 24 | final class MapMapper { 25 | 26 | private final Map source; 27 | 28 | private final Map destination; 29 | 30 | MapMapper(Map source, Map destination) { 31 | this.source = source; 32 | this.destination = destination; 33 | } 34 | 35 | Source from(String... keys) { 36 | return new SourceImpl(keys); 37 | } 38 | 39 | interface TriFunction { 40 | R apply(T t, U u, V v); 41 | } 42 | 43 | interface Source { 44 | void to(String key); 45 | 46 | void toIfAbsent(String key); 47 | 48 | void to(String key, Function function); 49 | 50 | void to(String key, TriFunction function); 51 | 52 | Source when(Predicate predicate); 53 | 54 | } 55 | 56 | final class SourceImpl implements Source { 57 | 58 | private final String[] keys; 59 | 60 | private SourceImpl(String[] keys) { 61 | this.keys = keys; 62 | } 63 | 64 | @Override 65 | public void to(String key) { 66 | to(key, v -> v); 67 | } 68 | 69 | @Override 70 | public void toIfAbsent(String key) { 71 | if (destination.containsKey(key)) { 72 | return; 73 | } 74 | to(key, v -> v); 75 | } 76 | 77 | @Override 78 | public void to(String key, Function function) { 79 | if (keys.length != 1) { 80 | throw new IllegalStateException( 81 | String.format("source size %d cannot be transformed as one argument", keys.length)); 82 | } 83 | 84 | if (!Arrays.stream(keys).allMatch(source::containsKey)) { 85 | return; 86 | } 87 | 88 | destination.put(key, function.apply(source.get(keys[0]))); 89 | } 90 | 91 | @Override 92 | public void to(String key, TriFunction function) { 93 | if (keys.length != 3) { 94 | throw new IllegalStateException( 95 | String.format("source size %d cannot be consumed as three arguments", keys.length)); 96 | } 97 | 98 | if (!Arrays.stream(keys).allMatch(source::containsKey)) { 99 | return; 100 | } 101 | 102 | destination.put(key, function.apply(source.get(keys[0]), source.get(keys[1]), source.get(keys[2]))); 103 | } 104 | 105 | @Override 106 | public Source when(Predicate predicate) { 107 | if (keys.length != 1) { 108 | throw new IllegalStateException( 109 | String.format("source size %d cannot be transformed as one argument", keys.length)); 110 | } 111 | 112 | if (predicate.test(source.get(keys[0]))) { 113 | return this; 114 | } else { 115 | return new NoopSource(); 116 | } 117 | } 118 | } 119 | 120 | final static class NoopSource implements Source { 121 | 122 | @Override 123 | public void to(String key) { 124 | 125 | } 126 | 127 | @Override 128 | public void toIfAbsent(String key) { 129 | 130 | } 131 | 132 | @Override 133 | public void to(String key, Function function) { 134 | 135 | } 136 | 137 | @Override 138 | public void to(String key, TriFunction function) { 139 | 140 | } 141 | 142 | @Override 143 | public Source when(Predicate predicate) { 144 | return this; 145 | } 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/BindingSpecificEnvironmentPostProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.boot.SpringApplication; 22 | import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor; 23 | import org.springframework.cloud.bindings.Binding; 24 | import org.springframework.cloud.bindings.Bindings; 25 | import org.springframework.cloud.bindings.FluentMap; 26 | import org.springframework.mock.env.MockEnvironment; 27 | 28 | import java.nio.file.Paths; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @DisplayName("Binding-specific EnvironmentPostProcessor") 33 | final class BindingSpecificEnvironmentPostProcessorTest { 34 | 35 | private final SpringApplication application = new SpringApplication(); 36 | 37 | private final MockEnvironment environment = new MockEnvironment() 38 | .withProperty("org.springframework.cloud.bindings.boot.enable", "true"); 39 | 40 | @Test 41 | @DisplayName("is disabled by default") 42 | void disabledByDefault() { 43 | new BindingSpecificEnvironmentPostProcessor( 44 | new Bindings( 45 | new Binding("test-name", Paths.get("test-path"), 46 | new FluentMap() 47 | .withEntry(Binding.TYPE, "test-type") 48 | ) 49 | ), 50 | (environment, bindings, properties) -> properties.put("test-key", "test-value") 51 | ).postProcessEnvironment(new MockEnvironment(), application); 52 | 53 | assertThat(environment.getPropertySources()).hasSize(1); 54 | } 55 | 56 | 57 | @Test 58 | @DisplayName("does not create PropertySource if no bindings") 59 | void noBindings() { 60 | new BindingSpecificEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application); 61 | 62 | assertThat(environment.getPropertySources()).hasSize(1); 63 | } 64 | 65 | @Test 66 | @DisplayName("does not create PropertySource if no properties") 67 | void noProperties() { 68 | new BindingSpecificEnvironmentPostProcessor( 69 | new Bindings( 70 | new Binding("test-name", Paths.get("test-path"), 71 | new FluentMap() 72 | .withEntry(Binding.TYPE, "test-type") 73 | ) 74 | ) 75 | ).postProcessEnvironment(environment, application); 76 | 77 | assertThat(environment.getPropertySources()).hasSize(1); 78 | } 79 | 80 | @Test 81 | @DisplayName("creates PropertySource with properties") 82 | void containsProperties() { 83 | new BindingSpecificEnvironmentPostProcessor( 84 | new Bindings( 85 | new Binding("test-name", Paths.get("test-path"), 86 | new FluentMap() 87 | .withEntry(Binding.TYPE, "test-type") 88 | ) 89 | ), 90 | (environment, bindings, properties) -> properties.put("test-key", "test-value") 91 | ).postProcessEnvironment(environment, application); 92 | 93 | assertThat(environment.getPropertySources()).hasSize(2); 94 | assertThat(environment.getProperty("test-key")).isEqualTo("test-value"); 95 | } 96 | 97 | @Test 98 | @DisplayName("has order before ConfigFileApplicationListener") 99 | void order() { 100 | assertThat(new BindingSpecificEnvironmentPostProcessor(new Bindings()).getOrder()) 101 | .isLessThan(ConfigDataEnvironmentPostProcessor.ORDER); 102 | } 103 | 104 | @Test 105 | @DisplayName("included implementations are registered") 106 | void includedImplementations() { 107 | assertThat(new BindingSpecificEnvironmentPostProcessor().processors).hasSize(21); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.cloud.bindings.Binding; 20 | import org.springframework.cloud.bindings.Bindings; 21 | import org.springframework.core.env.Environment; 22 | 23 | import java.util.Map; 24 | 25 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 26 | 27 | /** 28 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 29 | * 30 | * @see JDBC URL Format 31 | */ 32 | public final class MySqlBindingsPropertiesProcessor implements BindingsPropertiesProcessor { 33 | 34 | /** 35 | * The {@link Binding} type that this processor is interested in: {@value}. 36 | **/ 37 | public static final String TYPE = "mysql"; 38 | 39 | /** 40 | * MySQL connection protocol constant. 41 | */ 42 | private static final String MYSQL_PROTOCOL = "mysql"; 43 | 44 | /** 45 | * MariaDB connection protocol constant. 46 | */ 47 | private static final String MARIADB_PROTOCOL = "mariadb"; 48 | 49 | @Override 50 | public void process(Environment environment, Bindings bindings, Map properties) { 51 | if (!isTypeEnabled(environment, TYPE)) { 52 | return; 53 | } 54 | 55 | bindings.filterBindings(TYPE).forEach(binding -> { 56 | MapMapper map = new MapMapper(binding.getSecret(), properties); 57 | 58 | //jdbc properties 59 | map.from("username").to("spring.datasource.username"); 60 | map.from("password").to("spring.datasource.password"); 61 | map.from("host", "port", "database").to("spring.datasource.url", 62 | (host, port, database) -> String.format("jdbc:%s://%s:%s/%s", evalProtocol(), host, port, database)); 63 | 64 | // jdbcURL takes precedence 65 | map.from("jdbc-url").to("spring.datasource.url"); 66 | 67 | try { 68 | Class.forName("org.mariadb.jdbc.Driver", false, getClass().getClassLoader()); 69 | properties.put("spring.datasource.driver-class-name", "org.mariadb.jdbc.Driver"); 70 | } catch (ClassNotFoundException e) { 71 | try { 72 | Class.forName("com.mysql.cj.jdbc.Driver", false, getClass().getClassLoader()); 73 | properties.put("spring.datasource.driver-class-name", "com.mysql.cj.jdbc.Driver"); 74 | } catch (ClassNotFoundException ignored) { 75 | } 76 | } 77 | 78 | //r2dbc properties 79 | map.from("password").to("spring.r2dbc.password"); 80 | map.from("host", "port", "database").to("spring.r2dbc.url", 81 | (host, port, database) -> String.format("r2dbc:%s://%s:%s/%s", evalProtocol(), host, port, database)); 82 | map.from("username").to("spring.r2dbc.username"); 83 | 84 | // r2dbcURL takes precedence 85 | map.from("r2dbc-url").to("spring.r2dbc.url"); 86 | }); 87 | } 88 | 89 | private String evalProtocol() 90 | { 91 | // Default to "mysql" 92 | String connectionProtocol = MYSQL_PROTOCOL; 93 | 94 | /* Starting with Spring Boot 2.7.0, the previous MySQL r2dbc driver is no longer supported and 95 | * documentation suggests using the MariaDB R2DBC driver as an alternative. Some versions 96 | * of the MariaDB R2DBC driver do not support "mysql" as part of the connection 97 | * protocol; "mariadb" should be used instead when the MariaDB R2DBC driver class is on 98 | * the classpath. 99 | */ 100 | 101 | try { 102 | Class.forName("org.mariadb.r2dbc.MariadbConnection"); 103 | connectionProtocol = MARIADB_PROTOCOL; 104 | } 105 | catch (ClassNotFoundException ignored) { 106 | } 107 | 108 | return connectionProtocol; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/pem/PemSslStoreHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2023 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot.pem; 18 | 19 | import java.io.FileOutputStream; 20 | import java.io.IOException; 21 | import java.nio.file.Files; 22 | import java.nio.file.Path; 23 | import java.nio.file.Paths; 24 | import java.security.KeyStore; 25 | import java.security.KeyStoreException; 26 | import java.security.NoSuchAlgorithmException; 27 | import java.security.PrivateKey; 28 | import java.security.cert.CertificateException; 29 | import java.security.cert.X509Certificate; 30 | import java.util.Random; 31 | 32 | import org.springframework.util.Assert; 33 | 34 | /** 35 | * helper for creating stores from PEM-encoded certificates and private keys. 36 | */ 37 | public class PemSslStoreHelper { 38 | public static final String PKCS12_STORY_TYPE = "PKCS12"; 39 | private static final String DEFAULT_KEY_ALIAS = "ssl"; 40 | 41 | /** 42 | * Utility method to create a KeyStore and save it in the tmp directory with give name. 43 | * @param name the store file name 44 | * @param password the store password 45 | * @param certificate the certificate to add to the store 46 | * @param privateKey the private key to add to the store 47 | * @param keyAlias the alias 48 | * @return the path which store file is saved 49 | */ 50 | public static Path createKeyStoreFile(String name, String password, String certificate, String privateKey, String keyAlias) { 51 | KeyStore store = createKeyStore(certificate, privateKey, keyAlias); 52 | 53 | Path path; 54 | try { 55 | path = Files.createTempFile(Paths.get(System.getProperty("java.io.tmpdir")), name, ".p12"); 56 | } catch (IOException e) { 57 | throw new IllegalStateException("Unable to create " + name, e); 58 | } 59 | 60 | try (FileOutputStream fos = new FileOutputStream(path.toString())) { 61 | store.store(fos, password.toCharArray()); 62 | } catch (KeyStoreException e) { 63 | throw new IllegalStateException("Unable to write " + name, e); 64 | } catch (NoSuchAlgorithmException e) { 65 | throw new IllegalStateException("Cryptographic algorithm not available", e); 66 | } catch (CertificateException e) { 67 | throw new IllegalStateException("Unable to process certificate", e); 68 | } catch (IOException e) { 69 | throw new IllegalStateException("Unable to create " + name, e); 70 | } 71 | return path; 72 | } 73 | 74 | /** 75 | * Generates a password to use for KeyStore and/or TrustStore 76 | * @return the password 77 | */ 78 | public static String generatePassword() { 79 | return new Random().ints(97 /* letter a */, 122 /* letter z */ + 1) 80 | .limit(10) 81 | .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) 82 | .toString(); 83 | } 84 | 85 | private static KeyStore createKeyStore(String certificate, String privateKey, String keyAlias) { 86 | try { 87 | Assert.notNull(certificate, "CertificateContent must not be null"); 88 | KeyStore store = KeyStore.getInstance(PKCS12_STORY_TYPE); 89 | store.load(null); 90 | String certificateContent = PemContent.load(certificate); 91 | String privateKeyContent = PemContent.load(privateKey); 92 | X509Certificate[] certificates = PemCertificateParser.parse(certificateContent); 93 | PrivateKey pk = PemPrivateKeyParser.parse(privateKeyContent); 94 | addCertificates(store, certificates, pk, keyAlias); 95 | return store; 96 | } 97 | catch (Exception ex) { 98 | throw new IllegalStateException(String.format("Unable to create key/trust store: %s", ex.getMessage()), ex); 99 | } 100 | } 101 | 102 | private static void addCertificates(KeyStore keyStore, X509Certificate[] certificates, PrivateKey privateKey, String keyAlias) 103 | throws KeyStoreException { 104 | String alias = (keyAlias != null) ? keyAlias : DEFAULT_KEY_ALIAS; 105 | if (privateKey != null) { 106 | keyStore.setKeyEntry(alias, privateKey, null, certificates); 107 | } 108 | else { 109 | for (int index = 0; index < certificates.length; index++) { 110 | keyStore.setCertificateEntry(alias + "-" + index, certificates[index]); 111 | } 112 | } 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/BindingSpecificEnvironmentPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import java.util.Arrays; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.springframework.boot.SpringApplication; 25 | import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor; 26 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 27 | import org.springframework.boot.env.EnvironmentPostProcessor; 28 | import org.springframework.boot.logging.DeferredLog; 29 | import org.springframework.cloud.bindings.Bindings; 30 | import org.springframework.context.ApplicationListener; 31 | import org.springframework.core.Ordered; 32 | import org.springframework.core.env.ConfigurableEnvironment; 33 | import org.springframework.core.env.PropertySource; 34 | import org.springframework.core.io.support.SpringFactoriesLoader; 35 | 36 | 37 | import static org.springframework.cloud.bindings.boot.Guards.isGlobalEnabled; 38 | import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource; 39 | 40 | /** 41 | * An implementation of {@link EnvironmentPostProcessor} that delegates properties generation from {@link Bindings}. 42 | * This implementation generates a single instance of {@code Bindings} and then calls all implementations of 43 | * {@link BindingsPropertiesProcessor} registered with {@link SpringFactoriesLoader} allowing them to generate any 44 | * properties from the contents of the {@code Bindings}. 45 | *

46 | * Must be enabled by setting the {@code org.springframework.cloud.bindings.boot.enable} System Property to 47 | * {@code true}. 48 | */ 49 | public final class BindingSpecificEnvironmentPostProcessor implements ApplicationListener, 50 | EnvironmentPostProcessor, Ordered { 51 | 52 | /** 53 | * The name of the {@link PropertySource} created by the {@code BindingsEnvironmentPostProcessor}: {@value}. 54 | */ 55 | public static final String BINDING_SPECIFIC_PROPERTY_SOURCE_NAME = "kubernetesServiceBindingSpecific"; 56 | 57 | private static final DeferredLog LOG = new DeferredLog(); 58 | 59 | final List processors; 60 | 61 | private final Bindings bindings; 62 | 63 | /** 64 | * Creates a new instance of {@code BindingSpecificEnvironmentPostProcessor} using the {@link Bindings} available in 65 | * the environment and the {@link BindingsPropertiesProcessor}s registered with {@link SpringFactoriesLoader}. 66 | */ 67 | public BindingSpecificEnvironmentPostProcessor() { 68 | this.bindings = new Bindings(); 69 | this.processors = SpringFactoriesLoader. 70 | loadFactories(BindingsPropertiesProcessor.class, getClass().getClassLoader()); 71 | } 72 | 73 | BindingSpecificEnvironmentPostProcessor(Bindings bindings, BindingsPropertiesProcessor... processors) { 74 | this.bindings = bindings; 75 | this.processors = Arrays.asList(processors); 76 | } 77 | 78 | @Override 79 | public int getOrder() { 80 | // Before ConfigFileApplicationListener so values there can use values from {@link Bindings}. 81 | return ConfigDataEnvironmentPostProcessor.ORDER - 1; 82 | } 83 | 84 | @Override 85 | public void onApplicationEvent(ApplicationPreparedEvent event) { 86 | LOG.replayTo(getClass()); 87 | } 88 | 89 | @Override 90 | public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { 91 | if (!isGlobalEnabled(environment)) { 92 | return; 93 | } 94 | 95 | if (bindings.getBindings().isEmpty()) { 96 | LOG.debug("No Kubernetes Service Bindings found. Skipping Environment post-processing."); 97 | return; 98 | } 99 | 100 | Map properties = new HashMap<>(); 101 | processors.forEach(processor -> processor.process(environment, bindings, properties)); 102 | if (properties.isEmpty()) { 103 | LOG.debug("No properties set from Kubernetes Service Bindings. Skipping PropertySource creation."); 104 | return; 105 | } 106 | 107 | LOG.info("Creating binding-specific PropertySource from Kubernetes Service Bindings"); 108 | contributePropertySource(BINDING_SPECIFIC_PROPERTY_SOURCE_NAME, properties, environment); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/Db2BindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.Db2BindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("DB2 BindingsPropertiesProcessor") 33 | final class Db2BindingsPropertiesProcessorTest { 34 | 35 | private final FluentMap secret = new FluentMap() 36 | .withEntry(Binding.TYPE, TYPE) 37 | .withEntry("database", "test-database") 38 | .withEntry("host", "test-host") 39 | .withEntry("password", "test-password") 40 | .withEntry("port", "test-port") 41 | .withEntry("username", "test-username"); 42 | 43 | private final MockEnvironment environment = new MockEnvironment(); 44 | 45 | private final HashMap properties = new HashMap<>(); 46 | 47 | @Test 48 | @DisplayName("composes jdbc url from host port and database") 49 | void testJdbc() { 50 | Bindings bindings = new Bindings( 51 | new Binding("test-name", Paths.get("test-path"), secret) 52 | ); 53 | new Db2BindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.datasource.driver-class-name", "com.ibm.db2.jcc.DB2Driver") 56 | .containsEntry("spring.datasource.password", "test-password") 57 | .containsEntry("spring.datasource.url", "jdbc:db2://test-host:test-port/test-database") 58 | .containsEntry("spring.datasource.username", "test-username"); 59 | } 60 | 61 | @Test 62 | @DisplayName("gives precedence to jdbc-url") 63 | void testJdbcURL() { 64 | Bindings bindings = new Bindings( 65 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("jdbc-url", "test-jdbc-url")) 66 | ); 67 | new Db2BindingsPropertiesProcessor().process(environment, bindings, properties); 68 | assertThat(properties) 69 | .containsEntry("spring.datasource.driver-class-name", "com.ibm.db2.jcc.DB2Driver") 70 | .containsEntry("spring.datasource.password", "test-password") 71 | .containsEntry("spring.datasource.url", "test-jdbc-url") 72 | .containsEntry("spring.datasource.username", "test-username"); 73 | } 74 | 75 | @Test 76 | @DisplayName("contributes r2dbc properties") 77 | void testR2dbc() { 78 | Bindings bindings = new Bindings( 79 | new Binding("test-name", Paths.get("test-path"), secret) 80 | ); 81 | new Db2BindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties) 83 | .containsEntry("spring.r2dbc.password", "test-password") 84 | .containsEntry("spring.r2dbc.url", "r2dbc:db2://test-host:test-port/test-database") 85 | .containsEntry("spring.r2dbc.username", "test-username"); 86 | } 87 | 88 | @Test 89 | @DisplayName("gives precedence to r2dbc-url") 90 | void testR2dbcURL() { 91 | Bindings bindings = new Bindings( 92 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("r2dbc-url", "test-r2dbc-url")) 93 | ); 94 | new Db2BindingsPropertiesProcessor().process(environment, bindings, properties); 95 | assertThat(properties) 96 | .containsEntry("spring.r2dbc.password", "test-password") 97 | .containsEntry("spring.r2dbc.url", "test-r2dbc-url") 98 | .containsEntry("spring.r2dbc.username", "test-username"); 99 | } 100 | 101 | @Test 102 | @DisplayName("can be disabled") 103 | void disabled() { 104 | Bindings bindings = new Bindings( 105 | new Binding("test-name", Paths.get("test-path"), secret) 106 | ); 107 | environment.setProperty("org.springframework.cloud.bindings.boot.db2.enable", "false"); 108 | 109 | new Db2BindingsPropertiesProcessor().process(environment, bindings, properties); 110 | 111 | assertThat(properties).isEmpty(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/MySqlBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.MySqlBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("MySQL BindingsPropertiesProcessor") 33 | final class MySqlBindingsPropertiesProcessorTest { 34 | 35 | private final FluentMap secret = new FluentMap() 36 | .withEntry(Binding.TYPE, TYPE) 37 | .withEntry("database", "test-database") 38 | .withEntry("host", "test-host") 39 | .withEntry("password", "test-password") 40 | .withEntry("port", "test-port") 41 | .withEntry("username", "test-username"); 42 | 43 | private final MockEnvironment environment = new MockEnvironment(); 44 | 45 | private final HashMap properties = new HashMap<>(); 46 | 47 | @Test 48 | @DisplayName("composes jdbc url from host port and database") 49 | void testJdbc() { 50 | Bindings bindings = new Bindings( 51 | new Binding("test-name", Paths.get("test-path"), secret) 52 | ); 53 | new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.datasource.driver-class-name", "org.mariadb.jdbc.Driver") 56 | .containsEntry("spring.datasource.password", "test-password") 57 | .containsEntry("spring.datasource.url", "jdbc:mariadb://test-host:test-port/test-database") 58 | .containsEntry("spring.datasource.username", "test-username"); 59 | } 60 | 61 | @Test 62 | @DisplayName("gives precedence to jdbc-url") 63 | void testJdbcURL() { 64 | Bindings bindings = new Bindings( 65 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("jdbc-url", "test-jdbc-url")) 66 | ); 67 | new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); 68 | assertThat(properties) 69 | .containsEntry("spring.datasource.driver-class-name", "org.mariadb.jdbc.Driver") 70 | .containsEntry("spring.datasource.password", "test-password") 71 | .containsEntry("spring.datasource.url", "test-jdbc-url") 72 | .containsEntry("spring.datasource.username", "test-username"); 73 | } 74 | 75 | @Test 76 | @DisplayName("composes r2dbc url from host port and database") 77 | void testR2dbc() { 78 | Bindings bindings = new Bindings( 79 | new Binding("test-name", Paths.get("test-path"), secret) 80 | ); 81 | new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties) 83 | .containsEntry("spring.r2dbc.password", "test-password") 84 | .containsEntry("spring.r2dbc.url", "r2dbc:mariadb://test-host:test-port/test-database") 85 | .containsEntry("spring.r2dbc.username", "test-username"); 86 | } 87 | 88 | @Test 89 | @DisplayName("gives precedence to r2dbc-url") 90 | void testR2dbcURL() { 91 | Bindings bindings = new Bindings( 92 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("r2dbc-url", "test-r2dbc-url")) 93 | ); 94 | new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); 95 | assertThat(properties) 96 | .containsEntry("spring.r2dbc.password", "test-password") 97 | .containsEntry("spring.r2dbc.url", "test-r2dbc-url") 98 | .containsEntry("spring.r2dbc.username", "test-username"); 99 | } 100 | 101 | @Test 102 | @DisplayName("can be disabled") 103 | void disabled() { 104 | Bindings bindings = new Bindings( 105 | new Binding("test-name", Paths.get("test-path"), secret) 106 | ); 107 | environment.setProperty("org.springframework.cloud.bindings.boot.mysql.enable", "false"); 108 | 109 | new MySqlBindingsPropertiesProcessor().process(environment, bindings, properties); 110 | 111 | assertThat(properties).isEmpty(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/OracleBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.OracleBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("Oracle BindingsPropertiesProcessor") 33 | final class OracleBindingsPropertiesProcessorTest { 34 | 35 | private final FluentMap secret = new FluentMap() 36 | .withEntry(Binding.TYPE, TYPE) 37 | .withEntry("database", "test-database") 38 | .withEntry("host", "test-host") 39 | .withEntry("password", "test-password") 40 | .withEntry("port", "test-port") 41 | .withEntry("username", "test-username"); 42 | 43 | private final MockEnvironment environment = new MockEnvironment(); 44 | 45 | private final HashMap properties = new HashMap<>(); 46 | 47 | @Test 48 | @DisplayName("composes jdbc url from host port and database") 49 | void testJdbc() { 50 | Bindings bindings = new Bindings( 51 | new Binding("test-name", Paths.get("test-path"), secret) 52 | ); 53 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.datasource.driver-class-name", "oracle.jdbc.OracleDriver") 56 | .containsEntry("spring.datasource.password", "test-password") 57 | .containsEntry("spring.datasource.url", "jdbc:oracle://test-host:test-port/test-database") 58 | .containsEntry("spring.datasource.username", "test-username"); 59 | } 60 | 61 | @Test 62 | @DisplayName("gives precedence to jdbc-url") 63 | void testJdbcURL() { 64 | Bindings bindings = new Bindings( 65 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("jdbc-url", "test-jdbc-url")) 66 | ); 67 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 68 | assertThat(properties) 69 | .containsEntry("spring.datasource.driver-class-name", "oracle.jdbc.OracleDriver") 70 | .containsEntry("spring.datasource.password", "test-password") 71 | .containsEntry("spring.datasource.url", "test-jdbc-url") 72 | .containsEntry("spring.datasource.username", "test-username"); 73 | } 74 | 75 | @Test 76 | @DisplayName("composes r2dbc url from host port and database") 77 | void testR2dbc() { 78 | Bindings bindings = new Bindings( 79 | new Binding("test-name", Paths.get("test-path"), secret) 80 | ); 81 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties) 83 | .containsEntry("spring.r2dbc.password", "test-password") 84 | .containsEntry("spring.r2dbc.url", "r2dbc:oracle://test-host:test-port/test-database") 85 | .containsEntry("spring.r2dbc.username", "test-username"); 86 | } 87 | 88 | @Test 89 | @DisplayName("gives precedence to r2dbc-url") 90 | void testR2dbcURL() { 91 | Bindings bindings = new Bindings( 92 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("r2dbc-url", "test-r2dbc-url")) 93 | ); 94 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 95 | assertThat(properties) 96 | .containsEntry("spring.r2dbc.password", "test-password") 97 | .containsEntry("spring.r2dbc.url", "test-r2dbc-url") 98 | .containsEntry("spring.r2dbc.username", "test-username"); 99 | } 100 | 101 | @Test 102 | @DisplayName("can be disabled") 103 | void disabled() { 104 | Bindings bindings = new Bindings( 105 | new Binding("test-name", Paths.get("test-path"), secret) 106 | ); 107 | environment.setProperty("org.springframework.cloud.bindings.boot.oracle.enable", "false"); 108 | 109 | new OracleBindingsPropertiesProcessor().process(environment, bindings, properties); 110 | 111 | assertThat(properties).isEmpty(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/SapHanaBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.SapHanaBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("SAP Hana BindingsPropertiesProcessor") 33 | final class SapHanaBindingsPropertiesProcessorTest { 34 | 35 | private final FluentMap secret = new FluentMap() 36 | .withEntry(Binding.TYPE, TYPE) 37 | .withEntry("database", "test-database") 38 | .withEntry("host", "test-host") 39 | .withEntry("password", "test-password") 40 | .withEntry("port", "test-port") 41 | .withEntry("username", "test-username"); 42 | 43 | private final MockEnvironment environment = new MockEnvironment(); 44 | 45 | private final HashMap properties = new HashMap<>(); 46 | 47 | @Test 48 | @DisplayName("composes jdbc url from host port and database") 49 | void testJdbc() { 50 | Bindings bindings = new Bindings( 51 | new Binding("test-name", Paths.get("test-path"), secret) 52 | ); 53 | new SapHanaBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.datasource.driver-class-name", "com.sap.db.jdbc.Driver") 56 | .containsEntry("spring.datasource.password", "test-password") 57 | .containsEntry("spring.datasource.url", "jdbc:sap://test-host:test-port/test-database") 58 | .containsEntry("spring.datasource.username", "test-username"); 59 | } 60 | 61 | @Test 62 | @DisplayName("gives precedence to jdbc-url") 63 | void testJdbcURL() { 64 | Bindings bindings = new Bindings( 65 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("jdbc-url", "test-jdbc-url")) 66 | ); 67 | new SapHanaBindingsPropertiesProcessor().process(environment, bindings, properties); 68 | assertThat(properties) 69 | .containsEntry("spring.datasource.driver-class-name", "com.sap.db.jdbc.Driver") 70 | .containsEntry("spring.datasource.password", "test-password") 71 | .containsEntry("spring.datasource.url", "test-jdbc-url") 72 | .containsEntry("spring.datasource.username", "test-username"); 73 | } 74 | 75 | @Test 76 | @DisplayName("composes r2dbc url from host port and database") 77 | void testR2dbc() { 78 | Bindings bindings = new Bindings( 79 | new Binding("test-name", Paths.get("test-path"), secret) 80 | ); 81 | new SapHanaBindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties) 83 | .containsEntry("spring.r2dbc.password", "test-password") 84 | .containsEntry("spring.r2dbc.url", "r2dbc:sap://test-host:test-port/test-database") 85 | .containsEntry("spring.r2dbc.username", "test-username"); 86 | } 87 | 88 | @Test 89 | @DisplayName("gives precedence to r2dbc-url") 90 | void testR2dbcURL() { 91 | Bindings bindings = new Bindings( 92 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("r2dbc-url", "test-r2dbc-url")) 93 | ); 94 | new SapHanaBindingsPropertiesProcessor().process(environment, bindings, properties); 95 | assertThat(properties) 96 | .containsEntry("spring.r2dbc.password", "test-password") 97 | .containsEntry("spring.r2dbc.url", "test-r2dbc-url") 98 | .containsEntry("spring.r2dbc.username", "test-username"); 99 | } 100 | 101 | @Test 102 | @DisplayName("can be disabled") 103 | void disabled() { 104 | Bindings bindings = new Bindings( 105 | new Binding("test-name", Paths.get("test-path"), secret) 106 | ); 107 | environment.setProperty("org.springframework.cloud.bindings.boot.hana.enable", "false"); 108 | 109 | new SapHanaBindingsPropertiesProcessor().process(environment, bindings, properties); 110 | 111 | assertThat(properties).isEmpty(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/test/java/org/springframework/cloud/bindings/boot/SqlServerBindingsPropertiesProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.junit.jupiter.api.DisplayName; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.cloud.bindings.FluentMap; 24 | import org.springframework.mock.env.MockEnvironment; 25 | 26 | import java.nio.file.Paths; 27 | import java.util.HashMap; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.springframework.cloud.bindings.boot.SqlServerBindingsPropertiesProcessor.TYPE; 31 | 32 | @DisplayName("SQLServer BindingsPropertiesProcessor") 33 | final class SqlServerBindingsPropertiesProcessorTest { 34 | 35 | private final FluentMap secret = new FluentMap() 36 | .withEntry(Binding.TYPE, TYPE) 37 | .withEntry("database", "test-database") 38 | .withEntry("host", "test-host") 39 | .withEntry("password", "test-password") 40 | .withEntry("port", "test-port") 41 | .withEntry("username", "test-username"); 42 | 43 | private final MockEnvironment environment = new MockEnvironment(); 44 | 45 | private final HashMap properties = new HashMap<>(); 46 | 47 | @Test 48 | @DisplayName("composes jdbc url from host port and database") 49 | void testJdbc() { 50 | Bindings bindings = new Bindings( 51 | new Binding("test-name", Paths.get("test-path"), secret) 52 | ); 53 | new SqlServerBindingsPropertiesProcessor().process(environment, bindings, properties); 54 | assertThat(properties) 55 | .containsEntry("spring.datasource.driver-class-name", "com.microsoft.sqlserver.jdbc.SQLServerDriver") 56 | .containsEntry("spring.datasource.password", "test-password") 57 | .containsEntry("spring.datasource.url", "jdbc:sqlserver://test-host:test-port/test-database") 58 | .containsEntry("spring.datasource.username", "test-username"); 59 | } 60 | 61 | @Test 62 | @DisplayName("gives precedence to jdbc-url") 63 | void testJdbcURL() { 64 | Bindings bindings = new Bindings( 65 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("jdbc-url", "test-jdbc-url")) 66 | ); 67 | new SqlServerBindingsPropertiesProcessor().process(environment, bindings, properties); 68 | assertThat(properties) 69 | .containsEntry("spring.datasource.driver-class-name", "com.microsoft.sqlserver.jdbc.SQLServerDriver") 70 | .containsEntry("spring.datasource.password", "test-password") 71 | .containsEntry("spring.datasource.url", "test-jdbc-url") 72 | .containsEntry("spring.datasource.username", "test-username"); 73 | } 74 | 75 | @Test 76 | @DisplayName("composes r2dbc url from host port and database") 77 | void testR2dbc() { 78 | Bindings bindings = new Bindings( 79 | new Binding("test-name", Paths.get("test-path"), secret) 80 | ); 81 | new SqlServerBindingsPropertiesProcessor().process(environment, bindings, properties); 82 | assertThat(properties) 83 | .containsEntry("spring.r2dbc.password", "test-password") 84 | .containsEntry("spring.r2dbc.url", "r2dbc:sqlserver://test-host:test-port/test-database") 85 | .containsEntry("spring.r2dbc.username", "test-username"); 86 | } 87 | 88 | @Test 89 | @DisplayName("gives precedence to r2dbc-url") 90 | void testR2dbcURL() { 91 | Bindings bindings = new Bindings( 92 | new Binding("test-name", Paths.get("test-path"), secret.withEntry("r2dbc-url", "test-r2dbc-url")) 93 | ); 94 | new SqlServerBindingsPropertiesProcessor().process(environment, bindings, properties); 95 | assertThat(properties) 96 | .containsEntry("spring.r2dbc.password", "test-password") 97 | .containsEntry("spring.r2dbc.url", "test-r2dbc-url") 98 | .containsEntry("spring.r2dbc.username", "test-username"); 99 | } 100 | 101 | @Test 102 | @DisplayName("can be disabled") 103 | void disabled() { 104 | Bindings bindings = new Bindings( 105 | new Binding("test-name", Paths.get("test-path"), secret) 106 | ); 107 | environment.setProperty("org.springframework.cloud.bindings.boot.sqlserver.enable", "false"); 108 | 109 | new SqlServerBindingsPropertiesProcessor().process(environment, bindings, properties); 110 | 111 | assertThat(properties).isEmpty(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /spring-cloud-bindings/src/main/java/org/springframework/cloud/bindings/boot/SpringSecurityOAuth2BindingsPropertiesProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.cloud.bindings.boot; 18 | 19 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 20 | import org.springframework.boot.logging.DeferredLog; 21 | import org.springframework.cloud.bindings.Binding; 22 | import org.springframework.cloud.bindings.Bindings; 23 | import org.springframework.context.ApplicationListener; 24 | import org.springframework.core.env.Environment; 25 | 26 | import java.util.*; 27 | 28 | import javax.annotation.Nullable; 29 | 30 | import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled; 31 | 32 | /** 33 | * An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}. 34 | */ 35 | public final class SpringSecurityOAuth2BindingsPropertiesProcessor implements BindingsPropertiesProcessor, ApplicationListener { 36 | 37 | /** 38 | * The {@link Binding} type that this processor is interested in: {@value}. 39 | **/ 40 | public static final String TYPE = "oauth2"; 41 | 42 | private static final DeferredLog LOG = new DeferredLog(); 43 | 44 | @Override 45 | public void process(Environment environment, Bindings bindings, Map properties) { 46 | if (!isTypeEnabled(environment, TYPE)) { 47 | return; 48 | } 49 | 50 | bindings.filterBindings(TYPE).forEach(binding -> { 51 | MapMapper map = new MapMapper(binding.getSecret(), properties); 52 | String provider = binding.getProvider(); 53 | if (provider == null) { 54 | LOG.warn(String.format("Binding '%s' is missing required 'provider' and will not be processed.", binding.getName())); 55 | return; 56 | } 57 | String clientName = binding.getName(); 58 | properties.put(String.format("spring.security.oauth2.client.registration.%s.provider", clientName), provider); 59 | map.from("client-id").to(String.format("spring.security.oauth2.client.registration.%s.client-id", clientName)); 60 | map.from("client-secret").to(String.format("spring.security.oauth2.client.registration.%s.client-secret", clientName)); 61 | map.from("client-authentication-method").to(String.format("spring.security.oauth2.client.registration.%s.client-authentication-method", clientName)); 62 | map.from("authorization-grant-type").to(String.format("spring.security.oauth2.client.registration.%s.authorization-grant-type", clientName)); 63 | map.from("authorization-grant-types") 64 | .when(SpringSecurityOAuth2BindingsPropertiesProcessor::hasSingleValue) 65 | .toIfAbsent(String.format("spring.security.oauth2.client.registration.%s.authorization-grant-type", clientName)); 66 | map.from("redirect-uri").to(String.format("spring.security.oauth2.client.registration.%s.redirect-uri", clientName)); 67 | map.from("redirect-uris") 68 | .when(SpringSecurityOAuth2BindingsPropertiesProcessor::hasSingleValue) 69 | .toIfAbsent(String.format("spring.security.oauth2.client.registration.%s.redirect-uri", clientName)); 70 | map.from("scope").to(String.format("spring.security.oauth2.client.registration.%s.scope", clientName)); 71 | map.from("client-name").to(String.format("spring.security.oauth2.client.registration.%s.client-name", clientName)); 72 | map.from("issuer-uri").to(String.format("spring.security.oauth2.client.provider.%s.issuer-uri", provider)); 73 | map.from("authorization-uri").to(String.format("spring.security.oauth2.client.provider.%s.authorization-uri", provider)); 74 | map.from("token-uri").to(String.format("spring.security.oauth2.client.provider.%s.token-uri", provider)); 75 | map.from("user-info-uri").to(String.format("spring.security.oauth2.client.provider.%s.user-info-uri", provider)); 76 | map.from("user-info-authentication-method").to(String.format("spring.security.oauth2.client.provider.%s.user-info-authentication-method", provider)); 77 | map.from("jwk-set-uri").to(String.format("spring.security.oauth2.client.provider.%s.jwk-set-uri", provider)); 78 | map.from("user-name-attribute").to(String.format("spring.security.oauth2.client.provider.%s.user-name-attribute", provider)); 79 | }); 80 | } 81 | 82 | private static boolean hasSingleValue(@Nullable Object value) { 83 | return Optional.ofNullable(value) 84 | .filter(String.class::isInstance) 85 | .map(String.class::cast) 86 | .map(s -> s.split(",")) 87 | .filter(r -> r.length == 1) 88 | .isPresent(); 89 | } 90 | 91 | @Override 92 | public void onApplicationEvent(ApplicationPreparedEvent event) { 93 | LOG.replayTo(getClass()); 94 | } 95 | } 96 | --------------------------------------------------------------------------------