Merge branch '25-global-guard'

Signed-off-by: Ben Hale <bhale@vmware.com>
This commit is contained in:
Ben Hale
2020-05-11 10:42:57 -07:00
15 changed files with 195 additions and 124 deletions

View File

@@ -30,7 +30,7 @@ The more common usage of the library is opt-in automatic Spring Boot configurati
* Adds a `PropertySource` with binding-specific Spring Boot configuration properties.
## Auto-Configurations
Each auto-configuration is triggered by the kind of binding. Each auto-configuration can be disabled using a System Property specific to that kind and defaults to enable.
Each auto-configuration is triggered by the kind of binding. Each auto-configuration can be disabled using a System Property specific to that kind and defaults to enable. Auto-configuration is disabled by default and can be enabled by setting the `org.springframework.cloud.bindings.boot.enable` System Property to `true`.
### Cassandra
Kind: `cassandra`

View File

@@ -36,6 +36,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isGlobalEnabled;
import static org.springframework.core.env.CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
/**
@@ -43,6 +44,8 @@ import static org.springframework.core.env.CommandLinePropertySource.COMMAND_LIN
* This implementation generates a single instance of {@code Bindings} and then calls all implementations of
* {@link BindingsPropertiesProcessor} registered with {@link SpringFactoriesLoader} allowing them to generate any
* properties from the contents of the {@code Bindings}.
* <p>
* Must be enabled by setting the {@code org.springframework.cloud.bindings.boot.enable} System Property to {@code true}.
*/
public final class BindingsEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@@ -79,6 +82,10 @@ public final class BindingsEnvironmentPostProcessor implements EnvironmentPostPr
public void postProcessEnvironment(@NotNull ConfigurableEnvironment environment,
@NotNull SpringApplication application) {
if (!isGlobalEnabled()) {
return;
}
if (bindings.getBindings().isEmpty()) {
log.debug("No CNB Bindings found. Skipping Environment post-processing.");
return;

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -18,7 +18,12 @@ package org.springframework.cloud.bindings.boot;
import org.jetbrains.annotations.NotNull;
final class KindGuard {
final class Guards {
static boolean isGlobalEnabled() {
String value = System.getProperty("org.springframework.cloud.bindings.boot.enable", "false");
return Boolean.parseBoolean(value);
}
static boolean isKindEnabled(@NotNull String kind) {
String property = String.format("org.springframework.cloud.bindings.boot.%s.enable", kind.toLowerCase());

View File

@@ -22,7 +22,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -23,7 +23,7 @@ import org.springframework.lang.NonNull;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.

View File

@@ -31,7 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
final class BindingsTests {
@Nested
@DisplayName("Constructor")
@DisplayName("when constructed")
final class Constructor {
@Test
@@ -71,7 +71,7 @@ final class BindingsTests {
}
@Nested
@DisplayName("Content")
@DisplayName("with content")
final class Content {
private final Bindings bindings = new Bindings(

View File

@@ -17,7 +17,10 @@
package org.springframework.cloud.bindings.boot;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.ClearSystemProperty;
import org.junitpioneer.jupiter.SetSystemProperty;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.cloud.bindings.Binding;
@@ -40,86 +43,108 @@ final class BindingsEnvironmentPostProcessorTest {
private final MockEnvironment environment = new MockEnvironment();
@Test
@DisplayName("does not create PropertySource if no bindings")
void noBindings() {
new BindingsEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application);
assertThat(environment.getPropertySources()).hasSize(1);
}
@Test
@DisplayName("does not create PropertySource if no properties")
void noProperties() {
@DisplayName("is disabled by default")
@ClearSystemProperty(key = "org.springframework.cloud.bindings.boot.enable")
void disabledByDefault() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
)
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
assertThat(environment.getPropertySources()).hasSize(1);
}
@Test
@DisplayName("creates PropertySource with properties")
void containsProperties() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
@Nested
@DisplayName("when enabled")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.enable", value = "true")
final class Enabled {
assertThat(environment.getPropertySources()).hasSize(2);
assertThat(environment.getProperty("test-key")).isEqualTo("test-value");
}
@Test
@DisplayName("does not create PropertySource if no bindings")
void noBindings() {
new BindingsEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application);
@Test
@DisplayName("adds PropertySource after CommandLinePropertySource")
void withCommandLinePropertySource() {
environment.getPropertySources().addFirst(new SimpleCommandLinePropertySource());
assertThat(environment.getPropertySources()).hasSize(1);
}
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
@Test
@DisplayName("does not create PropertySource if no properties")
void noProperties() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
)
).postProcessEnvironment(environment, application);
PropertySource<?> propertySource = environment.getPropertySources().get(BINDINGS_PROPERTY_SOURCE_NAME);
assertThat(propertySource).isNotNull();
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(1);
}
assertThat(environment.getPropertySources()).hasSize(1);
}
@Test
@DisplayName("adds PropertySource first")
void withoutCommandLinePropertySource() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
@Test
@DisplayName("creates PropertySource with properties")
void containsProperties() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
PropertySource<?> propertySource = environment.getPropertySources().get(BINDINGS_PROPERTY_SOURCE_NAME);
assertThat(propertySource).isNotNull();
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(0);
}
assertThat(environment.getPropertySources()).hasSize(2);
assertThat(environment.getProperty("test-key")).isEqualTo("test-value");
}
@Test
@DisplayName("has order before ConfigFileApplicationListener")
void order() {
assertThat(new BindingsEnvironmentPostProcessor(new Bindings()).getOrder())
.isLessThan(ConfigFileApplicationListener.DEFAULT_ORDER);
}
@Test
@DisplayName("adds PropertySource after CommandLinePropertySource")
void withCommandLinePropertySource() {
environment.getPropertySources().addFirst(new SimpleCommandLinePropertySource());
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
PropertySource<?> propertySource = environment.getPropertySources().get(BINDINGS_PROPERTY_SOURCE_NAME);
assertThat(propertySource).isNotNull();
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(1);
}
@Test
@DisplayName("adds PropertySource first")
void withoutCommandLinePropertySource() {
new BindingsEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
),
(environment, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);
PropertySource<?> propertySource = environment.getPropertySources().get(BINDINGS_PROPERTY_SOURCE_NAME);
assertThat(propertySource).isNotNull();
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(0);
}
@Test
@DisplayName("has order before ConfigFileApplicationListener")
void order() {
assertThat(new BindingsEnvironmentPostProcessor(new Bindings()).getOrder())
.isLessThan(ConfigFileApplicationListener.DEFAULT_ORDER);
}
@Test
@DisplayName("included implementations are registered")
void includedImplementations() {
assertThat(new BindingsEnvironmentPostProcessor().processors).hasSize(8);
}
@Test
@DisplayName("included implementations are registered")
void includedImplementations() {
assertThat(new BindingsEnvironmentPostProcessor().processors).hasSize(8);
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2020 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.cloud.bindings.boot;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetSystemProperty;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.Guards.isGlobalEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
@DisplayName("Guards")
final class GuardsTest {
@Nested
@DisplayName("Global Guard")
final class GlobalGuard {
@Test
@DisplayName("returns false if unset")
void unset() {
assertThat(isGlobalEnabled()).isFalse();
}
@Test
@DisplayName("returns the set value of true")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.enable", value = "true")
void setTrue() {
assertThat(isGlobalEnabled()).isTrue();
}
@Test
@DisplayName("returns the set value of false")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.enable", value = "false")
void setFalse() {
assertThat(isGlobalEnabled()).isFalse();
}
}
@Nested
@DisplayName("Kind Guard")
final class KindGuard {
@Test
@DisplayName("returns true if unset")
void unset() {
assertThat(isKindEnabled("Test")).isTrue();
}
@Test
@DisplayName("returns the set value of true")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.test.enable", value = "true")
void setTrue() {
assertThat(isKindEnabled("Test")).isTrue();
}
@Test
@DisplayName("returns the set value of false")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.test.enable", value = "false")
void setFalse() {
assertThat(isKindEnabled("Test")).isFalse();
}
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2020 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.cloud.bindings.boot;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junitpioneer.jupiter.SetSystemProperty;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.KindGuard.isKindEnabled;
@DisplayName("Kind Guard")
final class KindGuardTest {
@Test
@DisplayName("returns true if unset")
void unset() {
assertThat(isKindEnabled("Test")).isTrue();
}
@Test
@DisplayName("returns the set value of true")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.test.enable", value = "true")
void setTrue() {
assertThat(isKindEnabled("Test")).isTrue();
}
@Test
@DisplayName("returns the set value of false")
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.test.enable", value = "false")
void setFalse() {
assertThat(isKindEnabled("Test")).isFalse();
}
}