Labeled secrets prefix support (#1017)
This commit is contained in:
@@ -409,6 +409,71 @@ will result in three properties being generated:
|
||||
|
||||
- `config-map-three.greetings.message` equal to `Say Hello from three`.
|
||||
|
||||
The same way you configure a prefix for configmaps, you can do it for secrets also; both for secrets that are based on name
|
||||
and the ones based on labels. For example:
|
||||
|
||||
====
|
||||
[source.yaml]
|
||||
----
|
||||
spring:
|
||||
application:
|
||||
name: prefix-based-secrets
|
||||
cloud:
|
||||
kubernetes:
|
||||
secrets:
|
||||
enableApi: true
|
||||
useNameAsPrefix: true
|
||||
namespace: spring-k8s
|
||||
sources:
|
||||
- labels:
|
||||
letter: a
|
||||
useNameAsPrefix: false
|
||||
- labels:
|
||||
letter: b
|
||||
explicitPrefix: two
|
||||
- labels:
|
||||
letter: c
|
||||
- labels:
|
||||
letter: d
|
||||
useNameAsPrefix: true
|
||||
- name: my-secret
|
||||
----
|
||||
====
|
||||
|
||||
The same processing rules apply when generating property source as for config maps. The only difference is that
|
||||
potentially, looking up secrets by labels can mean that we find more than one source. In such a case, prefix (if specified via `useNameAsPrefix`)
|
||||
will be the names of all secrets found for those particular labels.
|
||||
|
||||
One more thing to bear in mind is that we support `prefix` per _source_, not per secret. The easiest way to explain this is via an example:
|
||||
|
||||
====
|
||||
[source.yaml]
|
||||
----
|
||||
spring:
|
||||
application:
|
||||
name: prefix-based-secrets
|
||||
cloud:
|
||||
kubernetes:
|
||||
secrets:
|
||||
enableApi: true
|
||||
useNameAsPrefix: true
|
||||
namespace: spring-k8s
|
||||
sources:
|
||||
- labels:
|
||||
color: blue
|
||||
useNameAsPrefix: true
|
||||
----
|
||||
====
|
||||
|
||||
Suppose that a query matching such a label will provide two secrets as a result: `secret-a` and `secret-b`.
|
||||
Both of these secrets have the same property name: `color=sea-blue` and `color=ocean-blue`. It is undefined which
|
||||
`color` will end-up as part of property sources, but the prefix for it will be `secret-a.secret-b`
|
||||
(concatenated sorted naturally, names of the secrets).
|
||||
|
||||
If you need more fine-grained results, adding more labels to identify the secret uniquely would be an option.
|
||||
|
||||
|
||||
|
||||
By default, besides reading the config map that is specified in the `sources` configuration, Spring will also try to read
|
||||
all properties from "profile aware" sources. The easiest way to explain this is via an example. Let's suppose your application
|
||||
enables a profile called "dev" and you have a configuration like the one below:
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.springframework.cloud.kubernetes.client.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -29,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.PrefixContext;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
|
||||
import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.dataFromSecret;
|
||||
@@ -66,9 +69,10 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Kuberne
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
LabeledSecretNormalizedSource source = (LabeledSecretNormalizedSource) context.normalizedSource();
|
||||
Set<String> propertySourceNames = new LinkedHashSet<>();
|
||||
Map<String, String> labels = source.labels();
|
||||
String namespace = context.namespace();
|
||||
String sourceName = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, labels.keySet());
|
||||
String sourceNameFromLabels = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, labels.keySet());
|
||||
|
||||
try {
|
||||
|
||||
@@ -77,10 +81,42 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Kuberne
|
||||
createLabelsSelector(labels), null, null, null, null, null).getItems();
|
||||
|
||||
if (!secrets.isEmpty()) {
|
||||
sourceName = secrets.stream().map(V1Secret::getMetadata).map(V1ObjectMeta::getName)
|
||||
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
|
||||
|
||||
secrets.forEach(s -> result.putAll(dataFromSecret(s, namespace)));
|
||||
for (V1Secret secret : secrets) {
|
||||
// we support prefix per source, not per secret. This means that
|
||||
// in theory
|
||||
// we can still have clashes here, that we simply override.
|
||||
// If there are more than one secret found per labels, and they
|
||||
// have the same key on a
|
||||
// property, but different values; one value will override the
|
||||
// other, without any particular order.
|
||||
result.putAll(dataFromSecret(secret, namespace));
|
||||
}
|
||||
|
||||
String secretNames = secrets.stream().map(V1Secret::getMetadata).map(V1ObjectMeta::getName).sorted()
|
||||
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
|
||||
propertySourceNames.add(secretNames);
|
||||
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||
|
||||
String prefix;
|
||||
if (source.prefix() == ConfigUtils.Prefix.KNOWN) {
|
||||
prefix = source.prefix().prefixProvider().get();
|
||||
}
|
||||
else {
|
||||
// prefix is going to be all the secret names we found based
|
||||
// on the labels
|
||||
// concatenated with PROPERTY_SOURCE_NAME_SEPARATOR
|
||||
prefix = secretNames;
|
||||
}
|
||||
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
|
||||
String names = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, propertySourceNames);
|
||||
return new SourceData(ConfigUtils.sourceName(source.target(), names, namespace), result);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -89,8 +125,12 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Kuberne
|
||||
onException(source.failFast(), message, e);
|
||||
}
|
||||
|
||||
String propertySourceName = ConfigUtils.sourceName(source.target(), sourceName, namespace);
|
||||
return new SourceData(propertySourceName, result);
|
||||
// if we could not find a secret with provided labels, we will compute a
|
||||
// response with an empty Map
|
||||
// and name that will use all the label names (not their values)
|
||||
String propertySourceNameFromLabels = ConfigUtils.sourceName(source.target(), sourceNameFromLabels,
|
||||
namespace);
|
||||
return new SourceData(propertySourceNameFromLabels, result);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -104,9 +104,10 @@ final class NamedConfigMapContextToSourceDataProvider implements Supplier<Kubern
|
||||
propertySourceNames.add(entry.getValue());
|
||||
});
|
||||
|
||||
if (!"".equals(source.prefix())) {
|
||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
||||
propertySourceNames);
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||
// since we are in a named source, calling get on the supplier is safe
|
||||
String prefix = source.prefix().prefixProvider().get();
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,9 +72,10 @@ final class NamedSecretContextToSourceDataProvider implements Supplier<Kubernete
|
||||
|
||||
secret.ifPresent(s -> result.putAll(dataFromSecret(s, namespace)));
|
||||
|
||||
if (!"".equals(source.prefix()) && !result.isEmpty()) {
|
||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
||||
propertySourceNames);
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT && !result.isEmpty()) {
|
||||
// since we are in a named source, calling get on the supplier is safe
|
||||
String prefix = source.prefix().prefixProvider().get();
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
@@ -100,7 +101,7 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, "", true);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||
@@ -121,7 +122,7 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(YAML_CONFIGMAP_LIST))));
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-641", "default", false, "", true);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-641", "default", false, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||
@@ -142,7 +143,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, "prefix", true);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("prefix", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, prefix, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||
@@ -161,7 +163,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
@Test
|
||||
void constructorWithNamespaceMustNotFail() {
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, "prefix", true);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("prefix", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("bootstrap-640", "default", false, prefix, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -173,7 +176,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("my-config", "default", true, "prefix", true);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("prefix", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("my-config", "default", true, prefix, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -188,7 +192,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("my-config", "default", false, "prefix", true);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("prefix", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("my-config", "default", false, prefix, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRET_LIST))));
|
||||
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("db-secret", "default", false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("db-secret", "default", false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -151,7 +151,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
||||
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("secret", "default", true, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("secret", "default", true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -166,7 +166,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
||||
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("secret", "db-secret", false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("secret", "db-secret", false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||
new MockEnvironment());
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.kubernetes.client.config;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,6 +37,7 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
@@ -193,4 +195,93 @@ class LabeledSecretContextToSourceDataProviderTests {
|
||||
Assertions.assertEquals(sourceData.sourceData(), Map.of("color", "really-red"));
|
||||
}
|
||||
|
||||
/**
|
||||
* one secret with name : "blue-secret" and labels "color=blue" is deployed. we search
|
||||
* it with the same labels, find it, and assert that name of the SourceData (it must
|
||||
* use its name, not its labels) and values in the SourceData must be prefixed (since
|
||||
* we have provided an explicit prefix).
|
||||
*/
|
||||
@Test
|
||||
void testWithPrefix() {
|
||||
|
||||
V1SecretList SECRETS_LIST = new V1SecretList().addItemsItem(new V1SecretBuilder()
|
||||
.withMetadata(new V1ObjectMetaBuilder().withLabels(Map.of("color", "blue")).withNamespace(NAMESPACE)
|
||||
.withResourceVersion("1").withName("blue-secret").build())
|
||||
.addToData("what-color", "blue-color".getBytes()).build());
|
||||
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/secrets?labelSelector=color%3Dblue")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRETS_LIST))));
|
||||
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("me", false, false, null);
|
||||
NormalizedSource source = new LabeledSecretNormalizedSource(NAMESPACE, Map.of("color", "blue"), false, prefix);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
KubernetesClientContextToSourceData data = new LabeledSecretContextToSourceDataProvider().get();
|
||||
SourceData sourceData = data.apply(context);
|
||||
|
||||
Assertions.assertEquals("secret.blue-secret.default", sourceData.sourceName());
|
||||
Assertions.assertEquals(Map.of("me.what-color", "blue-color"), sourceData.sourceData());
|
||||
}
|
||||
|
||||
/**
|
||||
* two secrets are deployed (name:blue-secret, name:another-blue-secret) and labels
|
||||
* "color=blue" (on both). we search with the same labels, find them, and assert that
|
||||
* name of the SourceData (it must use its name, not its labels) and values in the
|
||||
* SourceData must be prefixed (since we have provided a delayed prefix).
|
||||
*
|
||||
* Also notice that the prefix is made up from both secret names.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
void testTwoSecretsWithPrefix() {
|
||||
V1SecretList SECRETS_LIST = new V1SecretList()
|
||||
.addItemsItem(
|
||||
new V1SecretBuilder()
|
||||
.withMetadata(
|
||||
new V1ObjectMetaBuilder().withLabels(Map.of("color", "blue"))
|
||||
.withNamespace(NAMESPACE).withResourceVersion("1").withName(
|
||||
"blue-secret")
|
||||
.build())
|
||||
.addToData("first", "blue".getBytes()).build())
|
||||
.addItemsItem(new V1SecretBuilder()
|
||||
.withMetadata(
|
||||
new V1ObjectMetaBuilder().withLabels(Map.of("color", "blue")).withNamespace(NAMESPACE)
|
||||
.withResourceVersion("1").withName("another-blue-secret").build())
|
||||
.addToData("second", "blue".getBytes()).build());
|
||||
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/secrets?labelSelector=color%3Dblue")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRETS_LIST))));
|
||||
|
||||
NormalizedSource source = new LabeledSecretNormalizedSource(NAMESPACE, Map.of("color", "blue"), false, ConfigUtils.Prefix.DELAYED);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
KubernetesClientContextToSourceData data = new LabeledSecretContextToSourceDataProvider().get();
|
||||
SourceData sourceData = data.apply(context);
|
||||
|
||||
// maps don't have a defined order, so assert components separately
|
||||
Assertions.assertEquals(46, sourceData.sourceName().length());
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("blue-secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("another-blue-secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("default"));
|
||||
|
||||
Map<String, Object> properties = sourceData.sourceData();
|
||||
Assertions.assertEquals(2, properties.size());
|
||||
Iterator<String> keys = properties.keySet().iterator();
|
||||
String firstKey = keys.next();
|
||||
String secondKey = keys.next();
|
||||
|
||||
if (firstKey.contains("first")) {
|
||||
Assertions.assertEquals(firstKey, "another-blue-secret.blue-secret.first");
|
||||
}
|
||||
|
||||
Assertions.assertEquals(secondKey, "another-blue-secret.blue-secret.second");
|
||||
Assertions.assertEquals(properties.get(firstKey), "blue");
|
||||
Assertions.assertEquals(properties.get(secondKey), "blue");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
@@ -90,7 +91,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(BLUE_CONFIG_MAP_NAME, NAMESPACE, true, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(BLUE_CONFIG_MAP_NAME, NAMESPACE, true, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -119,7 +120,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -154,7 +155,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, "", true);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, true);
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setActiveProfiles("with-profile");
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE, environment);
|
||||
@@ -194,7 +195,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, "some",
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("some", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, prefix,
|
||||
true);
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setActiveProfiles("with-profile");
|
||||
@@ -241,7 +243,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, "some",
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("some", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true, prefix,
|
||||
true);
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setActiveProfiles("with-taste", "with-shape");
|
||||
@@ -271,7 +274,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, "some", false);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("some", false, false, null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, prefix, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -302,7 +306,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
CoreV1Api api = new CoreV1Api();
|
||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE + "nope", true, "",
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE + "nope", true,
|
||||
false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -84,7 +84,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||
|
||||
// blue does not match red
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE, false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -125,7 +125,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||
|
||||
// blue does not match red
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE, false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -156,7 +156,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||
|
||||
// blue does not match red
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("blue", NAMESPACE, false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("blue", NAMESPACE, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -182,7 +182,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||
|
||||
// blue does not match red
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE + "nope", false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource("red", NAMESPACE + "nope", false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Four;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.One;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Three;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Two;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties({ One.class, Two.class, Three.class, Four.class })
|
||||
public class LabeledSecretWithPrefixApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LabeledSecretWithPrefixApp.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2013-2022 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* @author wind57
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = LabeledSecretWithPrefixApp.class,
|
||||
properties = { "spring.cloud.bootstrap.name=labeled-secret-with-prefix", "labeled.secret.with.prefix.stub=true",
|
||||
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.bootstrap.enabled=true",
|
||||
"spring.cloud.kubernetes.client.namespace=spring-k8s" })
|
||||
class LabeledSecretWithPrefixBootstrapTests extends LabeledSecretWithPrefixTests {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2013-2022 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import io.kubernetes.client.util.ClientBuilder;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.kubernetes.client.KubernetesClientUtils;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.springframework.cloud.kubernetes.client.config.boostrap.stubs.LabeledSecretWithPrefixConfigurationStub.stubData;
|
||||
|
||||
/**
|
||||
* @author wind57
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = LabeledSecretWithPrefixApp.class,
|
||||
properties = { "spring.cloud.application.name=labeled-secret-with-prefix",
|
||||
"labeled.secret.with.prefix.stub=true", "spring.main.cloud-platform=KUBERNETES",
|
||||
"spring.config.import=kubernetes:,classpath:./labeled-secret-with-prefix.yaml",
|
||||
"spring.cloud.kubernetes.client.namespace=spring-k8s" })
|
||||
class LabeledSecretWithPrefixConfigDataTests extends LabeledSecretWithPrefixTests {
|
||||
|
||||
private static MockedStatic<KubernetesClientUtils> clientUtilsMock;
|
||||
|
||||
@BeforeAll
|
||||
static void wireMock() {
|
||||
WireMockServer server = new WireMockServer(options().dynamicPort());
|
||||
server.start();
|
||||
WireMock.configureFor("localhost", server.port());
|
||||
clientUtilsMock = mockStatic(KubernetesClientUtils.class);
|
||||
clientUtilsMock.when(KubernetesClientUtils::kubernetesApiClient)
|
||||
.thenReturn(new ClientBuilder().setBasePath(server.baseUrl()).build());
|
||||
stubData();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void teardown() {
|
||||
clientUtilsMock.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2013-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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix;
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.kubernetes.client.config.boostrap.stubs.LabeledSecretWithPrefixConfigurationStub;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
/**
|
||||
* The stub data for this test is in : {@link LabeledSecretWithPrefixConfigurationStub}
|
||||
*
|
||||
* @author wind57
|
||||
*/
|
||||
abstract class LabeledSecretWithPrefixTests {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webClient;
|
||||
|
||||
@AfterEach
|
||||
void afterEach() {
|
||||
WireMock.reset();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void afterAll() {
|
||||
WireMock.shutdownServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[0].useNameAsPrefix=false'
|
||||
* ("one.property", "one")
|
||||
*
|
||||
* As such: @ConfigurationProperties("one")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testOne() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/one").exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(Matchers.equalTo("one"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[1].explicitPrefix=two'
|
||||
* ("property", "two")
|
||||
*
|
||||
* As such: @ConfigurationProperties("two")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testTwo() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/two").exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(Matchers.equalTo("two"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[2].labels=letter:c'
|
||||
* ("property", "three")
|
||||
*
|
||||
* We find the secret by labels, and use it's name as the prefix.
|
||||
*
|
||||
* As such: @ConfigurationProperties(prefix = "secret-three")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testThree() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/three").exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(Matchers.equalTo("three"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[3].labels=letter:d'
|
||||
* ("property", "four")
|
||||
*
|
||||
* We find the secret by labels, and use it's name as the prefix.
|
||||
*
|
||||
* As such: @ConfigurationProperties(prefix = "secret-four")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testFour() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/four").exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(Matchers.equalTo("four"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2013-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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix.controller;
|
||||
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Four;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.One;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Three;
|
||||
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_prefix.properties.Two;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class LabeledSecretWithPrefixController {
|
||||
|
||||
private final One one;
|
||||
|
||||
private final Two two;
|
||||
|
||||
private final Three three;
|
||||
|
||||
private final Four four;
|
||||
|
||||
public LabeledSecretWithPrefixController(One one, Two two, Three three, Four four) {
|
||||
this.one = one;
|
||||
this.two = two;
|
||||
this.three = three;
|
||||
this.four = four;
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/one")
|
||||
public String one() {
|
||||
return one.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/two")
|
||||
public String two() {
|
||||
return two.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/three")
|
||||
public String three() {
|
||||
return three.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/four")
|
||||
public String four() {
|
||||
return four.getProperty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "secret-four")
|
||||
public class Four {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("one")
|
||||
public class One {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "secret-three")
|
||||
public class Three {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.applications.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("two")
|
||||
public class Two {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,8 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = NamedSecretWithPrefixApp.class,
|
||||
properties = { "spring.cloud.bootstrap.name=named-secret-with-prefix", "named.secret.with.prefix.stub=true",
|
||||
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.bootstrap.enabled=true" })
|
||||
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.bootstrap.enabled=true",
|
||||
"spring.cloud.kubernetes.client.namespace=spring-k8s" })
|
||||
class NamedSecretWithPrefixBootstrapTests extends NamedSecretWithPrefixTests {
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ import static org.springframework.cloud.kubernetes.client.config.boostrap.stubs.
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = NamedSecretWithPrefixApp.class,
|
||||
properties = { "spring.cloud.application.name=named-secret-with-prefix", "named.secret.with.prefix.stub=true",
|
||||
"spring.main.cloud-platform=KUBERNETES",
|
||||
"spring.config.import=kubernetes:,classpath:./named-secret-with-prefix.yaml" })
|
||||
"spring.config.import=kubernetes:,classpath:./named-secret-with-prefix.yaml",
|
||||
"spring.cloud.kubernetes.client.namespace=spring-k8s" })
|
||||
class NamedSecretWithPrefixConfigDataTests extends NamedSecretWithPrefixTests {
|
||||
|
||||
private static MockedStatic<KubernetesClientUtils> clientUtilsMock;
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2013-2022 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
|
||||
*
|
||||
* https://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.kubernetes.client.config.boostrap.stubs;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import io.kubernetes.client.openapi.ApiClient;
|
||||
import io.kubernetes.client.openapi.JSON;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1Secret;
|
||||
import io.kubernetes.client.openapi.models.V1SecretBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1SecretList;
|
||||
import io.kubernetes.client.util.ClientBuilder;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
|
||||
|
||||
/**
|
||||
* A test bootstrap that takes care to initialize ApiClient _before_ our main bootstrap
|
||||
* context; with some stub data already present.
|
||||
*
|
||||
* @author wind57
|
||||
*/
|
||||
@Order(0)
|
||||
@Configuration
|
||||
@ConditionalOnProperty("labeled.secret.with.prefix.stub")
|
||||
public class LabeledSecretWithPrefixConfigurationStub {
|
||||
|
||||
@Bean
|
||||
public WireMockServer wireMock() {
|
||||
WireMockServer server = new WireMockServer(options().dynamicPort());
|
||||
server.start();
|
||||
WireMock.configureFor("localhost", server.port());
|
||||
return server;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApiClient apiClient(WireMockServer wireMockServer) {
|
||||
ApiClient apiClient = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
|
||||
io.kubernetes.client.openapi.Configuration.setDefaultApiClient(apiClient);
|
||||
apiClient.setDebugging(true);
|
||||
stubData();
|
||||
return apiClient;
|
||||
}
|
||||
|
||||
public static void stubData() {
|
||||
V1Secret one = new V1SecretBuilder()
|
||||
.withMetadata(new V1ObjectMetaBuilder().withName("secret-one").withNamespace("spring-k8s")
|
||||
.withLabels(Map.of("letter", "a")).withResourceVersion("1").build())
|
||||
.addToData(Collections.singletonMap("one.property", "one".getBytes())).build();
|
||||
|
||||
V1Secret two = new V1SecretBuilder()
|
||||
.withMetadata(new V1ObjectMetaBuilder().withName("secret-two").withNamespace("spring-k8s")
|
||||
.withLabels(Map.of("letter", "b")).withResourceVersion("1").build())
|
||||
.addToData(Collections.singletonMap("property", "two".getBytes())).build();
|
||||
|
||||
V1Secret three = new V1SecretBuilder()
|
||||
.withMetadata(new V1ObjectMetaBuilder().withName("secret-three").withNamespace("spring-k8s")
|
||||
.withLabels(Map.of("letter", "c")).withResourceVersion("1").build())
|
||||
.addToData(Collections.singletonMap("property", "three".getBytes())).build();
|
||||
|
||||
V1Secret four = new V1SecretBuilder()
|
||||
.withMetadata(new V1ObjectMetaBuilder().withName("secret-four").withNamespace("spring-k8s")
|
||||
.withLabels(Map.of("letter", "d")).withResourceVersion("1").build())
|
||||
.addToData(Collections.singletonMap("property", "four".getBytes())).build();
|
||||
|
||||
// the actual stub for CoreV1Api calls
|
||||
V1SecretList oneSecrets = new V1SecretList();
|
||||
oneSecrets.addItemsItem(one);
|
||||
WireMock.stubFor(WireMock.get("/api/v1/namespaces/spring-k8s/secrets?labelSelector=letter%3Da")
|
||||
.willReturn(WireMock.aResponse().withStatus(200).withBody(new JSON().serialize(oneSecrets))));
|
||||
|
||||
V1SecretList twoSecrets = new V1SecretList();
|
||||
twoSecrets.addItemsItem(two);
|
||||
WireMock.stubFor(WireMock.get("/api/v1/namespaces/spring-k8s/secrets?labelSelector=letter%3Db")
|
||||
.willReturn(WireMock.aResponse().withStatus(200).withBody(new JSON().serialize(twoSecrets))));
|
||||
|
||||
V1SecretList threeSecrets = new V1SecretList();
|
||||
threeSecrets.addItemsItem(three);
|
||||
WireMock.stubFor(WireMock.get("/api/v1/namespaces/spring-k8s/secrets?labelSelector=letter%3Dc")
|
||||
.willReturn(WireMock.aResponse().withStatus(200).withBody(new JSON().serialize(threeSecrets))));
|
||||
|
||||
V1SecretList fourSecrets = new V1SecretList();
|
||||
fourSecrets.addItemsItem(four);
|
||||
WireMock.stubFor(WireMock.get("/api/v1/namespaces/spring-k8s/secrets?labelSelector=letter%3Dd")
|
||||
.willReturn(WireMock.aResponse().withStatus(200).withBody(new JSON().serialize(fourSecrets))));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs.IncludeProfileSpecificSourcesConfigurationStub, \
|
||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs.NamedConfigMapWithPrefixConfigurationStub, \
|
||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs..NamedSecretWithPrefixConfigurationStub, \
|
||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs.LabeledSecretWithPrefixConfigurationStub, \
|
||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs.NamedSecretWithPrefixConfigurationStub, \
|
||||
org.springframework.cloud.kubernetes.client.config.EnableRetryBootstrapConfiguration
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
spring:
|
||||
application:
|
||||
name: labeled-secret-with-prefix
|
||||
cloud:
|
||||
kubernetes:
|
||||
secrets:
|
||||
enableApi: true
|
||||
useNameAsPrefix: true
|
||||
namespace: spring-k8s
|
||||
sources:
|
||||
- labels:
|
||||
letter: a
|
||||
useNameAsPrefix: false
|
||||
- labels:
|
||||
letter: b
|
||||
explicitPrefix: two
|
||||
- labels:
|
||||
letter: c
|
||||
- labels:
|
||||
letter: d
|
||||
useNameAsPrefix: true
|
||||
@@ -93,7 +93,7 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
|
||||
}
|
||||
String name = getApplicationName(environment, this.name, "Config Map");
|
||||
return Collections.singletonList(
|
||||
new NamedConfigMapNormalizedSource(name, namespace, failFast, "", includeProfileSpecificSources));
|
||||
new NamedConfigMapNormalizedSource(name, namespace, failFast, includeProfileSpecificSources));
|
||||
}
|
||||
|
||||
return sources.stream()
|
||||
@@ -185,8 +185,8 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
|
||||
boolean defaultIncludeProfileSpecificSources, boolean failFast) {
|
||||
String normalizedName = StringUtils.hasLength(this.name) ? this.name : defaultName;
|
||||
String normalizedNamespace = StringUtils.hasLength(this.namespace) ? this.namespace : defaultNamespace;
|
||||
String prefix = ConfigUtils.findPrefix(this.explicitPrefix, useNameAsPrefix, defaultUseNameAsPrefix,
|
||||
normalizedName);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix(this.explicitPrefix, useNameAsPrefix,
|
||||
defaultUseNameAsPrefix, normalizedName);
|
||||
boolean includeProfileSpecificSources = ConfigUtils.includeProfileSpecificSources(
|
||||
defaultIncludeProfileSpecificSources, this.includeProfileSpecificSources);
|
||||
return new NamedConfigMapNormalizedSource(normalizedName, normalizedNamespace, failFast, prefix,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.kubernetes.commons.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -61,31 +62,49 @@ public final class ConfigUtils {
|
||||
* @param normalizedName either the name of
|
||||
* 'spring.cloud.kubernetes.config|secrets.sources.name' or
|
||||
* 'spring.cloud.kubernetes.config|secrets.name'
|
||||
* @return prefix to use in normalized sources, never null
|
||||
* @return prefix to use in normalized sources
|
||||
*/
|
||||
public static String findPrefix(String explicitPrefix, Boolean useNameAsPrefix, boolean defaultUseNameAsPrefix,
|
||||
public static Prefix findPrefix(String explicitPrefix, Boolean useNameAsPrefix, boolean defaultUseNameAsPrefix,
|
||||
String normalizedName) {
|
||||
// if explicitPrefix is set, it takes priority over useNameAsPrefix
|
||||
// (either the one from 'spring.cloud.kubernetes.config|secrets' or
|
||||
// 'spring.cloud.kubernetes.config|secrets.sources')
|
||||
if (StringUtils.hasText(explicitPrefix)) {
|
||||
return explicitPrefix;
|
||||
Prefix.computeKnown(() -> explicitPrefix);
|
||||
return Prefix.KNOWN;
|
||||
}
|
||||
|
||||
// useNameAsPrefix is a java.lang.Boolean and if it's != null, users have
|
||||
// specified it explicitly
|
||||
if (useNameAsPrefix != null) {
|
||||
if (useNameAsPrefix) {
|
||||
return normalizedName;
|
||||
// this is the case when the source is searched by labels,
|
||||
// but prefix support is enabled.
|
||||
// in such cases, the name is not known yet.
|
||||
if (normalizedName == null) {
|
||||
return Prefix.DELAYED;
|
||||
}
|
||||
|
||||
Prefix.computeKnown(() -> normalizedName);
|
||||
return Prefix.KNOWN;
|
||||
}
|
||||
return "";
|
||||
return Prefix.DEFAULT;
|
||||
}
|
||||
|
||||
if (defaultUseNameAsPrefix) {
|
||||
return normalizedName;
|
||||
|
||||
// this is the case when the source is searched by labels,
|
||||
// but prefix support is enabled.ConfigUtilsTests
|
||||
// in such cases, the name is not known yet.
|
||||
if (normalizedName == null) {
|
||||
return Prefix.DELAYED;
|
||||
}
|
||||
|
||||
Prefix.computeKnown(() -> normalizedName);
|
||||
return Prefix.KNOWN;
|
||||
}
|
||||
|
||||
return "";
|
||||
return Prefix.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,4 +149,41 @@ public final class ConfigUtils {
|
||||
return target + PROPERTY_SOURCE_NAME_SEPARATOR + applicationName + PROPERTY_SOURCE_NAME_SEPARATOR + namespace;
|
||||
}
|
||||
|
||||
public static final class Prefix {
|
||||
|
||||
/**
|
||||
* prefix has not been provided.
|
||||
*/
|
||||
public static final Prefix DEFAULT = new Prefix(() -> "");
|
||||
|
||||
/**
|
||||
* prefix has been enabled, but the actual value will be known later; the value
|
||||
* for the prefix will be the name of the source. (this is the case for a
|
||||
* prefix-enabled labeled source for example)
|
||||
*/
|
||||
public static final Prefix DELAYED = new Prefix(() -> {
|
||||
throw new IllegalArgumentException("prefix is delayed, needs to be taken elsewhere");
|
||||
});
|
||||
|
||||
/**
|
||||
* prefix is known at the callsite.
|
||||
*/
|
||||
public static Prefix KNOWN;
|
||||
|
||||
public Supplier<String> prefixProvider() {
|
||||
return prefixProvider;
|
||||
}
|
||||
|
||||
private final Supplier<String> prefixProvider;
|
||||
|
||||
private Prefix(Supplier<String> prefixProvider) {
|
||||
this.prefixProvider = prefixProvider;
|
||||
}
|
||||
|
||||
private static void computeKnown(Supplier<String> supplier) {
|
||||
KNOWN = new Prefix(supplier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,9 +29,19 @@ public final class LabeledSecretNormalizedSource extends NormalizedSource {
|
||||
|
||||
private final Map<String, String> labels;
|
||||
|
||||
private final ConfigUtils.Prefix prefix;
|
||||
|
||||
public LabeledSecretNormalizedSource(String namespace, Map<String, String> labels, boolean failFast,
|
||||
ConfigUtils.Prefix prefix) {
|
||||
super(null, namespace, failFast);
|
||||
this.labels = Collections.unmodifiableMap(Objects.requireNonNull(labels));
|
||||
this.prefix = Objects.requireNonNull(prefix);
|
||||
}
|
||||
|
||||
public LabeledSecretNormalizedSource(String namespace, Map<String, String> labels, boolean failFast) {
|
||||
super(null, namespace, failFast);
|
||||
this.labels = Collections.unmodifiableMap(Objects.requireNonNull(labels));
|
||||
this.prefix = ConfigUtils.Prefix.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,6 +51,10 @@ public final class LabeledSecretNormalizedSource extends NormalizedSource {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public ConfigUtils.Prefix prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NormalizedSourceType type() {
|
||||
return NormalizedSourceType.LABELED_SECRET;
|
||||
|
||||
@@ -25,18 +25,25 @@ import java.util.Objects;
|
||||
*/
|
||||
public final class NamedConfigMapNormalizedSource extends NormalizedSource {
|
||||
|
||||
private final String prefix;
|
||||
private final ConfigUtils.Prefix prefix;
|
||||
|
||||
private final boolean includeProfileSpecificSources;
|
||||
|
||||
public NamedConfigMapNormalizedSource(String name, String namespace, boolean failFast, String prefix,
|
||||
public NamedConfigMapNormalizedSource(String name, String namespace, boolean failFast, ConfigUtils.Prefix prefix,
|
||||
boolean includeProfileSpecificSources) {
|
||||
super(name, namespace, failFast);
|
||||
this.prefix = Objects.requireNonNull(prefix);
|
||||
this.includeProfileSpecificSources = includeProfileSpecificSources;
|
||||
}
|
||||
|
||||
public String prefix() {
|
||||
public NamedConfigMapNormalizedSource(String name, String namespace, boolean failFast,
|
||||
boolean includeProfileSpecificSources) {
|
||||
super(name, namespace, failFast);
|
||||
this.prefix = ConfigUtils.Prefix.DEFAULT;
|
||||
this.includeProfileSpecificSources = includeProfileSpecificSources;
|
||||
}
|
||||
|
||||
public ConfigUtils.Prefix prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,19 @@ import java.util.Objects;
|
||||
*/
|
||||
public final class NamedSecretNormalizedSource extends NormalizedSource {
|
||||
|
||||
private final String prefix;
|
||||
private final ConfigUtils.Prefix prefix;
|
||||
|
||||
public NamedSecretNormalizedSource(String name, String namespace, boolean failFast, String prefix) {
|
||||
public NamedSecretNormalizedSource(String name, String namespace, boolean failFast, ConfigUtils.Prefix prefix) {
|
||||
super(name, namespace, failFast);
|
||||
this.prefix = prefix;
|
||||
this.prefix = Objects.requireNonNull(prefix);
|
||||
}
|
||||
|
||||
public String prefix() {
|
||||
public NamedSecretNormalizedSource(String name, String namespace, boolean failFast) {
|
||||
super(name, namespace, failFast);
|
||||
this.prefix = ConfigUtils.Prefix.DEFAULT;
|
||||
}
|
||||
|
||||
public ConfigUtils.Prefix prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,10 +96,11 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
||||
if (this.sources.isEmpty()) {
|
||||
List<NormalizedSource> result = new ArrayList<>(2);
|
||||
String name = getApplicationName(environment, this.name, "Secret");
|
||||
result.add(new NamedSecretNormalizedSource(name, this.namespace, this.isFailFast(), ""));
|
||||
result.add(new NamedSecretNormalizedSource(name, this.namespace, this.failFast));
|
||||
|
||||
if (!labels.isEmpty()) {
|
||||
result.add(new LabeledSecretNormalizedSource(this.namespace, this.labels, this.isFailFast()));
|
||||
result.add(new LabeledSecretNormalizedSource(this.namespace, this.labels, this.failFast,
|
||||
ConfigUtils.Prefix.DEFAULT));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -195,17 +196,17 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
||||
|
||||
String secretName = getApplicationName(environment, normalizedName, "Secret");
|
||||
|
||||
String prefix = ConfigUtils.findPrefix(this.explicitPrefix, this.useNameAsPrefix, defaultUseNameAsPrefix,
|
||||
normalizedName);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix(this.explicitPrefix, this.useNameAsPrefix,
|
||||
defaultUseNameAsPrefix, normalizedName);
|
||||
|
||||
NormalizedSource nameBasedSource = new NamedSecretNormalizedSource(secretName, normalizedNamespace,
|
||||
NormalizedSource namedBasedSource = new NamedSecretNormalizedSource(secretName, normalizedNamespace,
|
||||
failFast, prefix);
|
||||
normalizedSources.add(nameBasedSource);
|
||||
normalizedSources.add(namedBasedSource);
|
||||
|
||||
if (!normalizedLabels.isEmpty()) {
|
||||
NormalizedSource labelsBasedSource = new LabeledSecretNormalizedSource(normalizedNamespace, labels,
|
||||
failFast);
|
||||
normalizedSources.add(labelsBasedSource);
|
||||
NormalizedSource labeledBasedSource = new LabeledSecretNormalizedSource(normalizedNamespace, labels,
|
||||
failFast, prefix);
|
||||
normalizedSources.add(labeledBasedSource);
|
||||
}
|
||||
|
||||
return normalizedSources.build();
|
||||
|
||||
@@ -52,7 +52,7 @@ class ConfigMapConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "",
|
||||
Assertions.assertSame(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT,
|
||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty");
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class ConfigMapConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "",
|
||||
Assertions.assertSame(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT,
|
||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty,"
|
||||
+ "no matter of 'spring.cloud.kubernetes.config.useNameAsPrefix' value");
|
||||
}
|
||||
@@ -114,7 +114,8 @@ class ConfigMapConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "a single NormalizedSource is expected");
|
||||
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "config-map-one");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix().prefixProvider().get(),
|
||||
"config-map-one");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,9 +161,11 @@ class ConfigMapConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
||||
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix(), "config-map-two");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix(), "config-map-three");
|
||||
Assertions.assertSame(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||
"config-map-two");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||
"config-map-three");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,10 +217,13 @@ class ConfigMapConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
||||
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "one");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix(), "two");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix(), "three");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(3)).prefix(), "");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix().prefixProvider().get(),
|
||||
"one");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||
"two");
|
||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||
"three");
|
||||
Assertions.assertSame(((NamedConfigMapNormalizedSource) sources.get(3)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,32 +29,55 @@ class ConfigUtilsTests {
|
||||
|
||||
@Test
|
||||
void testExplicitPrefixSet() {
|
||||
String result = ConfigUtils.findPrefix("explicitPrefix", null, false, "irrelevant");
|
||||
Assertions.assertEquals(result, "explicitPrefix");
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("explicitPrefix", null, false, "irrelevant");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||
Assertions.assertEquals(result.prefixProvider().get(), "explicitPrefix");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseNameAsPrefixTrue() {
|
||||
String result = ConfigUtils.findPrefix("", Boolean.TRUE, false, "name-to-use");
|
||||
Assertions.assertEquals(result, "name-to-use");
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", Boolean.TRUE, false, "name-to-use");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||
Assertions.assertEquals(result.prefixProvider().get(), "name-to-use");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUseNameAsPrefixFalse() {
|
||||
String result = ConfigUtils.findPrefix("", Boolean.FALSE, false, "name-not-to-use");
|
||||
Assertions.assertEquals(result, "");
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", Boolean.FALSE, false, "name-not-to-use");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.DEFAULT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultUseNameAsPrefixTrue() {
|
||||
String result = ConfigUtils.findPrefix("", null, true, "name-to-use");
|
||||
Assertions.assertEquals(result, "name-to-use");
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", null, true, "name-to-use");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||
Assertions.assertEquals(result.prefixProvider().get(), "name-to-use");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoMatch() {
|
||||
String result = ConfigUtils.findPrefix("", null, false, "name-not-to-use");
|
||||
Assertions.assertEquals(result, "");
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", null, false, "name-not-to-use");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.DEFAULT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnsetEmpty() {
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", null, false, "name-not-to-use");
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.DEFAULT);
|
||||
|
||||
String expected = Assertions.assertDoesNotThrow(() -> result.prefixProvider().get());
|
||||
Assertions.assertEquals("", expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDelayed() {
|
||||
ConfigUtils.Prefix result = ConfigUtils.findPrefix(null, true, false, null);
|
||||
Assertions.assertSame(result, ConfigUtils.Prefix.DELAYED);
|
||||
|
||||
IllegalArgumentException ex = Assertions.assertThrows(IllegalArgumentException.class,
|
||||
() -> result.prefixProvider().get());
|
||||
|
||||
Assertions.assertEquals("prefix is delayed, needs to be taken elsewhere", ex.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,23 @@ class LabeledSecretNormalizedSourceTests {
|
||||
Assertions.assertEquals(left, right);
|
||||
}
|
||||
|
||||
/*
|
||||
* left and right instance have a different prefix, but the hashCode is the same; as
|
||||
* it is not taken into consideration when computing hashCode
|
||||
*/
|
||||
@Test
|
||||
void testEqualsAndHashCodePrefixDoesNotMatter() {
|
||||
|
||||
ConfigUtils.Prefix knownLeft = ConfigUtils.findPrefix("left", false, false, "some");
|
||||
ConfigUtils.Prefix knownRight = ConfigUtils.findPrefix("right", false, false, "some");
|
||||
|
||||
LabeledSecretNormalizedSource left = new LabeledSecretNormalizedSource("namespace", labels, true, knownLeft);
|
||||
LabeledSecretNormalizedSource right = new LabeledSecretNormalizedSource("namespace", labels, true, knownRight);
|
||||
|
||||
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
||||
Assertions.assertEquals(left, right);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testType() {
|
||||
LabeledSecretNormalizedSource source = new LabeledSecretNormalizedSource("namespace", labels, false);
|
||||
@@ -58,10 +75,12 @@ class LabeledSecretNormalizedSourceTests {
|
||||
|
||||
@Test
|
||||
void testConstructorFields() {
|
||||
LabeledSecretNormalizedSource source = new LabeledSecretNormalizedSource("namespace", labels, false);
|
||||
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix("prefix", false, false, "some");
|
||||
LabeledSecretNormalizedSource source = new LabeledSecretNormalizedSource("namespace", labels, false, prefix);
|
||||
Assertions.assertTrue(source.name().isEmpty());
|
||||
Assertions.assertEquals(source.namespace().get(), "namespace");
|
||||
Assertions.assertFalse(source.failFast());
|
||||
Assertions.assertSame(source.prefix(), prefix);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,12 +24,18 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
class NamedConfigMapNormalizedSourceTests {
|
||||
|
||||
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "prefix");
|
||||
|
||||
@Test
|
||||
void testEqualsAndHashCode() {
|
||||
NamedConfigMapNormalizedSource left = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
||||
|
||||
ConfigUtils.Prefix knownLeft = ConfigUtils.findPrefix("prefix", false, false, "some");
|
||||
ConfigUtils.Prefix knownRight = ConfigUtils.findPrefix("prefix", false, false, "non-equal-prefix");
|
||||
|
||||
NamedConfigMapNormalizedSource left = new NamedConfigMapNormalizedSource("name", "namespace", false, knownLeft,
|
||||
true);
|
||||
NamedConfigMapNormalizedSource right = new NamedConfigMapNormalizedSource("name", "namespace", true,
|
||||
"non-equal-prefix", false);
|
||||
NamedConfigMapNormalizedSource right = new NamedConfigMapNormalizedSource("name", "namespace", true, knownRight,
|
||||
false);
|
||||
|
||||
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
||||
Assertions.assertEquals(left, right);
|
||||
@@ -37,21 +43,22 @@ class NamedConfigMapNormalizedSourceTests {
|
||||
|
||||
@Test
|
||||
void testType() {
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
||||
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||
true);
|
||||
Assertions.assertSame(one.type(), NormalizedSourceType.NAMED_CONFIG_MAP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTarget() {
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||
true);
|
||||
Assertions.assertEquals(one.target(), "configmap");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructorFields() {
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||
true);
|
||||
Assertions.assertEquals(one.name().get(), "name");
|
||||
Assertions.assertEquals(one.namespace().get(), "namespace");
|
||||
|
||||
@@ -24,10 +24,12 @@ import org.junit.jupiter.api.Test;
|
||||
*/
|
||||
class NamedSecretNormalizedSourceTests {
|
||||
|
||||
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "prefix");
|
||||
|
||||
@Test
|
||||
void testEqualsAndHashCode() {
|
||||
NamedSecretNormalizedSource left = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
||||
NamedSecretNormalizedSource right = new NamedSecretNormalizedSource("name", "namespace", true, "");
|
||||
NamedSecretNormalizedSource left = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||
NamedSecretNormalizedSource right = new NamedSecretNormalizedSource("name", "namespace", true);
|
||||
|
||||
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
||||
Assertions.assertEquals(left, right);
|
||||
@@ -35,23 +37,23 @@ class NamedSecretNormalizedSourceTests {
|
||||
|
||||
@Test
|
||||
void testType() {
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||
Assertions.assertSame(source.type(), NormalizedSourceType.NAMED_SECRET);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTarget() {
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||
Assertions.assertEquals(source.target(), "secret");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructorFields() {
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, "prefix");
|
||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, PREFIX);
|
||||
Assertions.assertEquals(source.name().get(), "name");
|
||||
Assertions.assertEquals(source.namespace().get(), "namespace");
|
||||
Assertions.assertFalse(source.failFast());
|
||||
Assertions.assertEquals("prefix", source.prefix());
|
||||
Assertions.assertSame(PREFIX, source.prefix());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@@ -133,8 +134,7 @@ class SecretsConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "",
|
||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty");
|
||||
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,8 +162,8 @@ class SecretsConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "",
|
||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty,"
|
||||
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT,
|
||||
"empty sources must generate a List with a single NormalizedSource, where prefix is unset,"
|
||||
+ "no matter of 'spring.cloud.kubernetes.secret.useNameAsPrefix' value");
|
||||
}
|
||||
|
||||
@@ -195,7 +195,8 @@ class SecretsConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 1, "a single NormalizedSource is expected");
|
||||
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "secret-one");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix().prefixProvider().get(),
|
||||
"secret-one");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,9 +242,11 @@ class SecretsConfigPropertiesTests {
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
||||
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix(), "secret-two");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix(), "secret-three");
|
||||
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||
"secret-two");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||
"secret-three");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,31 +277,105 @@ class SecretsConfigPropertiesTests {
|
||||
properties.setNamespace("spring-k8s");
|
||||
|
||||
SecretsConfigProperties.Source one = new SecretsConfigProperties.Source();
|
||||
one.setNamespace("secret-one");
|
||||
one.setName("secret-one");
|
||||
one.setUseNameAsPrefix(false);
|
||||
one.setExplicitPrefix("one");
|
||||
|
||||
SecretsConfigProperties.Source two = new SecretsConfigProperties.Source();
|
||||
two.setNamespace("secret-two");
|
||||
two.setName("secret-two");
|
||||
two.setUseNameAsPrefix(true);
|
||||
two.setExplicitPrefix("two");
|
||||
|
||||
SecretsConfigProperties.Source three = new SecretsConfigProperties.Source();
|
||||
three.setNamespace("secret-three");
|
||||
three.setName("secret-three");
|
||||
three.setExplicitPrefix("three");
|
||||
|
||||
SecretsConfigProperties.Source four = new SecretsConfigProperties.Source();
|
||||
four.setNamespace("secret-four");
|
||||
four.setName("secret-four");
|
||||
|
||||
properties.setSources(Arrays.asList(one, two, three, four));
|
||||
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
||||
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "one");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix(), "two");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix(), "three");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(3)).prefix(), "");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix().prefixProvider().get(), "one");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix().prefixProvider().get(), "two");
|
||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||
"three");
|
||||
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(3)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* spring:
|
||||
* cloud:
|
||||
* kubernetes:
|
||||
* secrets:
|
||||
* useNameAsPrefix: false
|
||||
* namespace: spring-k8s
|
||||
* sources:
|
||||
* - labels:
|
||||
* - name: first-label
|
||||
* value: secret-one
|
||||
* useNameAsPrefix: false
|
||||
* explicitPrefix: one
|
||||
* - labels:
|
||||
* - name: second-label
|
||||
* value: secret-two
|
||||
* useNameAsPrefix: true
|
||||
* explicitPrefix: two
|
||||
* - labels:
|
||||
* - name: third-label
|
||||
* value: secret-three
|
||||
* explicitPrefix: three
|
||||
* - labels:
|
||||
* - name: fourth-label
|
||||
* value: secret-four
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
void testLabelsMultipleCases() {
|
||||
SecretsConfigProperties properties = new SecretsConfigProperties();
|
||||
properties.setUseNameAsPrefix(false);
|
||||
properties.setNamespace("spring-k8s");
|
||||
|
||||
SecretsConfigProperties.Source one = new SecretsConfigProperties.Source();
|
||||
one.setLabels(Map.of("first-label", "secret-one"));
|
||||
one.setUseNameAsPrefix(false);
|
||||
one.setExplicitPrefix("one");
|
||||
|
||||
SecretsConfigProperties.Source two = new SecretsConfigProperties.Source();
|
||||
two.setLabels(Map.of("second-label", "secret-two"));
|
||||
two.setUseNameAsPrefix(true);
|
||||
two.setExplicitPrefix("two");
|
||||
|
||||
SecretsConfigProperties.Source three = new SecretsConfigProperties.Source();
|
||||
three.setLabels(Map.of("third-label", "secret-three"));
|
||||
three.setExplicitPrefix("three");
|
||||
|
||||
SecretsConfigProperties.Source four = new SecretsConfigProperties.Source();
|
||||
four.setLabels(Map.of("fourth-label", "secret-four"));
|
||||
|
||||
properties.setSources(Arrays.asList(one, two, three, four));
|
||||
|
||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||
// we get 8 property sources, since "named" ones with "application" are
|
||||
// duplicated.
|
||||
// that's OK, since later in the code we get a LinkedHashSet out of them all,
|
||||
// so they become 5 only.
|
||||
Assertions.assertEquals(sources.size(), 8, "4 NormalizedSources are expected");
|
||||
|
||||
Assertions.assertEquals(((LabeledSecretNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||
"one");
|
||||
Assertions.assertEquals(((LabeledSecretNormalizedSource) sources.get(3)).prefix().prefixProvider().get(),
|
||||
"two");
|
||||
Assertions.assertEquals(((LabeledSecretNormalizedSource) sources.get(5)).prefix().prefixProvider().get(),
|
||||
"three");
|
||||
Assertions.assertSame(((LabeledSecretNormalizedSource) sources.get(7)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||
|
||||
Set<NormalizedSource> set = new LinkedHashSet<>(sources);
|
||||
Assertions.assertEquals(5, set.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class KubernetesConfigServerAutoConfiguration {
|
||||
namespaces.forEach(space -> {
|
||||
|
||||
NamedConfigMapNormalizedSource source = new NamedConfigMapNormalizedSource(applicationName, space,
|
||||
false, "", true);
|
||||
false, true);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
||||
springEnv);
|
||||
|
||||
@@ -96,7 +96,7 @@ public class KubernetesConfigServerAutoConfiguration {
|
||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
||||
|
||||
namespaces.forEach(space -> {
|
||||
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, space, false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, space, false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
||||
springEnv);
|
||||
propertySources.add(new KubernetesClientSecretsPropertySource(context));
|
||||
|
||||
@@ -101,12 +101,12 @@ class KubernetesEnvironmentRepositoryTests {
|
||||
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
||||
|
||||
NormalizedSource defaultSource = new NamedConfigMapNormalizedSource(applicationName, "default", false, "",
|
||||
NormalizedSource defaultSource = new NamedConfigMapNormalizedSource(applicationName, "default", false,
|
||||
true);
|
||||
KubernetesClientConfigContext defaultContext = new KubernetesClientConfigContext(coreApi, defaultSource,
|
||||
"default", springEnv);
|
||||
|
||||
NormalizedSource devSource = new NamedConfigMapNormalizedSource(applicationName, "dev", false, "", true);
|
||||
NormalizedSource devSource = new NamedConfigMapNormalizedSource(applicationName, "dev", false, true);
|
||||
KubernetesClientConfigContext devContext = new KubernetesClientConfigContext(coreApi, devSource, "dev",
|
||||
springEnv);
|
||||
|
||||
@@ -117,7 +117,7 @@ class KubernetesEnvironmentRepositoryTests {
|
||||
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
||||
|
||||
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, "default", false, "");
|
||||
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, "default", false);
|
||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, "default",
|
||||
springEnv);
|
||||
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package org.springframework.cloud.kubernetes.fabric8.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -29,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.PrefixContext;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
|
||||
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException;
|
||||
@@ -64,11 +67,12 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Fabric8
|
||||
return context -> {
|
||||
|
||||
LabeledSecretNormalizedSource source = ((LabeledSecretNormalizedSource) context.normalizedSource());
|
||||
Set<String> propertySourceNames = new LinkedHashSet<>();
|
||||
Map<String, String> labels = source.labels();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
String namespace = context.namespace();
|
||||
String sourceName = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, labels.keySet());
|
||||
String sourceNameFromLabels = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, labels.keySet());
|
||||
|
||||
try {
|
||||
|
||||
@@ -77,9 +81,43 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Fabric8
|
||||
.getItems();
|
||||
|
||||
if (!secrets.isEmpty()) {
|
||||
secrets.forEach(secret -> result.putAll(dataFromSecret(secret, namespace)));
|
||||
sourceName = secrets.stream().map(Secret::getMetadata).map(ObjectMeta::getName)
|
||||
|
||||
for (Secret secret : secrets) {
|
||||
// we support prefix per source, not per secret. This means that
|
||||
// in theory
|
||||
// we can still have clashes here, that we simply override.
|
||||
// If there are more than one secret found per labels, and they
|
||||
// have the same key on a
|
||||
// property, but different values; one value will override the
|
||||
// other, without any
|
||||
// particular order.
|
||||
result.putAll(dataFromSecret(secret, namespace));
|
||||
}
|
||||
|
||||
String secretNames = secrets.stream().map(Secret::getMetadata).map(ObjectMeta::getName).sorted()
|
||||
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
|
||||
propertySourceNames.add(secretNames);
|
||||
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||
|
||||
String prefix;
|
||||
if (source.prefix() == ConfigUtils.Prefix.KNOWN) {
|
||||
prefix = source.prefix().prefixProvider().get();
|
||||
}
|
||||
else {
|
||||
// prefix is going to be all the secret names we found based
|
||||
// on the labels
|
||||
// concatenated with PROPERTY_SOURCE_NAME_SEPARATOR
|
||||
prefix = secretNames;
|
||||
}
|
||||
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
|
||||
String names = String.join(PROPERTY_SOURCE_NAME_SEPARATOR, propertySourceNames);
|
||||
return new SourceData(ConfigUtils.sourceName(source.target(), names, namespace), result);
|
||||
|
||||
}
|
||||
else {
|
||||
LOG.info("No Secret(s) with labels '" + labels + "' in namespace '" + namespace + "' found.");
|
||||
@@ -91,8 +129,12 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Fabric8
|
||||
onException(source.failFast(), message, e);
|
||||
}
|
||||
|
||||
String propertySourceName = ConfigUtils.sourceName(source.target(), sourceName, namespace);
|
||||
return new SourceData(propertySourceName, result);
|
||||
// if we could not find a secret with provided labels, we will compute a
|
||||
// response with an empty Map
|
||||
// and name that will use all the label names (not their values)
|
||||
String propertySourceNameFromLabels = ConfigUtils.sourceName(source.target(), sourceNameFromLabels,
|
||||
namespace);
|
||||
return new SourceData(propertySourceNameFromLabels, result);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -97,9 +97,10 @@ final class NamedConfigMapContextToSourceDataProvider implements Supplier<Fabric
|
||||
}
|
||||
}
|
||||
|
||||
if (!"".equals(source.prefix())) {
|
||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
||||
propertySourceNames);
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||
// since we are in a named source, calling get on the supplier is safe
|
||||
String prefix = source.prefix().prefixProvider().get();
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,9 +71,11 @@ final class NamedSecretContextToSourceDataProvider implements Supplier<Fabric8Co
|
||||
else {
|
||||
result = dataFromSecret(secret, namespace);
|
||||
|
||||
if (!"".equals(source.prefix())) {
|
||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
||||
propertySourceNames);
|
||||
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||
// since we are in a named source, calling get on the supplier is
|
||||
// safe
|
||||
String prefix = source.prefix().prefixProvider().get();
|
||||
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class ConfigMapsTest {
|
||||
.build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
@@ -92,7 +92,7 @@ public class ConfigMapsTest {
|
||||
.addToData("application.yaml", ConfigMapTestUtil.readResourceFile("application.yaml")).build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
@@ -109,7 +109,7 @@ public class ConfigMapsTest {
|
||||
.addToData("adhoc.yml", ConfigMapTestUtil.readResourceFile("adhoc.yml")).build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
@@ -126,7 +126,7 @@ public class ConfigMapsTest {
|
||||
.addToData("application.properties", "somevalue").build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "namespace", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "namespace", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
@@ -141,7 +141,7 @@ public class ConfigMapsTest {
|
||||
.addToData("application.yaml", "somevalue").build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "namespace", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "namespace", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
@@ -157,7 +157,7 @@ public class ConfigMapsTest {
|
||||
.addToData("adhoc.properties", ConfigMapTestUtil.readResourceFile("adhoc.properties")).build();
|
||||
|
||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(configMapName, "test", false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
|
||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||
|
||||
@@ -64,7 +64,7 @@ public class EventBasedConfigurationChangeDetectorTests {
|
||||
when(mixedOperation.inNamespace("default")).thenReturn(mixedOperation);
|
||||
when(k8sClient.getNamespace()).thenReturn("default");
|
||||
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("myconfigmap", "default", true, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("myconfigmap", "default", true, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(k8sClient, source, "default", new MockEnvironment());
|
||||
Fabric8ConfigMapPropertySource fabric8ConfigMapPropertySource = new Fabric8ConfigMapPropertySource(context);
|
||||
env.getPropertySources().addFirst(new BootstrapPropertySource<>(fabric8ConfigMapPropertySource));
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
@@ -45,6 +46,8 @@ class Fabric8ConfigMapPropertySourceLocatorTests {
|
||||
|
||||
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
||||
|
||||
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "irrelevant");
|
||||
|
||||
@Test
|
||||
void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
||||
String name = "my-config";
|
||||
@@ -95,7 +98,7 @@ class Fabric8ConfigMapPropertySourceLocatorTests {
|
||||
Mockito.when(client.getNamespace()).thenReturn(null);
|
||||
Fabric8ConfigMapPropertySourceLocator source = new Fabric8ConfigMapPropertySourceLocator(client,
|
||||
configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment()));
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("name", null, false, "prefix", false);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("name", null, false, PREFIX, false);
|
||||
assertThatThrownBy(() -> source.getMapPropertySource(normalizedSource, new MockEnvironment()))
|
||||
.isInstanceOf(NamespaceResolutionFailedException.class);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
@@ -43,6 +44,8 @@ class Fabric8ConfigMapPropertySourceTests {
|
||||
|
||||
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
||||
|
||||
private static final ConfigUtils.Prefix DEFAULT = ConfigUtils.findPrefix("default", false, false, "irrelevant");
|
||||
|
||||
@Test
|
||||
void constructorShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
||||
final String name = "my-config";
|
||||
@@ -50,7 +53,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
||||
final String path = String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, name);
|
||||
|
||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(name, namespace, true, "default", true);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(name, namespace, true, DEFAULT, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "default", new MockEnvironment());
|
||||
assertThatThrownBy(() -> new Fabric8ConfigMapPropertySource(context)).isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Unable to read ConfigMap with name '" + name + "' in namespace '" + namespace + "'");
|
||||
@@ -63,7 +66,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
||||
final String path = String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, name);
|
||||
|
||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(name, namespace, false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource(name, namespace, false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
assertThatNoException().isThrownBy(() -> new Fabric8ConfigMapPropertySource(context));
|
||||
}
|
||||
@@ -72,7 +75,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
||||
void constructorWithClientNamespaceMustNotFail() {
|
||||
|
||||
Mockito.when(client.getNamespace()).thenReturn("namespace");
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("configmap", null, false, "", false);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("configmap", null, false, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
||||
}
|
||||
@@ -81,7 +84,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
||||
void constructorWithNamespaceMustNotFail() {
|
||||
|
||||
Mockito.when(client.getNamespace()).thenReturn(null);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("configMap", null, false, "", true);
|
||||
NormalizedSource source = new NamedConfigMapNormalizedSource("configMap", null, false, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class Fabric8SecretsPropertySourceMockTests {
|
||||
final String namespace = "default";
|
||||
final String path = String.format("/api/v1/namespaces/%s/secrets/%s", namespace, name);
|
||||
|
||||
NamedSecretNormalizedSource named = new NamedSecretNormalizedSource(name, namespace, true, "");
|
||||
NamedSecretNormalizedSource named = new NamedSecretNormalizedSource(name, namespace, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(client, named, "default", new MockEnvironment());
|
||||
|
||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
||||
@@ -77,7 +77,7 @@ class Fabric8SecretsPropertySourceMockTests {
|
||||
final String namespace = "default";
|
||||
final String path = String.format("/api/v1/namespaces/%s/secrets/%s", namespace, name);
|
||||
|
||||
NamedSecretNormalizedSource named = new NamedSecretNormalizedSource(name, namespace, false, "");
|
||||
NamedSecretNormalizedSource named = new NamedSecretNormalizedSource(name, namespace, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(client, named, "default", new MockEnvironment());
|
||||
|
||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.kubernetes.fabric8.config;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -31,6 +32,7 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
@@ -104,7 +106,7 @@ class LabeledSecretContextToSourceDataProviderTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* we have three secret deployed. two of them have labels that match (color=red), one
|
||||
* we have three secrets deployed. two of them have labels that match (color=red), one
|
||||
* does not (color=blue).
|
||||
*/
|
||||
@Test
|
||||
@@ -186,4 +188,83 @@ class LabeledSecretContextToSourceDataProviderTests {
|
||||
Assertions.assertEquals(Map.of("secretName", "secretValue"), sourceData.sourceData());
|
||||
}
|
||||
|
||||
/**
|
||||
* one secret with name : "blue-secret" and labels "color=blue" is deployed. we search
|
||||
* it with the same labels, find it, and assert that name of the SourceData (it must
|
||||
* use its name, not its labels) and values in the SourceData must be prefixed (since
|
||||
* we have provided an explicit prefix).
|
||||
*/
|
||||
@Test
|
||||
void testWithPrefix() {
|
||||
Secret secret = new SecretBuilder().withNewMetadata().withName("blue-secret")
|
||||
.withLabels(Collections.singletonMap("color", "blue")).endMetadata()
|
||||
.addToData("what-color", Base64.getEncoder().encodeToString("blue-color".getBytes())).build();
|
||||
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
||||
|
||||
ConfigUtils.Prefix mePrefix = ConfigUtils.findPrefix("me", false, false, "irrelevant");
|
||||
NormalizedSource normalizedSource = new LabeledSecretNormalizedSource(NAMESPACE,
|
||||
Collections.singletonMap("color", "blue"), true, mePrefix);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
Fabric8ContextToSourceData data = new LabeledSecretContextToSourceDataProvider().get();
|
||||
SourceData sourceData = data.apply(context);
|
||||
|
||||
Assertions.assertEquals("secret.blue-secret.default", sourceData.sourceName());
|
||||
Assertions.assertEquals(Map.of("me.what-color", "blue-color"), sourceData.sourceData());
|
||||
}
|
||||
|
||||
/**
|
||||
* two secrets are deployed (name:blue-secret, name:another-blue-secret) and labels
|
||||
* "color=blue" (on both). we search with the same labels, find them, and assert that
|
||||
* name of the SourceData (it must use its name, not its labels) and values in the
|
||||
* SourceData must be prefixed (since we have provided a delayed prefix).
|
||||
*
|
||||
* Also notice that the prefix is made up from both secret names.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
void testTwoSecretsWithPrefix() {
|
||||
Secret blueSecret = new SecretBuilder().withNewMetadata().withName("blue-secret")
|
||||
.withLabels(Collections.singletonMap("color", "blue")).endMetadata()
|
||||
.addToData("first", Base64.getEncoder().encodeToString("blue".getBytes())).build();
|
||||
|
||||
Secret anotherBlue = new SecretBuilder().withNewMetadata().withName("another-blue-secret")
|
||||
.withLabels(Collections.singletonMap("color", "blue")).endMetadata()
|
||||
.addToData("second", Base64.getEncoder().encodeToString("blue".getBytes())).build();
|
||||
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(blueSecret);
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(anotherBlue);
|
||||
|
||||
NormalizedSource normalizedSource = new LabeledSecretNormalizedSource(NAMESPACE,
|
||||
Collections.singletonMap("color", "blue"), true, ConfigUtils.Prefix.DELAYED);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
Fabric8ContextToSourceData data = new LabeledSecretContextToSourceDataProvider().get();
|
||||
SourceData sourceData = data.apply(context);
|
||||
|
||||
// maps don't have a defined order, so assert components separately
|
||||
Assertions.assertEquals(46, sourceData.sourceName().length());
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("blue-secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("another-blue-secret"));
|
||||
Assertions.assertTrue(sourceData.sourceName().contains("default"));
|
||||
|
||||
Map<String, Object> properties = sourceData.sourceData();
|
||||
Assertions.assertEquals(2, properties.size());
|
||||
Iterator<String> keys = properties.keySet().iterator();
|
||||
String firstKey = keys.next();
|
||||
String secondKey = keys.next();
|
||||
|
||||
if (firstKey.contains("first")) {
|
||||
Assertions.assertEquals(firstKey, "another-blue-secret.blue-secret.first");
|
||||
}
|
||||
|
||||
Assertions.assertEquals(secondKey, "another-blue-secret.blue-secret.second");
|
||||
Assertions.assertEquals(properties.get(firstKey), "blue");
|
||||
Assertions.assertEquals(properties.get(secondKey), "blue");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.ConfigUtils;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NamedConfigMapNormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||
@@ -48,6 +49,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("some", false, false, "irrelevant");
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
|
||||
@@ -77,7 +80,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
|
||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("blue", NAMESPACE, true, "", false);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("blue", NAMESPACE, true, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -100,7 +103,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
|
||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, "", false);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -131,7 +134,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
// add one more profile and specify that we want profile based config maps
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
env.setActiveProfiles("with-profile");
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, "", true);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, true);
|
||||
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||
|
||||
@@ -167,7 +170,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
// also append prefix
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
env.setActiveProfiles("with-profile");
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, "some", true);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, PREFIX, true);
|
||||
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||
|
||||
@@ -207,7 +210,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
// also append prefix
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
env.setActiveProfiles("with-taste", "with-shape");
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, "some", true);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE, true, PREFIX, true);
|
||||
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||
|
||||
@@ -232,8 +235,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
|
||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, "",
|
||||
false);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -259,8 +261,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||
|
||||
// different namespace
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE + "nope", true, "",
|
||||
false);
|
||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE + "nope", true, false);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE, true, "");
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -108,7 +108,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(blue);
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(yellow);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE, true, "");
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -132,7 +132,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(pink);
|
||||
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("blue", NAMESPACE, true, "");
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("blue", NAMESPACE, true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
@@ -158,7 +158,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
||||
|
||||
// different namespace
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE + "nope", true, "");
|
||||
NormalizedSource normalizedSource = new NamedSecretNormalizedSource("red", NAMESPACE + "nope", true);
|
||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||
new MockEnvironment());
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Four;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.One;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Three;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Two;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties({ One.class, Two.class, Three.class, Four.class })
|
||||
public class LabeledSecretWithPrefixApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LabeledSecretWithPrefixApp.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix;
|
||||
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* @author wind57
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = LabeledSecretWithPrefixApp.class,
|
||||
properties = { "spring.cloud.bootstrap.name=labeled-secret-with-prefix",
|
||||
"spring.main.cloud-platform=KUBERNETES", "spring.cloud.bootstrap.enabled=true" })
|
||||
@EnableKubernetesMockClient(crud = true, https = false)
|
||||
class LabeledSecretWithPrefixBootstrapTests extends LabeledSecretWithPrefixTests {
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpBeforeClass() {
|
||||
setUpBeforeClass(mockClient);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2013-2022 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix;
|
||||
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* @author wind57
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = LabeledSecretWithPrefixApp.class,
|
||||
properties = { "spring.application.name=named-secret-with-prefix", "spring.main.cloud-platform=KUBERNETES",
|
||||
"spring.config.import=kubernetes:,classpath:./labeled-secret-with-prefix.yaml" })
|
||||
@EnableKubernetesMockClient(crud = true, https = false)
|
||||
class LabeledSecretWithPrefixConfigDataTests extends LabeledSecretWithPrefixTests {
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpBeforeClass() {
|
||||
setUpBeforeClass(mockClient);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
/**
|
||||
* @author wind57
|
||||
*/
|
||||
abstract class LabeledSecretWithPrefixTests {
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webClient;
|
||||
|
||||
static void setUpBeforeClass(KubernetesClient mockClient) {
|
||||
LabeledSecretWithPrefixTests.mockClient = mockClient;
|
||||
// Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl());
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
Map<String, String> one = Collections.singletonMap("one.property",
|
||||
Base64.getEncoder().encodeToString("one".getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
createSecret("secret-one", one, Collections.singletonMap("letter", "a"));
|
||||
|
||||
Map<String, String> two = Collections.singletonMap("property",
|
||||
Base64.getEncoder().encodeToString("two".getBytes(StandardCharsets.UTF_8)));
|
||||
createSecret("secret-two", two, Collections.singletonMap("letter", "b"));
|
||||
|
||||
Map<String, String> three = Collections.singletonMap("property",
|
||||
Base64.getEncoder().encodeToString("three".getBytes(StandardCharsets.UTF_8)));
|
||||
createSecret("secret-three", three, Collections.singletonMap("letter", "c"));
|
||||
|
||||
Map<String, String> four = Collections.singletonMap("property",
|
||||
Base64.getEncoder().encodeToString("four".getBytes(StandardCharsets.UTF_8)));
|
||||
createSecret("secret-four", four, Collections.singletonMap("letter", "d"));
|
||||
|
||||
}
|
||||
|
||||
private static void createSecret(String name, Map<String, String> data, Map<String, String> labels) {
|
||||
mockClient.secrets().inNamespace("spring-k8s").create(new SecretBuilder().withNewMetadata().withName(name)
|
||||
.withLabels(labels).endMetadata().addToData(data).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[0].useNameAsPrefix=false'
|
||||
* ("one.property", "one")
|
||||
*
|
||||
* As such: @ConfigurationProperties("one")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testOne() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/one").exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(Matchers.equalTo("one"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[1].explicitPrefix=two'
|
||||
* ("property", "two")
|
||||
*
|
||||
* As such: @ConfigurationProperties("two")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testTwo() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/two").exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(Matchers.equalTo("two"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[2].labels=letter:c'
|
||||
* ("property", "three")
|
||||
*
|
||||
* We find the secret by labels, and use it's name as the prefix.
|
||||
*
|
||||
* As such: @ConfigurationProperties(prefix = "secret-three")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testThree() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/three").exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(Matchers.equalTo("three"));
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 'spring.cloud.kubernetes.secrets.useNameAsPrefix=true'
|
||||
* 'spring.cloud.kubernetes.secrets.sources[3].labels=letter:d'
|
||||
* ("property", "four")
|
||||
*
|
||||
* We find the secret by labels, and use it's name as the prefix.
|
||||
*
|
||||
* As such: @ConfigurationProperties(prefix = "secret-four")
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
void testFour() {
|
||||
this.webClient.get().uri("/labeled-secret/prefix/four").exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(Matchers.equalTo("four"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix.controller;
|
||||
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Four;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.One;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Three;
|
||||
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_prefix.properties.Two;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class LabeledSecretWithPrefixController {
|
||||
|
||||
private final One one;
|
||||
|
||||
private final Two two;
|
||||
|
||||
private final Three three;
|
||||
|
||||
private final Four four;
|
||||
|
||||
public LabeledSecretWithPrefixController(One one, Two two, Three three, Four four) {
|
||||
this.one = one;
|
||||
this.two = two;
|
||||
this.three = three;
|
||||
this.four = four;
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/one")
|
||||
public String one() {
|
||||
return one.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/two")
|
||||
public String two() {
|
||||
return two.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/three")
|
||||
public String three() {
|
||||
return three.getProperty();
|
||||
}
|
||||
|
||||
@GetMapping("/labeled-secret/prefix/four")
|
||||
public String four() {
|
||||
return four.getProperty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "secret-four")
|
||||
public class Four {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("one")
|
||||
public class One {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "secret-three")
|
||||
public class Three {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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
|
||||
*
|
||||
* https://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.kubernetes.fabric8.config.labeled_secret_with_prefix.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("two")
|
||||
public class Two {
|
||||
|
||||
private String property;
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
spring:
|
||||
application:
|
||||
name: labeled-secret-with-prefix
|
||||
cloud:
|
||||
kubernetes:
|
||||
secrets:
|
||||
enableApi: true
|
||||
useNameAsPrefix: true
|
||||
namespace: spring-k8s
|
||||
sources:
|
||||
- labels:
|
||||
letter: a
|
||||
useNameAsPrefix: false
|
||||
- labels:
|
||||
letter: b
|
||||
explicitPrefix: two
|
||||
- labels:
|
||||
letter: c
|
||||
- labels:
|
||||
letter: d
|
||||
useNameAsPrefix: true
|
||||
Reference in New Issue
Block a user