Merge branch 'k8s-service-bindings' into main

Signed-off-by: Ben Hale <bhale@vmware.com>
This commit is contained in:
Ben Hale
2020-07-14 10:53:07 -07:00
86 changed files with 787 additions and 567 deletions

View File

@@ -1,5 +1,5 @@
# Spring Cloud Bindings
The Spring Cloud Bindings library exposes a rich Java language binding for the [Cloud Native Buildpacks Binding Specification][s]. In addition, if opted-in, it configures Spring Boot application configuration properties appropriate for the kind of binding encountered.
The Spring Cloud Bindings library exposes a rich Java language binding for the [Cloud Native Buildpacks Binding Specification][s]. In addition, if opted-in, it configures Spring Boot application configuration properties appropriate for the type of binding encountered.
[s]: https://github.com/buildpacks/spec/blob/master/extensions/bindings.md
@@ -30,10 +30,10 @@ 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. Auto-configuration is disabled by default and can be enabled by setting the `org.springframework.cloud.bindings.boot.enable` System Property to `true`.
Each auto-configuration is triggered by the type of binding. Each auto-configuration can be disabled using a System Property specific to that type 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`
Type: `cassandra`
Disable Property: `org.springframework.cloud.bindings.boot.cassandra.enable`
| Property | Value
@@ -48,7 +48,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.cassandra.enable`
| `spring.data.cassandra.username` | `{secret/username}`
### Couchbase
Kind: `couchbase`
Type: `couchbase`
Disable Property: `org.springframework.cloud.bindings.boot.couchbase.enable`
| Property | Value
@@ -62,7 +62,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.couchbase.enable`
| `spring.couchbase.username` | `{secret/username}`
### DB2 RDBMS
Kind: `DB2`
Type: `DB2`
Disable Property: `org.springframework.cloud.bindings.boot.db2.enable`
| Property | Value
@@ -77,7 +77,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.db2.enable`
### Elasticsearch
Kind: `Elasticsearch`
Type: `Elasticsearch`
Disable Property: `org.springframework.cloud.bindings.boot.elasticsearch.enable`
| Property | Value
@@ -95,7 +95,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.elasticsearch.enable`
| `spring.elasticsearch.rest.username` | `{secret/username}`
### Kafka
Kind: `kafka`
Type: `kafka`
Disable Property: `org.springframework.cloud.bindings.boot.kafka.enable`
| Property | Value
@@ -106,7 +106,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.kafka.enable`
| `spring.kafka.streams.bootstrap-servers` | `{secret/streams.bootstrap-servers}`
### LDAP
Kind: `LDAP`
Type: `LDAP`
Disable Property: `org.springframework.cloud.bindings.boot.ldap.enable`
| Property | Value
@@ -117,7 +117,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.ldap.enable`
| `spring.ldap.username` | `{secret/username}`
### MongoDB
Kind: `MongoDB`
Type: `MongoDB`
Disable Property: `org.springframework.cloud.bindings.boot.mongodb.enable`
| Property | Value
@@ -132,7 +132,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.mongodb.enable`
| `spring.mongodb.username` | `{secret/username}`
### MySQL RDBMS
Kind: `MySQL`
Type: `MySQL`
Disable Property: `org.springframework.cloud.bindings.boot.mysql.enable`
| Property | Value
@@ -146,7 +146,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.mysql.enable`
| `spring.r2dbc.username` | `{secret/username}`
### Neo4J
Kind: `Neo4J`
Type: `Neo4J`
Disable Property: `org.springframework.cloud.bindings.boot.neo4j.enable`
| Property | Value
@@ -156,7 +156,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.neo4j.enable`
| `spring.data.neo4j.username` | `{secret/username}`
### Oracle RDBMS
Kind: `Oracle`
Type: `Oracle`
Disable Property: `org.springframework.cloud.bindings.boot.oracle.enable`
| Property | Value
@@ -170,7 +170,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.oracle.enable`
| `spring.r2dbc.username` | `{secret/username}`
### PostgreSQL RDBMS
Kind: `PostgreSQL`
Type: `PostgreSQL`
Disable Property: `org.springframework.cloud.bindings.boot.postgresql.enable`
| Property | Value
@@ -184,7 +184,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.postgresql.enable`
| `spring.r2dbc.username` | `{secret/username}`
### RabbitMQ RDBMS
Kind: `RabbitMQ`
Type: `RabbitMQ`
Disable Property: `org.springframework.cloud.bindings.boot.rabbitmq.enable`
| Property | Value
@@ -197,7 +197,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.rabbitmq.enable`
| `spring.rabbitmq.virtual-host` | `{secret/virtual-host}`
### Redis RDBMS
Kind: `Redis`
Type: `Redis`
Disable Property: `org.springframework.cloud.bindings.boot.redis.enable`
| Property | Value
@@ -215,7 +215,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.redis.enable`
| `spring.redis.url` | `{secret/url}`
## SCS Config Server
Kind: `Config`
Type: `Config`
Disable Property: `org.springframework.cloud.bindings.boot.config.enable`
| Property | Value
@@ -226,7 +226,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.config.enable`
| `spring.cloud.config.client.oauth2.accessTokenUri` | `{secret/access-token-uri}`
### SCS Eureka
Kind: `Eureka`
Type: `Eureka`
Disable Property: `org.springframework.cloud.bindings.boot.eureka.enable`
| Property | Value
@@ -237,7 +237,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.eureka.enable`
| `eureka.client.serviceUrl.defaultZone` | `{secret/uri}/eureka/`
## Spring Security OAuth2
Kind: `OAuth2`
Type: `OAuth2`
Disable Property: `org.springframework.cloud.bindings.boot.oauth2.enable`
| Property | Value
@@ -254,7 +254,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.oauth2.enable`
| `spring.security.oauth2.client.provider.{metadata/provider}.user-name-attribute` | `{secret/user-name-attribute}`
### SQLServer RDBMS
Kind: `SQLServer`
Type: `SQLServer`
Disable Property: `org.springframework.cloud.bindings.boot.sqlserver.enable`
| Property | Value
@@ -269,7 +269,7 @@ Disable Property: `org.springframework.cloud.bindings.boot.sqlserver.enable`
### Vault
Kind: `Vault`
Type: `Vault`
Disable Property: `org.springframework.cloud.bindings.boot.vault.enable`
Any Provider:
@@ -354,7 +354,7 @@ If `{secret/authentication-method}` is equal to `token`:
### Wavefront
Kind: `Wavefront`
Type: `Wavefront`
Disable Property: `org.springframework.cloud.bindings.boot.wavefront.enable`
| Property | Value
@@ -367,9 +367,9 @@ Disable Property: `org.springframework.cloud.bindings.boot.wavefront.enable`
Consumers can extend the `BindingSpecificEnvironmentPostProcessor` with support for additional bindings by registering additional implementations of the `BindingsPropertiesProcessor`.
Within the `process` method, custom processors should make desired modifications to the application properties, using the contents of the bindings to compute property values as appropriate. Custom processors are strongly encouraged to use the `kind` of each binding to filter for bindings intended for that processor.
Within the `process` method, custom processors should make desired modifications to the application properties, using the contents of the bindings to compute property values as appropriate. Custom processors are strongly encouraged to use the `type` of each binding to filter for bindings intended for that processor.
Below is an example that processes a single binding of `kind` `myservice`. If such a binding exists this processor sets `my.service.enabled=true` and sets `my.service.uri` to the value of `uri` found in the binding secret.
Below is an example that processes a single binding of `type` `myservice`. If such a binding exists this processor sets `my.service.enabled=true` and sets `my.service.uri` to the value of `uri` found in the binding secret.
```
package com.example;
@@ -385,14 +385,14 @@ import java.util.Map;
public final class MyServiceBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
public static final String KIND = "myservice";
public static final String TYPE = "myservice";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!environment.getProperty("com.example.bindings.myservice.enable", Boolean.class, true)) {
return;
}
List<Binding> myBindings = bindings.filterBindings(KIND);
List<Binding> myBindings = bindings.filterBindings(TYPE);
if (myBindings.size() == 0) {
return;
}

View File

@@ -15,52 +15,121 @@
*/
package org.springframework.cloud.bindings;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
/**
* A representation of a binding as defined by the
* <a href="https://github.com/buildpacks/spec/blob/master/extensions/bindings.md">Cloud Native Buildpacks Specification</a>.
* <a href="https://github.com/k8s-service-bindings/spec#application-projection">Kubernetes Service Binding Specification</a>.
*/
public final class Binding {
/**
* The key for the kind of a binding.
*/
public static final String KIND = "kind";
/**
* The key for the provider of a binding.
*/
public static final String PROVIDER = "provider";
/**
* The key for the type of a binding.
*/
public static final String TYPE = "type";
private final String name;
private final Path path;
private final Map<String, String> metadata;
private final String provider;
private final Map<String, String> secret;
private final String type;
/**
* Creates a new {@code Binding} instance using the specified file system root.
*/
public Binding(Path path) {
this.name = path.getFileName().toString();
this.path = path;
this.metadata = createFilePerEntryMap(path.resolve("metadata"));
this.secret = createFilePerEntryMap(path.resolve("secret"));
this(path.getFileName().toString(), path, createSecretMap(path));
}
/**
* Creates a new {@code Binding} instance using the specified content.
*
* @param name the name of the {@code Binding}.
* @param path the path to the {@code Binding}.
* @param metadata the metadata of the {@code Binding}.
* @param secret the secret of the {@code Binding}.
* @param name the name of the {@code Binding}.
* @param path the path to the {@code Binding}.
* @param secret the secret of the {@code Binding}.
*/
public Binding(String name, Path path, Map<String, String> metadata, Map<String, String> secret) {
public Binding(String name, Path path, Map<String, String> secret) {
this.name = name;
this.path = path;
this.metadata = metadata;
this.secret = secret;
this.secret = new HashMap<>();
String provider = null;
String type = null;
for (Map.Entry<String, String> entry : secret.entrySet()) {
switch (entry.getKey()) {
case TYPE:
case KIND: // TODO: Remove as CNB_BINDINGS ages out
type = entry.getValue();
break;
case PROVIDER:
provider = entry.getValue();
break;
default:
this.secret.put(entry.getKey(), entry.getValue());
}
}
this.provider = provider;
this.type = type;
}
private static Map<String, String> createSecretMap(Path path) {
Map<String, String> secret = createFilePerEntryMap(path);
// TODO: Remove as CNB_BINDINGS ages out
Arrays.asList("metadata", "secret")
.forEach(d -> secret.putAll(createFilePerEntryMap(path.resolve(d))));
return secret;
}
private static Map<String, String> createFilePerEntryMap(Path path) {
if (!Files.exists(path)) {
return Collections.emptyMap();
}
try {
return Files.list(path)
.filter(p -> {
try {
return !Files.isHidden(p);
} catch (IOException e) {
throw new IllegalStateException(String.format("unable to determin id file '%s' is hidden", p), e);
}
})
.filter(p -> !Files.isDirectory(p))
.collect(Collectors.toMap(
p -> p.getFileName().toString(),
p -> {
try {
return new String(Files.readAllBytes(p), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new IllegalStateException(String.format("unable to read file '%s'", p), e);
}
}
));
} catch (IOException e) {
throw new IllegalStateException(String.format("unable to list children of '%s'", path), e);
}
}
/**
@@ -77,41 +146,25 @@ public final class Binding {
return path;
}
/**
* Returns the metadata of the binding.
*/
public Map<String, String> getMetadata() {
return metadata;
}
/**
* Returns the secret of the binding.
*/
public Map<String, String> getSecret() {
return secret;
return Collections.unmodifiableMap(secret);
}
/**
* Returns the kind of the binding. Equivalent to {@code getMetadata().get("kind")}.
* Returns the type of the binding.
*/
public String getKind() {
return metadata.get("kind");
public String getType() {
return type;
}
/**
* Returns the provider of the binding. Equivalent to {@code getMetadata().get("provider")}.
* Returns the provider of the binding.
*/
public String getProvider() {
return metadata.get("provider");
}
/**
* Returns the {@link Path} to a metadata file on disk.
*
* @param name the name of the metadata key.
*/
public Path getMetadataFilePath(String name) {
return this.path.resolve("metadata").resolve(name);
return provider;
}
/**
@@ -120,7 +173,14 @@ public final class Binding {
* @param name the name of the secret key.
*/
public Path getSecretFilePath(String name) {
return this.path.resolve("secret").resolve(name);
for (String d : Arrays.asList("metadata", "secret")) {
Path file = path.resolve(d).resolve(name);
if (Files.exists(file)) {
return file;
}
}
return this.path.resolve(name);
}
@Override
@@ -130,33 +190,25 @@ public final class Binding {
Binding binding = (Binding) o;
return name.equals(binding.name) &&
path.equals(binding.path) &&
metadata.equals(binding.metadata) &&
secret.equals(binding.secret);
Objects.equals(provider, binding.provider) &&
secret.equals(binding.secret) &&
Objects.equals(type, binding.type);
}
@Override
public int hashCode() {
return Objects.hash(name, path, metadata, secret);
return Objects.hash(name, path, provider, secret, type);
}
private Map<String, String> createFilePerEntryMap(Path path) {
try {
return Files.list(path)
.filter(p -> !p.getFileName().toString().startsWith("."))
.filter(p -> !new File(p.toString()).isDirectory())
.collect(Collectors.toMap(
p -> p.getFileName().toString(),
p -> {
try {
return new String(Files.readAllBytes(p), StandardCharsets.UTF_8).trim();
} catch (IOException e) {
throw new IllegalStateException(String.format("unable to read file '%s'", p), e);
}
}
));
} catch (IOException e) {
throw new IllegalStateException(String.format("unable to list children of '%s'", path), e);
}
@Override
public String toString() {
return "Binding{" +
"name='" + name + '\'' +
", path=" + path +
", provider='" + provider + '\'' +
", secret=" + new TreeSet<>(secret.keySet()) +
", type='" + type + '\'' +
'}';
}
}

View File

@@ -24,21 +24,28 @@ import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* A representation of a collection of bindings as defined by the
* <a href="https://github.com/buildpacks/spec/blob/master/extensions/bindings.md">Cloud Native Buildpacks Specification</a>.
* <a href="https://github.com/k8s-service-bindings/spec#application-projection">Kubernetes Service Binding Specification</a>.
*/
public final class Bindings {
/**
* The name of the environment variable to read to determine the bindings file system root. Specified by the Cloud
* Native Buildpacks Specification.
* The name of the environment variable to read to determine the bindings file system root. Specified by the
* <a href="https://github.com/buildpacks/spec/blob/master/extensions/bindings.md">Cloud Native Buildpacks Specification</a>
*/
public static final String CNB_BINDINGS = "CNB_BINDINGS";
/**
* The name of the environment variable to read to determine the bindings file system root. Specified by the
* Kubernetes Service Binding Specification.
*/
public static final String SERVICE_BINDING_ROOT = "SERVICE_BINDING_ROOT";
private final List<Binding> bindings;
/**
@@ -47,7 +54,7 @@ public final class Bindings {
* returned. If the directory does not exist, an empty {@code Bindings} is returned.
*/
public Bindings() {
this(System.getenv(CNB_BINDINGS));
this(getBindingRoot());
}
/**
@@ -91,6 +98,17 @@ public final class Bindings {
this.bindings = Arrays.asList(bindings);
}
private static String getBindingRoot() {
Map<String, String> environment = System.getenv();
// TODO: Remove as CNB_BINDINGS ages out
if (environment.containsKey(CNB_BINDINGS)) {
return environment.get(CNB_BINDINGS);
}
return System.getenv(SERVICE_BINDING_ROOT);
}
/**
* Returns all the {@link Binding}s that were found during construction.
*/
@@ -113,27 +131,27 @@ public final class Bindings {
}
/**
* Returns zero or more {@link Binding}s with a given kind. Equivalent to {@link #filterBindings(String, String)}.
* Returns zero or more {@link Binding}s with a given type. Equivalent to {@link #filterBindings(String, String)}.
*
* @param kind the kind of the {@code Binding} to find.
* @return the collection of {@code Binding}s with a given kind.
* @param type the type of the {@code Binding} to find.
* @return the collection of {@code Binding}s with a given type.
*/
public List<Binding> filterBindings(@Nullable String kind) {
return filterBindings(kind, null);
public List<Binding> filterBindings(@Nullable String type) {
return filterBindings(type, null);
}
/**
* Return zero or more {@link Binding}s with a given kind and provider. If {@code kind} or {@code provider} are
* Return zero or more {@link Binding}s with a given type and provider. If {@code type} or {@code provider} are
* {@code null}, the result is not filtered on that argument.
*
* @param kind the kind of {@code Binding} to find.
* @param type the type of {@code Binding} to find.
* @param provider the provider of {@code Binding} to find
* @return the collection of {@code Binding}s with a given kind and provider.
* @return the collection of {@code Binding}s with a given type and provider.
*/
public List<Binding> filterBindings(@Nullable String kind, @Nullable String provider) {
public List<Binding> filterBindings(@Nullable String type, @Nullable String provider) {
return bindings.stream()
.filter(binding ->
(kind == null || binding.getKind().equalsIgnoreCase(kind)) &&
(type == null || binding.getType().equalsIgnoreCase(type)) &&
(provider == null || binding.getProvider().equalsIgnoreCase(provider)))
.collect(Collectors.toList());
}

View File

@@ -71,11 +71,8 @@ public final class BindingFlattenedEnvironmentPostProcessor implements Applicati
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);
properties.put(String.format("cnb.bindings.%s.%s", binding.getName(), key), value);
});
});

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class CassandraBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Cassandra";
public static final String TYPE = "Cassandra";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("cluster-name").to("spring.data.cassandra.cluster-name");

View File

@@ -22,24 +22,24 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class ConfigServerBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Config";
public static final String TYPE = "Config";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("uri").to("spring.cloud.config.uri");
map.from("client-id").to("spring.cloud.config.client.oauth2.clientId");

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class CouchbaseBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Couchbase";
public static final String TYPE = "Couchbase";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("bootstrap-hosts").to("spring.couchbase.bootstrap-hosts");

View File

@@ -22,27 +22,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*
* @see <a href="https://www.ibm.com/support/knowledgecenter/SSEPGG_11.5.0/com.ibm.db2.luw.apdv.java.doc/src/tpc/imjcc_r0052342.html">JDBC URL Format</a>
*/
public final class Db2BindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "DB2";
public static final String TYPE = "DB2";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
//jdbc properties

View File

@@ -22,26 +22,26 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class ElasticsearchBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Elasticsearch";
public static final String TYPE = "Elasticsearch";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("endpoints").to("spring.data.elasticsearch.client.reactive.endpoints");

View File

@@ -22,24 +22,24 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class EurekaBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Eureka";
public static final String TYPE = "Eureka";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("client-id").to("eureka.client.oauth2.client-id");

View File

@@ -24,9 +24,9 @@ final class Guards {
return environment.getProperty("org.springframework.cloud.bindings.boot.enable", Boolean.class, false);
}
static boolean isKindEnabled(Environment environment, String kind) {
static boolean isTypeEnabled(Environment environment, String type) {
return environment.getProperty(
String.format("org.springframework.cloud.bindings.boot.%s.enable", kind.toLowerCase()),
String.format("org.springframework.cloud.bindings.boot.%s.enable", type.toLowerCase()),
Boolean.class, true);
}

View File

@@ -22,24 +22,24 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class KafkaBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Kafka";
public static final String TYPE = "Kafka";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("bootstrap-servers").to("spring.kafka.bootstrap-servers");

View File

@@ -22,24 +22,24 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class LDAPBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "LDAP";
public static final String TYPE = "LDAP";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("base").to("spring.ldap.base");
map.from("password").to("spring.ldap.password");

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class MongoDbBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "MongoDB";
public static final String TYPE = "MongoDB";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("authentication-database").to("spring.mongodb.authentication-database");

View File

@@ -22,27 +22,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*
* @see <a href="https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-jdbc-url-format.html">JDBC URL Format</a>
*/
public final class MySqlBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "MySQL";
public static final String TYPE = "MySQL";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
//jdbc properties

View File

@@ -22,24 +22,24 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class Neo4JBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Neo4J";
public static final String TYPE = "Neo4J";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("password").to("spring.data.neo4j.password");

View File

@@ -22,27 +22,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*
* @see <a href="https://docs.oracle.com/cd/E11882_01/appdev.112/e13995/oracle/jdbc/OracleDriver.html">JDBC URL Format</a>
*/
public final class OracleBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Oracle";
public static final String TYPE = "Oracle";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
//jdbc properties

View File

@@ -22,27 +22,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*
* @see <a href="https://jdbc.postgresql.org/documentation/80/connect.html">JDBC URL Format</a>
*/
public final class PostgreSqlBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "PostgreSQL";
public static final String TYPE = "PostgreSQL";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
//jdbc properties

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
final class RabbitMqBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "RabbitMQ";
public static final String TYPE = "RabbitMQ";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("addresses").to("spring.rabbitmq.addresses");

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class RedisBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Redis";
public static final String TYPE = "Redis";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("client-name").to("spring.redis.client-name");

View File

@@ -25,27 +25,27 @@ import org.springframework.core.env.Environment;
import java.util.*;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class SpringSecurityOAuth2BindingsPropertiesProcessor implements BindingsPropertiesProcessor, ApplicationListener<ApplicationPreparedEvent> {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "OAuth2";
public static final String TYPE = "OAuth2";
private static final DeferredLog LOG = new DeferredLog();
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
String provider = binding.getProvider();
if (provider == null) {

View File

@@ -22,27 +22,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*
* @see <a href="https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15">JDBC URL Format</a>
*/
public final class SqlServerBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "SQLServer";
public static final String TYPE = "SQLServer";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
//jdbc properties

View File

@@ -25,27 +25,27 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class VaultBindingsPropertiesProcessor implements BindingsPropertiesProcessor, ApplicationListener<ApplicationPreparedEvent> {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Vault";
public static final String TYPE = "Vault";
private static final DeferredLog LOG = new DeferredLog();
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("uri").to("spring.cloud.vault.uri");
map.from("namespace").to("spring.cloud.vault.namespace"); // vault enterprise feature

View File

@@ -22,25 +22,25 @@ import org.springframework.core.env.Environment;
import java.util.Map;
import static org.springframework.cloud.bindings.boot.Guards.isKindEnabled;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
/**
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of kind: {@value KIND}.
* An implementation of {@link BindingsPropertiesProcessor} that detects {@link Binding}s of type: {@value TYPE}.
*/
public final class WavefrontBindingsPropertiesProcessor implements BindingsPropertiesProcessor {
/**
* The {@link Binding} kind that this processor is interested in: {@value}.
* The {@link Binding} type that this processor is interested in: {@value}.
**/
public static final String KIND = "Wavefront";
public static final String TYPE = "Wavefront";
@Override
public void process(Environment environment, Bindings bindings, Map<String, Object> properties) {
if (!isKindEnabled(environment, KIND)) {
if (!isTypeEnabled(environment, TYPE)) {
return;
}
bindings.filterBindings(KIND).forEach(binding -> {
bindings.filterBindings(TYPE).forEach(binding -> {
MapMapper map = new MapMapper(binding.getSecret(), properties);
map.from("api-token").to("management.metrics.export.wavefront.api-token");
map.from("uri").to("management.metrics.export.wavefront.uri");

View File

@@ -17,8 +17,10 @@ package org.springframework.cloud.bindings;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
@@ -26,30 +28,70 @@ import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("Binding")
final class BindingTest {
@Test
@DisplayName("populates content from filesystem")
void test() {
Binding binding = new Binding(Paths.get("src/test/resources/test-name-1"));
@Nested
@DisplayName("CNB Bindings")
final class CNBBindings {
private final Path root = Paths.get("src/test/resources/cnb");
@Test
@DisplayName("populates content from filesystem")
void test() {
Binding binding = new Binding(root.resolve("test-name-1"));
assertThat(binding.getType()).isEqualTo("test-kind-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getSecretFilePath("test-metadata-key"))
.isEqualTo(root.resolve("test-name-1/metadata/test-metadata-key"));
assertThat(binding.getSecretFilePath("test-secret-key"))
.isEqualTo(root.resolve("test-name-1/secret/test-secret-key"));
}
@Test
@DisplayName("populates k8s style content from filesystem")
void testK8s() {
//When bindings are provided as a k8s configmap secret pairs data files will be symlinks to hidden directories
Binding binding = new Binding(root.resolve("test-k8s"));
assertThat(binding.getType()).isEqualTo("test-kind-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getSecretFilePath("test-metadata-key"))
.isEqualTo(root.resolve("test-k8s/metadata/test-metadata-key"));
assertThat(binding.getSecretFilePath("test-secret-key"))
.isEqualTo(root.resolve("test-k8s/secret/test-secret-key"));
}
assertThat(binding.getKind()).isEqualTo("test-kind-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getMetadataFilePath("test-key"))
.isEqualTo(Paths.get("src/test/resources/test-name-1/metadata/test-key"));
assertThat(binding.getSecretFilePath("test-key"))
.isEqualTo(Paths.get("src/test/resources/test-name-1/secret/test-key"));
}
@Test
@DisplayName("populates k8s style content from filesystem")
void testK8s() {
//When bindings are provided as a k8s configmap secret pairs data files will be symlinks to hidden directories
Binding binding = new Binding(Paths.get("src/test/resources/test-k8s"));
@Nested
@DisplayName("Kubernetes Bindings")
final class KubernetesBindings {
private final Path root = Paths.get("src/test/resources/k8s");
@Test
@DisplayName("populates content from filesystem")
void test() {
Binding binding = new Binding(root.resolve("test-name-1"));
assertThat(binding.getType()).isEqualTo("test-type-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getSecretFilePath("test-secret-key"))
.isEqualTo(root.resolve("test-name-1/test-secret-key"));
}
@Test
@DisplayName("populates k8s style content from filesystem")
void testK8s() {
//When bindings are provided as a k8s configmap secret pairs data files will be symlinks to hidden directories
Binding binding = new Binding(root.resolve("test-k8s"));
assertThat(binding.getType()).isEqualTo("test-type-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getSecretFilePath("test-secret-key"))
.isEqualTo(root.resolve("test-k8s/test-secret-key"));
}
assertThat(binding.getKind()).isEqualTo("test-kind-1");
assertThat(binding.getProvider()).isEqualTo("test-provider-1");
assertThat(binding.getMetadataFilePath("test-key"))
.isEqualTo(Paths.get("src/test/resources/test-k8s/metadata/test-key"));
assertThat(binding.getSecretFilePath("test-key"))
.isEqualTo(Paths.get("src/test/resources/test-k8s/secret/test-key"));
}
}

View File

@@ -0,0 +1,199 @@
/*
* 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;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@DisplayName("Bindings")
final class BindingsTest {
@Nested
@DisplayName("CNB Bindings")
final class CNBBindings {
private final Path root = Paths.get("src/test/resources/cnb");
@Nested
@DisplayName("when constructed")
final class Constructor {
@Test
@DisplayName("empty if path is null")
void nullPath() {
Bindings b = new Bindings((String) null);
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("empty if path does not exist")
void nonExistentDirectory() {
Bindings b = new Bindings(root.resolve("non-existent").toString());
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("throws exception if path is not a directory")
void nonDirectory() throws IOException {
Path path = File.createTempFile("bindings", "").toPath();
assertThatIllegalArgumentException().isThrownBy(() -> new Bindings(path.toString()));
}
@Test
@DisplayName("populates content")
void construct() {
Bindings b = new Bindings(root.toString());
assertThat(b.getBindings()).hasSize(3);
}
}
@Nested
@DisplayName("with content")
final class Content {
private final Bindings bindings = new Bindings(
new Binding("test-name-1", root.resolve("test-name-1"),
new FluentMap()
.withEntry("kind", "test-kind-1")
.withEntry("provider", "test-provider-1")
),
new Binding("test-name-2", root.resolve("test-name-2"),
new FluentMap()
.withEntry("kind", "test-kind-2")
.withEntry("provider", "test-provider-2")
)
);
@Test
@DisplayName("returns content")
void getBindings() {
assertThat(bindings.getBindings()).hasSize(2);
}
@Test
@DisplayName("filters bindings by kind")
void filterBindingsByKind() {
assertThat(bindings.filterBindings("test-kind-1", null)).hasSize(1);
}
@Test
@DisplayName("filters bindings by provider")
void filterBindingsByProvider() {
assertThat(bindings.filterBindings(null, "test-provider-1")).hasSize(1);
}
}
}
@Nested
@DisplayName("Kubernetes Bindings")
final class KubernetesBindings {
private final Path root = Paths.get("src/test/resources/k8s");
@Nested
@DisplayName("when constructed")
final class Constructor {
@Test
@DisplayName("empty if path is null")
void nullPath() {
Bindings b = new Bindings((String) null);
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("empty if path does not exist")
void nonExistentDirectory() {
Bindings b = new Bindings(root.resolve("non-existent").toString());
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("throws exception if path is not a directory")
void nonDirectory() throws IOException {
Path path = File.createTempFile("bindings", "").toPath();
assertThatIllegalArgumentException().isThrownBy(() -> new Bindings(path.toString()));
}
@Test
@DisplayName("populates content")
void construct() {
Bindings b = new Bindings(root.toString());
assertThat(b.getBindings()).hasSize(3);
}
}
@Nested
@DisplayName("with content")
final class Content {
private final Bindings bindings = new Bindings(
new Binding("test-name-1", root.resolve("test-name-1"),
new FluentMap()
.withEntry("type", "test-type-1")
.withEntry("provider", "test-provider-1")
),
new Binding("test-name-2", root.resolve("test-name-2"),
new FluentMap()
.withEntry("type", "test-type-2")
.withEntry("provider", "test-provider-2")
)
);
@Test
@DisplayName("returns content")
void getBindings() {
assertThat(bindings.getBindings()).hasSize(2);
}
@Test
@DisplayName("filters bindings by kind")
void filterBindingsByKind() {
assertThat(bindings.filterBindings("test-type-1", null)).hasSize(1);
}
@Test
@DisplayName("filters bindings by provider")
void filterBindingsByProvider() {
assertThat(bindings.filterBindings(null, "test-provider-1")).hasSize(1);
}
}
}
}

View File

@@ -1,105 +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;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@DisplayName("Bindings")
final class BindingsTests {
@Nested
@DisplayName("when constructed")
final class Constructor {
@Test
@DisplayName("empty if path is null")
void nullPath() {
Bindings b = new Bindings((String) null);
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("empty if path does not exist")
void nonExistentDirectory() {
String path = "src/test/resources/non-existent";
Bindings b = new Bindings(path);
assertThat(b.getBindings()).isEmpty();
}
@Test
@DisplayName("throws exception if path is not a directory")
void nonDirectory() throws IOException {
String path = File.createTempFile("bindings", "").getPath();
assertThatIllegalArgumentException().isThrownBy(() -> new Bindings(path));
}
@Test
@DisplayName("populates content")
void construct() {
String path = "src/test/resources";
Bindings b = new Bindings(path);
assertThat(b.getBindings()).hasSize(3);
}
}
@Nested
@DisplayName("with content")
final class Content {
private final Bindings bindings = new Bindings(
new Binding("test-name-1", Paths.get("src/test/resources/test-name-1"),
new FluentMap().withEntry("kind", "test-kind-1").withEntry("provider", "test-provider-1"),
Collections.emptyMap()),
new Binding("test-name-2", Paths.get("src/test/resources/test-name-2"),
new FluentMap().withEntry("kind", "test-kind-2").withEntry("provider", "test-provider-2"),
Collections.emptyMap())
);
@Test
@DisplayName("returns content")
void getBindings() {
assertThat(bindings.getBindings()).hasSize(2);
}
@Test
@DisplayName("filters bindings by kind")
void filterBindingsByKind() {
assertThat(bindings.filterBindings("test-kind-1", null)).hasSize(1);
}
@Test
@DisplayName("filters bindings by provider")
void filterBindingsByProvider() {
assertThat(bindings.filterBindings(null, "test-provider-1")).hasSize(1);
}
}
}

View File

@@ -43,7 +43,8 @@ final class BindingFlattenedEnvironmentPostProcessorTest {
new BindingFlattenedEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
Collections.emptyMap()
)
)
).postProcessEnvironment(new MockEnvironment(), application);
@@ -65,14 +66,13 @@ final class BindingFlattenedEnvironmentPostProcessorTest {
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"))
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");
assertThat(environment.getProperty("cnb.bindings.test-name.test-secret-key")).isEqualTo("test-secret-value");
}
@Test

View File

@@ -43,7 +43,8 @@ final class BindingSpecificEnvironmentPostProcessorTest {
new BindingSpecificEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
Collections.emptyMap()
)
),
(environment, bindings, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(new MockEnvironment(), application);
@@ -66,7 +67,8 @@ final class BindingSpecificEnvironmentPostProcessorTest {
new BindingSpecificEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
Collections.emptyMap()
)
)
).postProcessEnvironment(environment, application);
@@ -79,7 +81,8 @@ final class BindingSpecificEnvironmentPostProcessorTest {
new BindingSpecificEnvironmentPostProcessor(
new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.emptyMap(), Collections.emptyMap())
Collections.emptyMap()
)
),
(environment, bindings, properties) -> properties.put("test-key", "test-value")
).postProcessEnvironment(environment, application);

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.CassandraBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.CassandraBindingsPropertiesProcessor.TYPE;
@DisplayName("Cassandra BindingsPropertiesProcessor")
final class CassandraBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("cluster-name", "test-cluster-name")
.withEntry("compression", "test-compression")
.withEntry("contact-points", "test-contact-points")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.ConfigServerBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.ConfigServerBindingsPropertiesProcessor.TYPE;
@DisplayName("Config Server BindingsPropertiesProcessor")
final class ConfigServerBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("uri", "test-uri")
.withEntry("client-id", "test-client-id")
.withEntry("client-secret", "test-client-secret")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.CouchbaseBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.CouchbaseBindingsPropertiesProcessor.TYPE;
@DisplayName("Couchbase BindingsPropertiesProcessor")
final class CouchbaseBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("bootstrap-hosts", "test-bootstrap-hosts")
.withEntry("bucket.name", "test-bucket-name")
.withEntry("bucket.password", "test-bucket-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.Db2BindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.Db2BindingsPropertiesProcessor.TYPE;
@DisplayName("DB2 BindingsPropertiesProcessor")
final class Db2BindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("database", "test-database")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.ElasticsearchBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.ElasticsearchBindingsPropertiesProcessor.TYPE;
@DisplayName("Elasticsearch BindingsPropertiesProcessor")
final class ElasticsearchBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("endpoints", "test-endpoints")
.withEntry("password", "test-password")
.withEntry("use-ssl", "test-use-ssl")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.EurekaBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.EurekaBindingsPropertiesProcessor.TYPE;
@DisplayName("Eureka BindingsPropertiesProcessor")
final class EurekaBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("uri", "test-uri")
.withEntry("client-id", "test-client-id")
.withEntry("client-secret", "test-client-secret")

View File

@@ -23,7 +23,7 @@ import org.springframework.mock.env.MockEnvironment;
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;
import static org.springframework.cloud.bindings.boot.Guards.isTypeEnabled;
@DisplayName("Guards")
final class GuardsTest {
@@ -57,29 +57,29 @@ final class GuardsTest {
}
@Nested
@DisplayName("Kind Guard")
final class KindGuard {
@DisplayName("Type Guard")
final class TypeGuard {
private final MockEnvironment environment = new MockEnvironment();
@Test
@DisplayName("returns true if unset")
void unset() {
assertThat(isKindEnabled(environment, "Test")).isTrue();
assertThat(isTypeEnabled(environment, "Test")).isTrue();
}
@Test
@DisplayName("returns the set value of true")
void setTrue() {
environment.setProperty("org.springframework.cloud.bindings.boot.test.enable", "true");
assertThat(isKindEnabled(environment, "Test")).isTrue();
assertThat(isTypeEnabled(environment, "Test")).isTrue();
}
@Test
@DisplayName("returns the set value of false")
void setFalse() {
environment.setProperty("org.springframework.cloud.bindings.boot.test.enable", "false");
assertThat(isKindEnabled(environment, "Test")).isFalse();
assertThat(isTypeEnabled(environment, "Test")).isFalse();
}
}

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.KafkaBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.KafkaBindingsPropertiesProcessor.TYPE;
@DisplayName("Kafka BindingsPropertiesProcessor")
final class KafkaBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("bootstrap-servers", "test-bootstrap-servers")
.withEntry("consumer.bootstrap-servers", "test-consumer-bootstrap-servers")
.withEntry("producer.bootstrap-servers", "test-producer-bootstrap-servers")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.LDAPBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.LDAPBindingsPropertiesProcessor.TYPE;
@DisplayName("LDAP BindingsPropertiesProcessor")
final class LDAPBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("urls", "test-urls")
.withEntry("password", "test-password")
.withEntry("username", "test-username")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.MongoDbBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.MongoDbBindingsPropertiesProcessor.TYPE;
@DisplayName("MongoDB BindingsPropertiesProcessor")
final class MongoDbBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("authentication-database", "test-authentication-database")
.withEntry("database", "test-database")
.withEntry("grid-fs-database", "test-grid-fs-database")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.MySqlBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.MySqlBindingsPropertiesProcessor.TYPE;
@DisplayName("MySQL BindingsPropertiesProcessor")
final class MySqlBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("database", "test-database")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.Neo4JBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.Neo4JBindingsPropertiesProcessor.TYPE;
@DisplayName("Neo4J BindingsPropertiesProcessor")
final class Neo4JBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("password", "test-password")
.withEntry("uri", "test-uri")
.withEntry("username", "test-username")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.OracleBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.OracleBindingsPropertiesProcessor.TYPE;
@DisplayName("Oracle BindingsPropertiesProcessor")
final class OracleBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("database", "test-database")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.PostgreSqlBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.PostgreSqlBindingsPropertiesProcessor.TYPE;
@DisplayName("PostgreSQL BindingsPropertiesProcessor")
final class PostgreSqlBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("database", "test-database")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.RabbitMqBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.RabbitMqBindingsPropertiesProcessor.TYPE;
@DisplayName("RabbitMQ BindingsPropertiesProcessor")
final class RabbitMqBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("addresses", "test-addresses")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.RedisBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.RedisBindingsPropertiesProcessor.TYPE;
@DisplayName("Redis BindingsPropertiesProcessor")
final class RedisBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("client-name", "test-client-name")
.withEntry("cluster.max-redirects", "test-cluster-max-redirects")
.withEntry("cluster.nodes", "test-cluster-nodes")

View File

@@ -27,7 +27,7 @@ import java.nio.file.Paths;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.SpringSecurityOAuth2BindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.SpringSecurityOAuth2BindingsPropertiesProcessor.TYPE;
@DisplayName("Spring Security OAuth2 BindingsPropertiesProcessor")
final class SpringSecurityOAuth2BindingsPropertiesProcessorTest {
@@ -35,26 +35,23 @@ final class SpringSecurityOAuth2BindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name-1", Paths.get("test-path"),
new FluentMap()
.withEntry("kind", KIND)
.withEntry("provider", "github"),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("provider", "github")
.withEntry("client-id", "github-client-id")
.withEntry("client-secret", "github-client-secret")
),
new Binding("test-name-2", Paths.get("test-path"),
new FluentMap()
.withEntry("kind", KIND)
.withEntry("provider", "okta"),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("provider", "okta")
.withEntry("client-id", "okta-client-id")
.withEntry("client-secret", "okta-client-secret")
.withEntry("issuer-uri", "okta-issuer-uri")
),
new Binding("test-name-3", Paths.get("test-path"),
new FluentMap()
.withEntry("kind", KIND)
.withEntry("provider", "my-provider"),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("provider", "my-provider")
.withEntry("client-id", "my-provider-client-id")
.withEntry("client-secret", "my-provider-client-secret")
.withEntry("authorization-uri", "my-provider-authorization-uri")
@@ -67,8 +64,7 @@ final class SpringSecurityOAuth2BindingsPropertiesProcessorTest {
// Don't crash when provider is missing
new Binding("test-missing-provider", Paths.get("test-path"),
new FluentMap()
.withEntry("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("client-id", "my-provider-client-id")
)
);

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.SqlServerBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.SqlServerBindingsPropertiesProcessor.TYPE;
@DisplayName("SQLServer BindingsPropertiesProcessor")
final class SqlServerBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("database", "test-database")
.withEntry("host", "test-host")
.withEntry("password", "test-password")

View File

@@ -27,122 +27,10 @@ import java.nio.file.Paths;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.VaultBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.VaultBindingsPropertiesProcessor.TYPE;
@DisplayName("Vault BindingsPropertiesProcessor")
final class VaultPropertiesProcessorTest {
private FluentMap baseSecret() {
return new FluentMap()
.withEntry("namespace", "test-namespace")
.withEntry("uri", "test-uri");
}
private FluentMap metadata() {
return new FluentMap()
.withEntry("kind", KIND);
}
private final Binding tokenBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "token")
.withEntry("token", "test-token")
);
private final Binding appRoleBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("app-role-path", "test-app-role-path")
.withEntry("authentication-method", "approle")
.withEntry("role", "test-role")
.withEntry("role-id", "test-role-id")
.withEntry("secret-id", "test-secret-id")
);
private final Binding cubbyholeBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "cubbyhole")
.withEntry("token", "test-token")
);
private final Binding certBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "cert")
.withEntry("cert-auth-path", "test-cert-auth-path")
.withEntry("key-store-password", "test-key-store-password")
.withEntry("keystore.jks", "key store contents!")
);
private final Binding awsEc2Binding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "aws_ec2")
.withEntry("aws-ec2-instance-identity-document", "test-identity-document")
.withEntry("nonce", "test-nonce")
.withEntry("aws-ec2-path", "test-aws-ec2-path")
.withEntry("role", "test-role")
);
private final Binding awsIamBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "aws_iam")
.withEntry("aws-iam-server-id", "test-server-id")
.withEntry("aws-path", "test-aws-path")
.withEntry("aws-sts-endpoint-uri", "test-endpoint-uri")
.withEntry("role", "test-role")
);
private final Binding azureMsiBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "azure_msi")
.withEntry("azure-path", "test-azure-path")
.withEntry("role", "test-role")
);
private final Binding gcpGceBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "gcp_gce")
.withEntry("gcp-path", "test-gcp-path")
.withEntry("gcp-service-account", "test-service-account")
.withEntry("role", "test-role")
);
private final Binding gcpIamBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "gcp_iam")
.withEntry("credentials.json", "credentials JSON contents!")
.withEntry("encoded-key", "test-encoded-key")
.withEntry("gcp-path", "test-gcp-path")
.withEntry("gcp-project-id", "test-project-id")
.withEntry("gcp-service-account", "test-service-account")
.withEntry("jwt-validity", "test-jwt-validity")
.withEntry("role", "test-role")
);
private final Binding k8sBinding = new Binding(
"test-name", Paths.get("test-path"),
metadata(),
baseSecret()
.withEntry("authentication-method", "kubernetes")
.withEntry("role", "test-role")
.withEntry("kubernetes-path", "test-kubernetes-path")
);
final class VaultBindingsPropertiesProcessorTest {
private final MockEnvironment environment = new MockEnvironment();
@@ -151,7 +39,15 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports token authentication")
void testTokenAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(tokenBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "token")
.withEntry("token", "test-token")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -162,7 +58,18 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports AppRole authentication")
void testAppRoleAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(appRoleBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("app-role-path", "test-app-role-path")
.withEntry("authentication-method", "approle")
.withEntry("role", "test-role")
.withEntry("role-id", "test-role-id")
.withEntry("secret-id", "test-secret-id")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -176,7 +83,15 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports cubbyhole authentication")
void testCubbyholeAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(cubbyholeBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "cubbyhole")
.withEntry("token", "test-token")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -187,12 +102,22 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports TLS certificate authentication")
void testCertAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(certBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "cert")
.withEntry("cert-auth-path", "test-cert-auth-path")
.withEntry("key-store-password", "test-key-store-password")
.withEntry("keystore.jks", "key store contents!")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
.containsEntry("spring.cloud.vault.authentication", "cert")
.containsEntry("spring.cloud.vault.ssl.key-store", "test-path/secret/keystore.jks")
.containsEntry("spring.cloud.vault.ssl.key-store", "test-path/keystore.jks")
.containsEntry("spring.cloud.vault.ssl.key-store-password", "test-key-store-password")
.containsEntry("spring.cloud.vault.ssl.cert-auth-path", "test-cert-auth-path");
}
@@ -200,7 +125,18 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports AWS EC2 authentication")
void testAwsEc2Authentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(awsEc2Binding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "aws_ec2")
.withEntry("aws-ec2-instance-identity-document", "test-identity-document")
.withEntry("nonce", "test-nonce")
.withEntry("aws-ec2-path", "test-aws-ec2-path")
.withEntry("role", "test-role")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -214,7 +150,18 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports AWS IAM authentication")
void testAwsIamAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(awsIamBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "aws_iam")
.withEntry("aws-iam-server-id", "test-server-id")
.withEntry("aws-path", "test-aws-path")
.withEntry("aws-sts-endpoint-uri", "test-endpoint-uri")
.withEntry("role", "test-role")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -228,7 +175,16 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports Azure MSI authentication")
void testAzureMsiAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(azureMsiBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "azure_msi")
.withEntry("azure-path", "test-azure-path")
.withEntry("role", "test-role")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -240,7 +196,17 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports GCP GCE authentication")
void testGcpGceAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(gcpGceBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "gcp_gce")
.withEntry("gcp-path", "test-gcp-path")
.withEntry("gcp-service-account", "test-service-account")
.withEntry("role", "test-role")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -253,13 +219,27 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports GCP IAM authentication")
void testGcpIamAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(gcpIamBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "gcp_iam")
.withEntry("credentials.json", "credentials JSON contents!")
.withEntry("encoded-key", "test-encoded-key")
.withEntry("gcp-path", "test-gcp-path")
.withEntry("gcp-project-id", "test-project-id")
.withEntry("gcp-service-account", "test-service-account")
.withEntry("jwt-validity", "test-jwt-validity")
.withEntry("role", "test-role")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
.containsEntry("spring.cloud.vault.authentication", "gcp_iam")
.containsEntry("spring.cloud.vault.gcp-iam.role", "test-role")
.containsEntry("spring.cloud.vault.gcp-iam.credentials.location", "test-path/secret/credentials.json")
.containsEntry("spring.cloud.vault.gcp-iam.credentials.location", "test-path/credentials.json")
.containsEntry("spring.cloud.vault.gcp-iam.credentials.encoded-key", "test-encoded-key")
.containsEntry("spring.cloud.vault.gcp-iam.gcp-path", "test-gcp-path")
.containsEntry("spring.cloud.vault.gcp-iam.jwt-validity", "test-jwt-validity")
@@ -270,7 +250,16 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Supports Kubernetes authentication")
void testK8sAuthentication() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(k8sBinding), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "kubernetes")
.withEntry("role", "test-role")
.withEntry("kubernetes-path", "test-kubernetes-path")
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
@@ -282,33 +271,62 @@ final class VaultPropertiesProcessorTest {
@Test
@DisplayName("Doesn't fail when method is missing")
void testMissingProvider() {
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(new Binding(
"test-name",
Paths.get("test-path"),
metadata(),
baseSecret()
)), properties);
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
)
);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties)
.containsEntry("spring.cloud.vault.uri", "test-uri")
.containsEntry("spring.cloud.vault.namespace", "test-namespace")
.doesNotContainKey("spring.cloud.vault.authentication");
}
//Vault agent authentication can be configured using a sidecar and should not require a binding
@Test
@DisplayName("can be disabled")
void disabled() {
Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "token")
.withEntry("token", "test-token")
),
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("app-role-path", "test-app-role-path")
.withEntry("authentication-method", "approle")
.withEntry("role", "test-role")
.withEntry("role-id", "test-role-id")
.withEntry("secret-id", "test-secret-id")
),
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "cubbyhole")
.withEntry("token", "test-token")
),
new Binding("test-name", Paths.get("test-path"),
baseSecret()
.withEntry("authentication-method", "cert")
.withEntry("cert-auth-path", "test-cert-auth-path")
.withEntry("key-store-password", "test-key-store-password")
.withEntry("keystore.jks", "key store contents!")
)
);
environment.setProperty("org.springframework.cloud.bindings.boot.vault.enable", "false");
new VaultBindingsPropertiesProcessor().process(environment, new Bindings(
tokenBinding,
appRoleBinding,
cubbyholeBinding,
certBinding
), properties);
new VaultBindingsPropertiesProcessor().process(environment, bindings, properties);
assertThat(properties).isEmpty();
}
private FluentMap baseSecret() {
return new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("namespace", "test-namespace")
.withEntry("uri", "test-uri");
}
}

View File

@@ -24,19 +24,18 @@ import org.springframework.cloud.bindings.FluentMap;
import org.springframework.mock.env.MockEnvironment;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.bindings.boot.WavefrontBindingsPropertiesProcessor.KIND;
import static org.springframework.cloud.bindings.boot.WavefrontBindingsPropertiesProcessor.TYPE;
@DisplayName("Wavefront BindingsPropertiesProcessor")
final class WavefrontPropertiesProcessorTest {
final class WavefrontBindingsPropertiesProcessorTest {
private final Bindings bindings = new Bindings(
new Binding("test-name", Paths.get("test-path"),
Collections.singletonMap("kind", KIND),
new FluentMap()
.withEntry(Binding.TYPE, TYPE)
.withEntry("api-token", "test-api-token")
.withEntry("uri", "test-uri")
)

View File

@@ -0,0 +1 @@
test-metadata-value

View File

@@ -0,0 +1 @@
.hidden-data/test-metadata-key

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
.hidden-data/test-secret-key

View File

@@ -0,0 +1 @@
test-metadata-value

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
test-metadata-value

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
.hidden-data-1

View File

@@ -0,0 +1 @@
test-provider-1

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
test-type-1

View File

@@ -0,0 +1 @@
.hidden-data/provider

View File

@@ -0,0 +1 @@
.hidden-data/test-secret-key

View File

@@ -0,0 +1 @@
.hidden-data/type

View File

@@ -0,0 +1 @@
test-provider-1

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
test-type-1

View File

@@ -0,0 +1 @@
test-provider-2

View File

@@ -0,0 +1 @@
test-secret-value

View File

@@ -0,0 +1 @@
test-type-2

View File

@@ -1 +0,0 @@
test-value

View File

@@ -1 +0,0 @@
.hidden-data/test-key

View File

@@ -1 +0,0 @@
test-value

View File

@@ -1 +0,0 @@
test-value