From 0446b8f096229baf368911c227f9f6c6e2281a3a Mon Sep 17 00:00:00 2001 From: Daniel Lavoie Date: Fri, 3 Nov 2017 08:02:00 -0400 Subject: [PATCH] Support Spring Boot autoconfiguration - Added spring-credhub-starter project - Updated demo app with spring-credhub-starter [Closes #23] --- build.gradle | 1 + settings.gradle | 2 + ...InterpolationServiceDataPostProcessor.java | 48 ++++++++++----- .../configuration/CredHubTemplateFactory.java | 56 +++++++++++++++++ .../credhub/core/CredHubProperties.java | 38 +++++++----- .../credhub/core/CredHubTemplate.java | 2 - spring-credhub-demo/build.gradle | 2 +- spring-credhub-starter/build.gradle | 31 ++++++++++ .../autoconfig/CredHubAutoConfiguration.java | 61 ++++++++----------- .../credhub/autoconfig/package-info.java | 14 ++--- .../main/resources/META-INF/spring.factories | 2 + .../CredHubAutoConfigurationTest.java | 28 +++++++++ 12 files changed, 205 insertions(+), 80 deletions(-) create mode 100644 spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubTemplateFactory.java create mode 100644 spring-credhub-starter/build.gradle rename spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubConfiguration.java => spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/CredHubAutoConfiguration.java (70%) rename spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoConfiguration.java => spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/package-info.java (65%) create mode 100644 spring-credhub-starter/src/main/resources/META-INF/spring.factories create mode 100644 spring-credhub-starter/src/test/java/org/springframework/credhub/configuration/CredHubAutoConfigurationTest.java diff --git a/build.gradle b/build.gradle index 6bc96b7..282422d 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ buildscript { ext { springVersion = "4.3.8.RELEASE" + springBootVersion = "1.5.6.RELEASE" junitVersion = "4.12" mockitoVersion = "2.7.22" diff --git a/settings.gradle b/settings.gradle index 67652f2..c696461 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,8 @@ rootProject.name = 'spring-credhub' include ':spring-credhub-core' include ':spring-credhub-cloud-connector' +include ':spring-credhub-starter' project(':spring-credhub-core').projectDir = "$rootDir/spring-credhub-core" as File project(':spring-credhub-cloud-connector').projectDir = "$rootDir/spring-credhub-cloud-connector" as File +project(':spring-credhub-starter').projectDir = "$rootDir/spring-credhub-starter" as File diff --git a/spring-credhub-cloud-connector/src/main/java/org/springframework/credhub/cloud/CredHubInterpolationServiceDataPostProcessor.java b/spring-credhub-cloud-connector/src/main/java/org/springframework/credhub/cloud/CredHubInterpolationServiceDataPostProcessor.java index 121764a..5820efe 100644 --- a/spring-credhub-cloud-connector/src/main/java/org/springframework/credhub/cloud/CredHubInterpolationServiceDataPostProcessor.java +++ b/spring-credhub-cloud-connector/src/main/java/org/springframework/credhub/cloud/CredHubInterpolationServiceDataPostProcessor.java @@ -21,8 +21,9 @@ import java.util.logging.Logger; import org.springframework.cloud.cloudfoundry.CloudFoundryRawServiceData; import org.springframework.cloud.cloudfoundry.ServiceDataPostProcessor; -import org.springframework.credhub.configuration.CredHubConfiguration; +import org.springframework.credhub.configuration.CredHubTemplateFactory; import org.springframework.credhub.core.CredHubOperations; +import org.springframework.credhub.core.CredHubProperties; import org.springframework.credhub.support.ServicesData; /** @@ -30,8 +31,10 @@ import org.springframework.credhub.support.ServicesData; * data from {@literal VCAP_SERVICES} using the CredHub interpolation API. * * @author Scott Frederick + * @author Daniel Lavoie */ -public class CredHubInterpolationServiceDataPostProcessor implements ServiceDataPostProcessor { +public class CredHubInterpolationServiceDataPostProcessor + implements ServiceDataPostProcessor { private Logger logger = Logger .getLogger(CredHubInterpolationServiceDataPostProcessor.class.getName()); @@ -42,17 +45,31 @@ public class CredHubInterpolationServiceDataPostProcessor implements ServiceData */ public CredHubInterpolationServiceDataPostProcessor() { try { - credHubOperations = new CredHubConfiguration().credHubTemplate(); + CredHubTemplateFactory credHubTemplateFactroy = new CredHubTemplateFactory(); + CredHubProperties credHubProperties = new CredHubProperties(); + + credHubProperties.setUrl(System.getProperty("spring.credhub.url")); + + if (credHubProperties.getUrl() != null + && !credHubProperties.getUrl().isEmpty()) { + credHubOperations = credHubTemplateFactroy.credHubTemplate( + credHubProperties, + credHubTemplateFactroy.clientHttpRequestFactoryWrapper()); + } + else { + logger.log(Level.WARNING, + "System property spring.credhub.url is undefined. CredHubOperations cannot be initialized, disabling processing of service data"); + } } catch (Exception e) { - logger.log(Level.WARNING, "CredHubOperations cannot be initialized, " + - "disabling processing of service data", e); + logger.log(Level.WARNING, "CredHubOperations cannot be initialized, " + + "disabling processing of service data", e); } } /** - * Initialize the service data post-processor using the provided {@link CredHubOperations}. - * Intended for internal use. + * Initialize the service data post-processor using the provided + * {@link CredHubOperations}. Intended for internal use. * * @param credHubOperations the CredHubOperations to use */ @@ -79,15 +96,17 @@ public class CredHubInterpolationServiceDataPostProcessor implements ServiceData .interpolateServiceData(connectorsToCredHub(serviceData)); return credHubToConnectors(interpolatedData); - } catch (Exception e) { - logger.log(Level.WARNING, "Error interpolating service data from CredHub.", e); + } + catch (Exception e) { + logger.log(Level.WARNING, "Error interpolating service data from CredHub.", + e); return serviceData; } } /** - * Convert from the Spring Cloud Connectors service data structure to the Spring Credhub - * data structure. + * Convert from the Spring Cloud Connectors service data structure to the Spring + * Credhub data structure. * * @param rawServiceData the Spring Cloud Connectors data structure * @return the equivalent Spring CredHub data structure @@ -99,13 +118,14 @@ public class CredHubInterpolationServiceDataPostProcessor implements ServiceData } /** - * Convert from the Spring Credhub service data structure to the Spring Cloud Connectors - * data structure. + * Convert from the Spring Credhub service data structure to the Spring Cloud + * Connectors data structure. * * @param interpolatedData the Spring CredHub data structure * @return the equivalent Spring Cloud Connectors data structure */ - private CloudFoundryRawServiceData credHubToConnectors(ServicesData interpolatedData) { + private CloudFoundryRawServiceData credHubToConnectors( + ServicesData interpolatedData) { CloudFoundryRawServiceData rawServicesData = new CloudFoundryRawServiceData(); rawServicesData.putAll(interpolatedData); return rawServicesData; diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubTemplateFactory.java b/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubTemplateFactory.java new file mode 100644 index 0000000..a3de7bb --- /dev/null +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubTemplateFactory.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.credhub.configuration; + +import org.springframework.credhub.core.CredHubProperties; +import org.springframework.credhub.core.CredHubTemplate; +import org.springframework.credhub.support.ClientOptions; +import org.springframework.http.client.ClientHttpRequestFactory; + +/** + * Factory for {@link CredHubTemplate} used to communicate with CredHub. + * + * @author Scott Frederick + * @author Daniel Lavoie + */ +public class CredHubTemplateFactory { + + public CredHubTemplate credHubTemplate(CredHubProperties credHubProperties, + ClientHttpRequestFactory clientHttpRequestFactory) { + return new CredHubTemplate(credHubProperties.getUrl(), clientHttpRequestFactory); + } + + /** + * Create a {@link ClientHttpRequestFactory}. + * + * @return the {@link ClientHttpRequestFactory} instance. + * + * @see #clientOptions() + */ + public ClientHttpRequestFactory clientHttpRequestFactoryWrapper() { + return ClientHttpRequestFactoryFactory.create(clientOptions()); + } + + /** + * Create the default {@link ClientOptions} to configure communication parameters. + * + * @return the default {@link ClientOptions} + */ + private ClientOptions clientOptions() { + return new ClientOptions(); + } +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubProperties.java b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubProperties.java index 6b90761..36d109f 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubProperties.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubProperties.java @@ -18,43 +18,49 @@ package org.springframework.credhub.core; -import org.springframework.beans.factory.annotation.Value; - /** * Properties containing information about a CredHub server. * * @author Scott Frederick + * @author Daniel Lavoie */ public class CredHubProperties { - @Value("${CREDHUB_API}") - private String apiUriBase; + private String url; /** * Create a new instance without initializing properties. */ public CredHubProperties() { - if (apiUriBase == null) { - apiUriBase = System.getenv("CREDHUB_API"); - } + } /** - * Create a new instance with the provided properties. Intended to be used - * internally for testing. + * Create a new instance with the provided properties. Intended to be used internally + * for testing. * - * @param apiUriBase the base URI for the CredHub server + * @param url the base URI for the CredHub server */ - CredHubProperties(String apiUriBase) { - this.apiUriBase = apiUriBase; + CredHubProperties(String url) { + this.url = url; } /** - * Get the base URI for the CredHub server (scheme, host, and port). This value - * will be prepended to all requests to CredHub. + * Get the base URI for the CredHub server (scheme, host, and port). This value will + * be prepended to all requests to CredHub. * * @return the base URI */ - public String getApiUriBase() { - return apiUriBase; + public String getUrl() { + return url; + } + + /** + * Set the base URI for the CredHub server (scheme, host, and port). This value will + * be prepended to all requests to CredHub. + * + * @param url the base URI for the CredHub server + */ + public void setUrl(String url) { + this.url = url; } } diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java index 9770e6e..cffdbd9 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java +++ b/spring-credhub-core/src/main/java/org/springframework/credhub/core/CredHubTemplate.java @@ -97,7 +97,6 @@ public class CredHubTemplate implements CredHubOperations { } @Override - @SuppressWarnings("unchecked") public CredentialDetails write(final CredentialRequest credentialRequest) { Assert.notNull(credentialRequest, "credentialRequest must not be null"); @@ -119,7 +118,6 @@ public class CredHubTemplate implements CredHubOperations { } @Override - @SuppressWarnings("unchecked") public CredentialDetails generate(final ParametersRequest

parametersRequest) { Assert.notNull(parametersRequest, "parametersRequest must not be null"); diff --git a/spring-credhub-demo/build.gradle b/spring-credhub-demo/build.gradle index 502c3c1..fb05777 100644 --- a/spring-credhub-demo/build.gradle +++ b/spring-credhub-demo/build.gradle @@ -44,7 +44,7 @@ apply plugin: 'propdeps-eclipse' apply plugin: 'org.springframework.boot' dependencies { - compile group: 'org.springframework.credhub', name: 'spring-credhub-core', version: '1.0.0.BUILD-SNAPSHOT' + compile group: 'org.springframework.credhub', name: 'spring-credhub-starter', version: '1.0.0.BUILD-SNAPSHOT' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web' compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator' diff --git a/spring-credhub-starter/build.gradle b/spring-credhub-starter/build.gradle new file mode 100644 index 0000000..81d0f93 --- /dev/null +++ b/spring-credhub-starter/build.gradle @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +description = 'Spring CredHub Starter' + +dependencies { + compile project(':spring-credhub-core') + compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: "${springBootVersion}" + + optional(group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3') { + exclude(module: 'commons-logging') + } + optional group: 'com.squareup.okhttp', name: 'okhttp', version: '2.7.5' + optional group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0' + optional group: 'io.netty', name: 'netty-all', version: '4.1.8.Final' + + testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: "${springBootVersion}" +} diff --git a/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubConfiguration.java b/spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/CredHubAutoConfiguration.java similarity index 70% rename from spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubConfiguration.java rename to spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/CredHubAutoConfiguration.java index 57835a2..f4d7ec6 100644 --- a/spring-credhub-core/src/main/java/org/springframework/credhub/configuration/CredHubConfiguration.java +++ b/spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/CredHubAutoConfiguration.java @@ -14,56 +14,53 @@ * limitations under the License. */ -package org.springframework.credhub.configuration; +package org.springframework.credhub.autoconfig; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.credhub.configuration.CredHubTemplateFactory; import org.springframework.credhub.core.CredHubProperties; import org.springframework.credhub.core.CredHubTemplate; import org.springframework.credhub.support.ClientOptions; import org.springframework.http.client.ClientHttpRequestFactory; /** - * Configuration for the {@link CredHubTemplate} used to communicate with CredHub. This - * class is typically imported into Java-based Spring application configuration as in - * this example: - * - *

- * {@code
- * @Configuration
- * @Import(CredHubConfiguration.class)
- * public class MyConfiguration {
- * }
- * }
- * 
- * - * @author Scott Frederick + * {@link EnableAutoConfiguration Auto-configuration} for {@link CredHubTemplate}. + * + * @author Scott Frederick + * @author Daniel Lavoie */ + @Configuration -public class CredHubConfiguration { +@ConditionalOnProperty(value = "spring.credhub.url") +public class CredHubAutoConfiguration { + private final CredHubTemplateFactory credHubTemplateFactory = new CredHubTemplateFactory(); /** - * Create the {@link CredHubProperties} that contains information about the - * CredHub server. - * - * @return the {@link CredHubProperties} bean + * Configuration properties for CredHub + * + * @return a {@link CredHubProperties} bean */ @Bean + @ConfigurationProperties(prefix = "spring.credhub") public CredHubProperties credHubProperties() { return new CredHubProperties(); } /** - * Create the {@link CredHubTemplate} that the application will use to interact - * with CredHub. + * Create the {@link CredHubTemplate} that the application will use to interact with + * CredHub. * * @return the {@link CredHubTemplate} bean */ @Bean public CredHubTemplate credHubTemplate() { - return new CredHubTemplate(credHubProperties().getApiUriBase(), + return credHubTemplateFactory.credHubTemplate(credHubProperties(), clientHttpRequestFactoryWrapper().getClientHttpRequestFactory()); } @@ -71,8 +68,8 @@ public class CredHubConfiguration { * Create a {@link ClientFactoryWrapper} containing a * {@link ClientHttpRequestFactory}. {@link ClientHttpRequestFactory} is not exposed * as root bean because {@link ClientHttpRequestFactory} is configured with - * {@link ClientOptions} which are not necessarily - * applicable for the whole application. + * {@link ClientOptions} which are not necessarily applicable for the whole + * application. * * @return the {@link ClientFactoryWrapper} to wrap a {@link ClientHttpRequestFactory} * instance. @@ -80,18 +77,8 @@ public class CredHubConfiguration { */ @Bean public ClientFactoryWrapper clientHttpRequestFactoryWrapper() { - ClientHttpRequestFactory clientHttpRequestFactory = - ClientHttpRequestFactoryFactory.create(clientOptions()); - return new ClientFactoryWrapper(clientHttpRequestFactory); - } - - /** - * Create the default {@link ClientOptions} to configure communication parameters. - * - * @return the default {@link ClientOptions} - */ - private ClientOptions clientOptions() { - return new ClientOptions(); + return new ClientFactoryWrapper( + credHubTemplateFactory.clientHttpRequestFactoryWrapper()); } /** diff --git a/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoConfiguration.java b/spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/package-info.java similarity index 65% rename from spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoConfiguration.java rename to spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/package-info.java index 91c9ce7..02143de 100644 --- a/spring-credhub-demo/src/main/java/org/springframework/credhub/demo/CredHubDemoConfiguration.java +++ b/spring-credhub-starter/src/main/java/org/springframework/credhub/autoconfig/package-info.java @@ -14,13 +14,7 @@ * limitations under the License. */ -package org.springframework.credhub.demo; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.credhub.configuration.CredHubConfiguration; - -@Configuration -@Import(CredHubConfiguration.class) -public class CredHubDemoConfiguration { -} +/** + * Spring auto configuration support for Spring CredHub. + */ +package org.springframework.credhub.autoconfig; \ No newline at end of file diff --git a/spring-credhub-starter/src/main/resources/META-INF/spring.factories b/spring-credhub-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..2925e54 --- /dev/null +++ b/spring-credhub-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.credhub.autoconfig.CredHubAutoConfiguration \ No newline at end of file diff --git a/spring-credhub-starter/src/test/java/org/springframework/credhub/configuration/CredHubAutoConfigurationTest.java b/spring-credhub-starter/src/test/java/org/springframework/credhub/configuration/CredHubAutoConfigurationTest.java new file mode 100644 index 0000000..454e18a --- /dev/null +++ b/spring-credhub-starter/src/test/java/org/springframework/credhub/configuration/CredHubAutoConfigurationTest.java @@ -0,0 +1,28 @@ +package org.springframework.credhub.configuration; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.credhub.configuration.CredHubAutoConfigurationTest.TestConfig; +import org.springframework.credhub.core.CredHubTemplate; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestConfig.class, value = "spring.credhub.url=http://localhost") +public class CredHubAutoConfigurationTest { + @Autowired + private CredHubTemplate credHubTemplate; + + @Test + public void contextLoads() { + Assert.assertNotNull(credHubTemplate); + } + + @SpringBootApplication + public static class TestConfig { + + } +}