Merge branch '24-flattened-bindings'
Signed-off-by: Ben Hale <bhale@vmware.com>
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -25,7 +25,7 @@
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<jetbrains-annotations.version>19.0.0</jetbrains-annotations.version>
|
||||
<jsr305.version>3.0.2</jsr305.version>
|
||||
<junit-pioneer.version>0.6.0</junit-pioneer.version>
|
||||
<spring-boot.version>2.2.7.RELEASE</spring-boot.version>
|
||||
|
||||
@@ -54,9 +54,9 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>${jetbrains-annotations.version}</version>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>${jsr305.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.cloud.bindings;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -42,7 +40,7 @@ public final class Binding {
|
||||
/**
|
||||
* Creates a new {@code Binding} instance using the specified file system root.
|
||||
*/
|
||||
public Binding(@NotNull Path path) {
|
||||
public Binding(Path path) {
|
||||
this.name = path.getFileName().toString();
|
||||
this.path = path;
|
||||
this.metadata = createFilePerEntryMap(path.resolve("metadata"));
|
||||
@@ -57,9 +55,7 @@ public final class Binding {
|
||||
* @param metadata the metadata of the {@code Binding}.
|
||||
* @param secret the secret of the {@code Binding}.
|
||||
*/
|
||||
public Binding(@NotNull String name, @NotNull Path path, @NotNull Map<String, String> metadata,
|
||||
@NotNull Map<String, String> secret) {
|
||||
|
||||
public Binding(String name, Path path, Map<String, String> metadata, Map<String, String> secret) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
this.metadata = metadata;
|
||||
@@ -69,42 +65,42 @@ public final class Binding {
|
||||
/**
|
||||
* Returns the name of the binding.
|
||||
*/
|
||||
public @NotNull String getName() {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of the binding.
|
||||
*/
|
||||
public @NotNull Path getPath() {
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata of the binding.
|
||||
*/
|
||||
public @NotNull Map<String, String> getMetadata() {
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the secret of the binding.
|
||||
*/
|
||||
public @NotNull Map<String, String> getSecret() {
|
||||
public Map<String, String> getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind of the binding. Equivalent to {@code getMetadata().get("kind")}.
|
||||
*/
|
||||
public @NotNull String getKind() {
|
||||
public String getKind() {
|
||||
return metadata.get("kind");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider of the binding. Equivalent to {@code getMetadata().get("provider")}.
|
||||
*/
|
||||
public @NotNull String getProvider() {
|
||||
public String getProvider() {
|
||||
return metadata.get("provider");
|
||||
}
|
||||
|
||||
@@ -113,7 +109,7 @@ public final class Binding {
|
||||
*
|
||||
* @param name the name of the metadata key.
|
||||
*/
|
||||
public @NotNull Path getMetadataFilePath(@NotNull String name) {
|
||||
public Path getMetadataFilePath(String name) {
|
||||
return this.path.resolve("metadata").resolve(name);
|
||||
}
|
||||
|
||||
@@ -122,7 +118,7 @@ public final class Binding {
|
||||
*
|
||||
* @param name the name of the secret key.
|
||||
*/
|
||||
public @NotNull Path getSecretFilePath(@NotNull String name) {
|
||||
public Path getSecretFilePath(String name) {
|
||||
return this.path.resolve("secret").resolve(name);
|
||||
}
|
||||
|
||||
@@ -142,7 +138,7 @@ public final class Binding {
|
||||
return Objects.hash(name, path, metadata, secret);
|
||||
}
|
||||
|
||||
private @NotNull Map<String, String> createFilePerEntryMap(@NotNull Path path) {
|
||||
private Map<String, String> createFilePerEntryMap(Path path) {
|
||||
try {
|
||||
return Files.list(path)
|
||||
.collect(Collectors.toMap(
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
*/
|
||||
package org.springframework.cloud.bindings;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -58,7 +56,7 @@ public final class Bindings {
|
||||
*
|
||||
* @param path the path to populate the {@code Bindings} from.
|
||||
*/
|
||||
public Bindings(String path) {
|
||||
public Bindings(@Nullable String path) {
|
||||
if (path == null) {
|
||||
this.bindings = Collections.emptyList();
|
||||
return;
|
||||
@@ -89,14 +87,14 @@ public final class Bindings {
|
||||
*
|
||||
* @param bindings the {@code Binding}s.
|
||||
*/
|
||||
public Bindings(@NotNull Binding... bindings) {
|
||||
public Bindings(Binding... bindings) {
|
||||
this.bindings = Arrays.asList(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the {@link Binding}s that were found during construction.
|
||||
*/
|
||||
public @NotNull List<Binding> getBindings() {
|
||||
public List<Binding> getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@@ -106,14 +104,12 @@ public final class Bindings {
|
||||
* @param name the name of the {@code Binding} to find.
|
||||
* @return the {@code Binding} with a given name if it exists, {@code null} otherwise.
|
||||
*/
|
||||
public @Nullable Binding findBinding(@NotNull String name) {
|
||||
for (Binding binding : bindings) {
|
||||
if (binding.getName().equalsIgnoreCase(name)) {
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@Nullable
|
||||
public Binding findBinding(String name) {
|
||||
return bindings.stream()
|
||||
.filter(binding -> binding.getName().equalsIgnoreCase(name))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +118,7 @@ public final class Bindings {
|
||||
* @param kind the kind of the {@code Binding} to find.
|
||||
* @return the collection of {@code Binding}s with a given kind.
|
||||
*/
|
||||
public @NotNull List<Binding> filterBindings(@Nullable String kind) {
|
||||
public List<Binding> filterBindings(@Nullable String kind) {
|
||||
return filterBindings(kind, null);
|
||||
}
|
||||
|
||||
@@ -134,18 +130,12 @@ public final class Bindings {
|
||||
* @param provider the provider of {@code Binding} to find
|
||||
* @return the collection of {@code Binding}s with a given kind and provider.
|
||||
*/
|
||||
public @NotNull List<Binding> filterBindings(@Nullable String kind, @Nullable String provider) {
|
||||
List<Binding> filtered = new ArrayList<>();
|
||||
|
||||
for (Binding binding : bindings) {
|
||||
if ((kind == null || binding.getKind().equalsIgnoreCase(kind)) &&
|
||||
(provider == null) || binding.getProvider().equalsIgnoreCase(provider)) {
|
||||
|
||||
filtered.add(binding);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
public List<Binding> filterBindings(@Nullable String kind, @Nullable String provider) {
|
||||
return bindings.stream()
|
||||
.filter(binding ->
|
||||
(kind == null || binding.getKind().equalsIgnoreCase(kind)) &&
|
||||
(provider == null) || binding.getProvider().equalsIgnoreCase(provider))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource;
|
||||
|
||||
/**
|
||||
* An implementation of {@link EnvironmentPostProcessor} that generates properties from {@link Bindings} with a
|
||||
* flattened format: {@code cnb.bindings.{name}.{metadata,secret}.*}.
|
||||
*/
|
||||
public final class BindingFlattenedEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
public static final String BINDING_FLATTENED_PROPERTY_SOURCE_NAME = "cnbBindingFlattened";
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private final Bindings bindings;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code BindingFlattenedEnvironmentPostProcessor} using the {@link Bindings} available
|
||||
* in the environment.
|
||||
*/
|
||||
public BindingFlattenedEnvironmentPostProcessor() {
|
||||
this(new Bindings());
|
||||
}
|
||||
|
||||
BindingFlattenedEnvironmentPostProcessor(Bindings bindings) {
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
bindings.getBindings().forEach(binding -> {
|
||||
binding.getMetadata().forEach((key, value) -> {
|
||||
properties.put(String.format("cnb.bindings.%s.metadata.%s", binding.getName(), key), value);
|
||||
});
|
||||
binding.getSecret().forEach((key, value) -> {
|
||||
properties.put(String.format("cnb.bindings.%s.secret.%s", binding.getName(), key), value);
|
||||
});
|
||||
});
|
||||
|
||||
if (properties.isEmpty()) {
|
||||
log.debug("No properties set from CNB Bindings. Skipping PropertySource creation.");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Creating flattened PropertySource from CNB Bindings");
|
||||
contributePropertySource(BINDING_FLATTENED_PROPERTY_SOURCE_NAME, properties, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
// Before ConfigFileApplicationListener so values there can use values from {@link Bindings}.
|
||||
return ConfigFileApplicationListener.DEFAULT_ORDER - 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
@@ -26,8 +25,6 @@ import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
@@ -37,7 +34,7 @@ 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;
|
||||
import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource;
|
||||
|
||||
/**
|
||||
* An implementation of {@link EnvironmentPostProcessor} that delegates properties generation from {@link Bindings}.
|
||||
@@ -45,14 +42,15 @@ import static org.springframework.core.env.CommandLinePropertySource.COMMAND_LIN
|
||||
* {@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}.
|
||||
* 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 {
|
||||
public final class BindingSpecificEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
/**
|
||||
* The name of the {@link PropertySource} created by the {@code BindingsEnvironmentPostProcessor}: {@value}.
|
||||
*/
|
||||
public static final String BINDINGS_PROPERTY_SOURCE_NAME = "cnbBindings";
|
||||
public static final String BINDING_SPECIFIC_PROPERTY_SOURCE_NAME = "cnbBindingSpecific";
|
||||
|
||||
final List<BindingsPropertiesProcessor> processors;
|
||||
|
||||
@@ -61,27 +59,23 @@ public final class BindingsEnvironmentPostProcessor implements EnvironmentPostPr
|
||||
private final Bindings bindings;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@code BindingsEnvironmentPostProcessor} using the {@link Bindings} available in the
|
||||
* environment and the {@link BindingsPropertiesProcessor}s registered with {@link SpringFactoriesLoader}.
|
||||
* Creates a new instance of {@code BindingSpecificEnvironmentPostProcessor} using the {@link Bindings} available in
|
||||
* the environment and the {@link BindingsPropertiesProcessor}s registered with {@link SpringFactoriesLoader}.
|
||||
*/
|
||||
public BindingsEnvironmentPostProcessor() {
|
||||
public BindingSpecificEnvironmentPostProcessor() {
|
||||
this.bindings = new Bindings();
|
||||
this.processors = SpringFactoriesLoader.
|
||||
loadFactories(BindingsPropertiesProcessor.class, getClass().getClassLoader());
|
||||
AnnotationAwareOrderComparator.sort(this.processors);
|
||||
}
|
||||
|
||||
BindingsEnvironmentPostProcessor(@NotNull Bindings bindings,
|
||||
@NotNull BindingsPropertiesProcessor... processors) {
|
||||
|
||||
BindingSpecificEnvironmentPostProcessor(Bindings bindings, BindingsPropertiesProcessor... processors) {
|
||||
this.bindings = bindings;
|
||||
this.processors = Arrays.asList(processors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(@NotNull ConfigurableEnvironment environment,
|
||||
@NotNull SpringApplication application) {
|
||||
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
if (!isGlobalEnabled()) {
|
||||
return;
|
||||
}
|
||||
@@ -92,23 +86,14 @@ public final class BindingsEnvironmentPostProcessor implements EnvironmentPostPr
|
||||
}
|
||||
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
for (BindingsPropertiesProcessor processor : processors) {
|
||||
processor.process(bindings, properties);
|
||||
}
|
||||
processors.forEach(processor -> processor.process(bindings, properties));
|
||||
if (properties.isEmpty()) {
|
||||
log.debug("No properties set from CNB Bindings. Skipping PropertySource creation.");
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Creating PropertySource from CNB Bindings");
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
MapPropertySource propertySource = new MapPropertySource(BINDINGS_PROPERTY_SOURCE_NAME, properties);
|
||||
|
||||
if (propertySources.contains(COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
|
||||
propertySources.addAfter(COMMAND_LINE_PROPERTY_SOURCE_NAME, propertySource);
|
||||
} else {
|
||||
propertySources.addFirst(propertySource);
|
||||
}
|
||||
log.info("Creating binding-specific PropertySource from CNB Bindings");
|
||||
contributePropertySource(BINDING_SPECIFIC_PROPERTY_SOURCE_NAME, properties, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -34,6 +33,6 @@ public interface BindingsPropertiesProcessor {
|
||||
* @param bindings the {@code Bindings} exposed to the application.
|
||||
* @param properties the currently accumulated properties.
|
||||
*/
|
||||
void process(@NonNull Bindings bindings, @NonNull Map<String, Object> properties);
|
||||
void process(Bindings bindings, Map<String, Object> properties);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,7 +34,7 @@ public final class CassandraBindingsPropertiesProcessor implements BindingsPrope
|
||||
public static final String KIND = "Cassandra";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,7 +36,7 @@ public final class Db2BindingsPropertiesProcessor implements BindingsPropertiesP
|
||||
public static final String KIND = "DB2";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
final class Guards {
|
||||
|
||||
static boolean isGlobalEnabled() {
|
||||
@@ -25,7 +23,7 @@ final class Guards {
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
static boolean isKindEnabled(@NotNull String kind) {
|
||||
static boolean isKindEnabled(String kind) {
|
||||
String property = String.format("org.springframework.cloud.bindings.boot.%s.enable", kind.toLowerCase());
|
||||
String value = System.getProperty(property, "true");
|
||||
return Boolean.parseBoolean(value);
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,7 +34,7 @@ public final class MongoDbBindingsPropertiesProcessor implements BindingsPropert
|
||||
public static final String KIND = "MongoDB";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NonNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,7 +36,7 @@ public final class MySqlBindingsPropertiesProcessor implements BindingsPropertie
|
||||
public static final String KIND = "MySQL";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,7 +36,7 @@ public final class OracleBindingsPropertiesProcessor implements BindingsProperti
|
||||
public static final String KIND = "Oracle";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,7 +36,7 @@ public final class PostgreSqlBindingsPropertiesProcessor implements BindingsProp
|
||||
public static final String KIND = "PostgreSQL";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.core.env.CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
|
||||
|
||||
final class PropertySourceContributor {
|
||||
|
||||
static void contributePropertySource(String name, Map<String, Object> properties, ConfigurableEnvironment environment) {
|
||||
MapPropertySource propertySource = new MapPropertySource(name, properties);
|
||||
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
if (propertySources.contains(COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
|
||||
propertySources.addAfter(COMMAND_LINE_PROPERTY_SOURCE_NAME, propertySource);
|
||||
} else {
|
||||
propertySources.addFirst(propertySource);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,7 +34,7 @@ public final class RedisBindingsPropertiesProcessor implements BindingsPropertie
|
||||
public static final String KIND = "Redis";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -38,7 +36,7 @@ public final class SqlServerBindingsPropertiesProcessor implements BindingsPrope
|
||||
public static final String KIND = "SQLServer";
|
||||
|
||||
@Override
|
||||
public void process(@NonNull Bindings bindings, @NotNull Map<String, Object> properties) {
|
||||
public void process(Bindings bindings, Map<String, Object> properties) {
|
||||
if (!isKindEnabled(KIND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@NonNullApi
|
||||
package org.springframework.cloud.bindings.boot;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@NonNullApi
|
||||
package org.springframework.cloud.bindings;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
@@ -1,5 +1,5 @@
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||
org.springframework.cloud.bindings.boot.BindingsEnvironmentPostProcessor
|
||||
org.springframework.cloud.bindings.boot.BindingSpecificEnvironmentPostProcessor
|
||||
# Included implementations
|
||||
org.springframework.cloud.bindings.boot.BindingsPropertiesProcessor=\
|
||||
org.springframework.cloud.bindings.boot.CassandraBindingsPropertiesProcessor, \
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.ClearSystemProperty;
|
||||
import org.junitpioneer.jupiter.SetSystemProperty;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DisplayName("Binding-flattened EnvironmentPostProcessor")
|
||||
final class BindingFlattenedEnvironmentPostProcessorTest {
|
||||
|
||||
private final SpringApplication application = new SpringApplication();
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
@DisplayName("is disabled by default")
|
||||
@ClearSystemProperty(key = "org.springframework.cloud.bindings.boot.enable")
|
||||
void disabledByDefault() {
|
||||
new BindingFlattenedEnvironmentPostProcessor(
|
||||
new Bindings(
|
||||
new Binding("test-name", Paths.get("test-path"),
|
||||
Collections.emptyMap(), Collections.emptyMap())
|
||||
)
|
||||
).postProcessEnvironment(environment, application);
|
||||
|
||||
assertThat(environment.getPropertySources()).hasSize(1);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("when enabled")
|
||||
@SetSystemProperty(key = "org.springframework.cloud.bindings.boot.enable", value = "true")
|
||||
final class Enabled {
|
||||
|
||||
@Test
|
||||
@DisplayName("does not create PropertySource if no bindings")
|
||||
void noBindings() {
|
||||
new BindingFlattenedEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application);
|
||||
|
||||
assertThat(environment.getPropertySources()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("creates PropertySource with properties")
|
||||
void containsProperties() {
|
||||
new BindingFlattenedEnvironmentPostProcessor(
|
||||
new Bindings(
|
||||
new Binding("test-name", Paths.get("test-path"),
|
||||
Collections.singletonMap("test-metadata-key", "test-metadata-value"),
|
||||
Collections.singletonMap("test-secret-key", "test-secret-value"))
|
||||
)
|
||||
).postProcessEnvironment(environment, application);
|
||||
|
||||
assertThat(environment.getPropertySources()).hasSize(2);
|
||||
assertThat(environment.getProperty("cnb.bindings.test-name.metadata.test-metadata-key")).isEqualTo("test-metadata-value");
|
||||
assertThat(environment.getProperty("cnb.bindings.test-name.secret.test-secret-key")).isEqualTo("test-secret-value");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("has order before ConfigFileApplicationListener")
|
||||
void order() {
|
||||
assertThat(new BindingFlattenedEnvironmentPostProcessor(new Bindings()).getOrder())
|
||||
.isLessThan(ConfigFileApplicationListener.DEFAULT_ORDER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,18 +25,15 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.cloud.bindings.Binding;
|
||||
import org.springframework.cloud.bindings.Bindings;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.SimpleCommandLinePropertySource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.bindings.boot.BindingsEnvironmentPostProcessor.BINDINGS_PROPERTY_SOURCE_NAME;
|
||||
|
||||
@DisplayName("Bindings EnvironmentPostProcessor")
|
||||
final class BindingsEnvironmentPostProcessorTest {
|
||||
@DisplayName("Binding-specific EnvironmentPostProcessor")
|
||||
final class BindingSpecificEnvironmentPostProcessorTest {
|
||||
|
||||
private final SpringApplication application = new SpringApplication();
|
||||
|
||||
@@ -46,7 +43,7 @@ final class BindingsEnvironmentPostProcessorTest {
|
||||
@DisplayName("is disabled by default")
|
||||
@ClearSystemProperty(key = "org.springframework.cloud.bindings.boot.enable")
|
||||
void disabledByDefault() {
|
||||
new BindingsEnvironmentPostProcessor(
|
||||
new BindingSpecificEnvironmentPostProcessor(
|
||||
new Bindings(
|
||||
new Binding("test-name", Paths.get("test-path"),
|
||||
Collections.emptyMap(), Collections.emptyMap())
|
||||
@@ -65,7 +62,7 @@ final class BindingsEnvironmentPostProcessorTest {
|
||||
@Test
|
||||
@DisplayName("does not create PropertySource if no bindings")
|
||||
void noBindings() {
|
||||
new BindingsEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application);
|
||||
new BindingSpecificEnvironmentPostProcessor(new Bindings()).postProcessEnvironment(environment, application);
|
||||
|
||||
assertThat(environment.getPropertySources()).hasSize(1);
|
||||
}
|
||||
@@ -73,7 +70,7 @@ final class BindingsEnvironmentPostProcessorTest {
|
||||
@Test
|
||||
@DisplayName("does not create PropertySource if no properties")
|
||||
void noProperties() {
|
||||
new BindingsEnvironmentPostProcessor(
|
||||
new BindingSpecificEnvironmentPostProcessor(
|
||||
new Bindings(
|
||||
new Binding("test-name", Paths.get("test-path"),
|
||||
Collections.emptyMap(), Collections.emptyMap())
|
||||
@@ -86,7 +83,7 @@ final class BindingsEnvironmentPostProcessorTest {
|
||||
@Test
|
||||
@DisplayName("creates PropertySource with properties")
|
||||
void containsProperties() {
|
||||
new BindingsEnvironmentPostProcessor(
|
||||
new BindingSpecificEnvironmentPostProcessor(
|
||||
new Bindings(
|
||||
new Binding("test-name", Paths.get("test-path"),
|
||||
Collections.emptyMap(), Collections.emptyMap())
|
||||
@@ -98,51 +95,17 @@ final class BindingsEnvironmentPostProcessorTest {
|
||||
assertThat(environment.getProperty("test-key")).isEqualTo("test-value");
|
||||
}
|
||||
|
||||
@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())
|
||||
assertThat(new BindingSpecificEnvironmentPostProcessor(new Bindings()).getOrder())
|
||||
.isLessThan(ConfigFileApplicationListener.DEFAULT_ORDER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("included implementations are registered")
|
||||
void includedImplementations() {
|
||||
assertThat(new BindingsEnvironmentPostProcessor().processors).hasSize(8);
|
||||
assertThat(new BindingSpecificEnvironmentPostProcessor().processors).hasSize(8);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.SimpleCommandLinePropertySource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.bindings.boot.PropertySourceContributor.contributePropertySource;
|
||||
|
||||
@DisplayName("PropertySource Contributor")
|
||||
final class PropertySourceContributorTest {
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
@Test
|
||||
@DisplayName("adds PropertySource after CommandLinePropertySource")
|
||||
void withCommandLinePropertySource() {
|
||||
environment.getPropertySources().addFirst(new SimpleCommandLinePropertySource());
|
||||
|
||||
contributePropertySource("test-name", Collections.singletonMap("test-key", "test-value"), environment);
|
||||
|
||||
PropertySource<?> propertySource = environment.getPropertySources().get("test-name");
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getProperty("test-key")).isEqualTo("test-value");
|
||||
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("adds PropertySource first")
|
||||
void withoutCommandLinePropertySource() {
|
||||
contributePropertySource("test-name", Collections.singletonMap("test-key", "test-value"), environment);
|
||||
|
||||
PropertySource<?> propertySource = environment.getPropertySources().get("test-name");
|
||||
assertThat(propertySource).isNotNull();
|
||||
assertThat(propertySource.getProperty("test-key")).isEqualTo("test-value");
|
||||
assertThat(environment.getPropertySources().precedenceOf(propertySource)).isEqualTo(0);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user