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`.
|
- `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
|
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
|
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:
|
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;
|
package org.springframework.cloud.kubernetes.client.config;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
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.ConfigUtils;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
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 org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||||
|
|
||||||
import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.dataFromSecret;
|
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<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
LabeledSecretNormalizedSource source = (LabeledSecretNormalizedSource) context.normalizedSource();
|
LabeledSecretNormalizedSource source = (LabeledSecretNormalizedSource) context.normalizedSource();
|
||||||
|
Set<String> propertySourceNames = new LinkedHashSet<>();
|
||||||
Map<String, String> labels = source.labels();
|
Map<String, String> labels = source.labels();
|
||||||
String namespace = context.namespace();
|
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 {
|
try {
|
||||||
|
|
||||||
@@ -77,10 +81,42 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Kuberne
|
|||||||
createLabelsSelector(labels), null, null, null, null, null).getItems();
|
createLabelsSelector(labels), null, null, null, null, null).getItems();
|
||||||
|
|
||||||
if (!secrets.isEmpty()) {
|
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);
|
onException(source.failFast(), message, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String propertySourceName = ConfigUtils.sourceName(source.target(), sourceName, namespace);
|
// if we could not find a secret with provided labels, we will compute a
|
||||||
return new SourceData(propertySourceName, result);
|
// 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());
|
propertySourceNames.add(entry.getValue());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!"".equals(source.prefix())) {
|
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
// since we are in a named source, calling get on the supplier is safe
|
||||||
propertySourceNames);
|
String prefix = source.prefix().prefixProvider().get();
|
||||||
|
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,9 +72,10 @@ final class NamedSecretContextToSourceDataProvider implements Supplier<Kubernete
|
|||||||
|
|
||||||
secret.ifPresent(s -> result.putAll(dataFromSecret(s, namespace)));
|
secret.ifPresent(s -> result.putAll(dataFromSecret(s, namespace)));
|
||||||
|
|
||||||
if (!"".equals(source.prefix()) && !result.isEmpty()) {
|
if (source.prefix() != ConfigUtils.Prefix.DEFAULT && !result.isEmpty()) {
|
||||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
// since we are in a named source, calling get on the supplier is safe
|
||||||
propertySourceNames);
|
String prefix = source.prefix().prefixProvider().get();
|
||||||
|
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
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.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
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.NamedConfigMapNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
@@ -100,7 +101,7 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
|
.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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||||
@@ -121,7 +122,7 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(YAML_CONFIGMAP_LIST))));
|
.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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||||
@@ -142,7 +143,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(PROPERTIES_CONFIGMAP_LIST))));
|
.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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
KubernetesClientConfigMapPropertySource propertySource = new KubernetesClientConfigMapPropertySource(context);
|
||||||
@@ -161,7 +163,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
@Test
|
@Test
|
||||||
void constructorWithNamespaceMustNotFail() {
|
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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -173,7 +176,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
.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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -188,7 +192,8 @@ class KubernetesClientConfigMapPropertySourceTests {
|
|||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
.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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(new CoreV1Api(), source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get(API).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SECRET_LIST))));
|
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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ class KubernetesClientSecretsPropertySourceTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get(API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error")));
|
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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, "default",
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.kubernetes.client.config;
|
|||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
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.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
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.LabeledSecretNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||||
@@ -193,4 +195,93 @@ class LabeledSecretContextToSourceDataProviderTests {
|
|||||||
Assertions.assertEquals(sourceData.sourceData(), Map.of("color", "really-red"));
|
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.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
|
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.NamedConfigMapNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||||
@@ -90,7 +91,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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();
|
MockEnvironment environment = new MockEnvironment();
|
||||||
environment.setActiveProfiles("with-profile");
|
environment.setActiveProfiles("with-profile");
|
||||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE, environment);
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE, environment);
|
||||||
@@ -194,7 +195,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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);
|
true);
|
||||||
MockEnvironment environment = new MockEnvironment();
|
MockEnvironment environment = new MockEnvironment();
|
||||||
environment.setActiveProfiles("with-profile");
|
environment.setActiveProfiles("with-profile");
|
||||||
@@ -241,7 +243,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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);
|
true);
|
||||||
MockEnvironment environment = new MockEnvironment();
|
MockEnvironment environment = new MockEnvironment();
|
||||||
environment.setActiveProfiles("with-taste", "with-shape");
|
environment.setActiveProfiles("with-taste", "with-shape");
|
||||||
@@ -271,7 +274,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -302,7 +306,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
CoreV1Api api = new CoreV1Api();
|
CoreV1Api api = new CoreV1Api();
|
||||||
stubFor(get("/api/v1/namespaces/default/configmaps")
|
stubFor(get("/api/v1/namespaces/default/configmaps")
|
||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList))));
|
.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);
|
false);
|
||||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||||
|
|
||||||
// blue does not match red
|
// 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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||||
|
|
||||||
// blue does not match red
|
// 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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||||
|
|
||||||
// blue does not match red
|
// 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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList))));
|
||||||
|
|
||||||
// blue does not match red
|
// 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,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE,
|
||||||
new MockEnvironment());
|
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,
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = NamedSecretWithPrefixApp.class,
|
||||||
properties = { "spring.cloud.bootstrap.name=named-secret-with-prefix", "named.secret.with.prefix.stub=true",
|
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 {
|
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,
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = NamedSecretWithPrefixApp.class,
|
||||||
properties = { "spring.cloud.application.name=named-secret-with-prefix", "named.secret.with.prefix.stub=true",
|
properties = { "spring.cloud.application.name=named-secret-with-prefix", "named.secret.with.prefix.stub=true",
|
||||||
"spring.main.cloud-platform=KUBERNETES",
|
"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 {
|
class NamedSecretWithPrefixConfigDataTests extends NamedSecretWithPrefixTests {
|
||||||
|
|
||||||
private static MockedStatic<KubernetesClientUtils> clientUtilsMock;
|
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.bootstrap.BootstrapConfiguration=\
|
||||||
org.springframework.cloud.kubernetes.client.config.boostrap.stubs.IncludeProfileSpecificSourcesConfigurationStub, \
|
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.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
|
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");
|
String name = getApplicationName(environment, this.name, "Config Map");
|
||||||
return Collections.singletonList(
|
return Collections.singletonList(
|
||||||
new NamedConfigMapNormalizedSource(name, namespace, failFast, "", includeProfileSpecificSources));
|
new NamedConfigMapNormalizedSource(name, namespace, failFast, includeProfileSpecificSources));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sources.stream()
|
return sources.stream()
|
||||||
@@ -185,8 +185,8 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
|
|||||||
boolean defaultIncludeProfileSpecificSources, boolean failFast) {
|
boolean defaultIncludeProfileSpecificSources, boolean failFast) {
|
||||||
String normalizedName = StringUtils.hasLength(this.name) ? this.name : defaultName;
|
String normalizedName = StringUtils.hasLength(this.name) ? this.name : defaultName;
|
||||||
String normalizedNamespace = StringUtils.hasLength(this.namespace) ? this.namespace : defaultNamespace;
|
String normalizedNamespace = StringUtils.hasLength(this.namespace) ? this.namespace : defaultNamespace;
|
||||||
String prefix = ConfigUtils.findPrefix(this.explicitPrefix, useNameAsPrefix, defaultUseNameAsPrefix,
|
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix(this.explicitPrefix, useNameAsPrefix,
|
||||||
normalizedName);
|
defaultUseNameAsPrefix, normalizedName);
|
||||||
boolean includeProfileSpecificSources = ConfigUtils.includeProfileSpecificSources(
|
boolean includeProfileSpecificSources = ConfigUtils.includeProfileSpecificSources(
|
||||||
defaultIncludeProfileSpecificSources, this.includeProfileSpecificSources);
|
defaultIncludeProfileSpecificSources, this.includeProfileSpecificSources);
|
||||||
return new NamedConfigMapNormalizedSource(normalizedName, normalizedNamespace, failFast, prefix,
|
return new NamedConfigMapNormalizedSource(normalizedName, normalizedNamespace, failFast, prefix,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.springframework.cloud.kubernetes.commons.config;
|
package org.springframework.cloud.kubernetes.commons.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -61,31 +62,49 @@ public final class ConfigUtils {
|
|||||||
* @param normalizedName either the name of
|
* @param normalizedName either the name of
|
||||||
* 'spring.cloud.kubernetes.config|secrets.sources.name' or
|
* 'spring.cloud.kubernetes.config|secrets.sources.name' or
|
||||||
* 'spring.cloud.kubernetes.config|secrets.name'
|
* '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) {
|
String normalizedName) {
|
||||||
// if explicitPrefix is set, it takes priority over useNameAsPrefix
|
// if explicitPrefix is set, it takes priority over useNameAsPrefix
|
||||||
// (either the one from 'spring.cloud.kubernetes.config|secrets' or
|
// (either the one from 'spring.cloud.kubernetes.config|secrets' or
|
||||||
// 'spring.cloud.kubernetes.config|secrets.sources')
|
// 'spring.cloud.kubernetes.config|secrets.sources')
|
||||||
if (StringUtils.hasText(explicitPrefix)) {
|
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
|
// useNameAsPrefix is a java.lang.Boolean and if it's != null, users have
|
||||||
// specified it explicitly
|
// specified it explicitly
|
||||||
if (useNameAsPrefix != null) {
|
if (useNameAsPrefix != null) {
|
||||||
if (useNameAsPrefix) {
|
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) {
|
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;
|
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 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) {
|
public LabeledSecretNormalizedSource(String namespace, Map<String, String> labels, boolean failFast) {
|
||||||
super(null, namespace, failFast);
|
super(null, namespace, failFast);
|
||||||
this.labels = Collections.unmodifiableMap(Objects.requireNonNull(labels));
|
this.labels = Collections.unmodifiableMap(Objects.requireNonNull(labels));
|
||||||
|
this.prefix = ConfigUtils.Prefix.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +51,10 @@ public final class LabeledSecretNormalizedSource extends NormalizedSource {
|
|||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConfigUtils.Prefix prefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NormalizedSourceType type() {
|
public NormalizedSourceType type() {
|
||||||
return NormalizedSourceType.LABELED_SECRET;
|
return NormalizedSourceType.LABELED_SECRET;
|
||||||
|
|||||||
@@ -25,18 +25,25 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class NamedConfigMapNormalizedSource extends NormalizedSource {
|
public final class NamedConfigMapNormalizedSource extends NormalizedSource {
|
||||||
|
|
||||||
private final String prefix;
|
private final ConfigUtils.Prefix prefix;
|
||||||
|
|
||||||
private final boolean includeProfileSpecificSources;
|
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) {
|
boolean includeProfileSpecificSources) {
|
||||||
super(name, namespace, failFast);
|
super(name, namespace, failFast);
|
||||||
this.prefix = Objects.requireNonNull(prefix);
|
this.prefix = Objects.requireNonNull(prefix);
|
||||||
this.includeProfileSpecificSources = includeProfileSpecificSources;
|
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;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,14 +25,19 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class NamedSecretNormalizedSource extends NormalizedSource {
|
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);
|
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;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,10 +96,11 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
|||||||
if (this.sources.isEmpty()) {
|
if (this.sources.isEmpty()) {
|
||||||
List<NormalizedSource> result = new ArrayList<>(2);
|
List<NormalizedSource> result = new ArrayList<>(2);
|
||||||
String name = getApplicationName(environment, this.name, "Secret");
|
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()) {
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -195,17 +196,17 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
|||||||
|
|
||||||
String secretName = getApplicationName(environment, normalizedName, "Secret");
|
String secretName = getApplicationName(environment, normalizedName, "Secret");
|
||||||
|
|
||||||
String prefix = ConfigUtils.findPrefix(this.explicitPrefix, this.useNameAsPrefix, defaultUseNameAsPrefix,
|
ConfigUtils.Prefix prefix = ConfigUtils.findPrefix(this.explicitPrefix, this.useNameAsPrefix,
|
||||||
normalizedName);
|
defaultUseNameAsPrefix, normalizedName);
|
||||||
|
|
||||||
NormalizedSource nameBasedSource = new NamedSecretNormalizedSource(secretName, normalizedNamespace,
|
NormalizedSource namedBasedSource = new NamedSecretNormalizedSource(secretName, normalizedNamespace,
|
||||||
failFast, prefix);
|
failFast, prefix);
|
||||||
normalizedSources.add(nameBasedSource);
|
normalizedSources.add(namedBasedSource);
|
||||||
|
|
||||||
if (!normalizedLabels.isEmpty()) {
|
if (!normalizedLabels.isEmpty()) {
|
||||||
NormalizedSource labelsBasedSource = new LabeledSecretNormalizedSource(normalizedNamespace, labels,
|
NormalizedSource labeledBasedSource = new LabeledSecretNormalizedSource(normalizedNamespace, labels,
|
||||||
failFast);
|
failFast, prefix);
|
||||||
normalizedSources.add(labelsBasedSource);
|
normalizedSources.add(labeledBasedSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalizedSources.build();
|
return normalizedSources.build();
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class ConfigMapConfigPropertiesTests {
|
|||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
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");
|
"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());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
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,"
|
"empty sources must generate a List with a single NormalizedSource, where prefix is empty,"
|
||||||
+ "no matter of 'spring.cloud.kubernetes.config.useNameAsPrefix' value");
|
+ "no matter of 'spring.cloud.kubernetes.config.useNameAsPrefix' value");
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,8 @@ class ConfigMapConfigPropertiesTests {
|
|||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "a single NormalizedSource is expected");
|
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());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "");
|
Assertions.assertSame(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix(), "config-map-two");
|
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix(), "config-map-three");
|
"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());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix(), "one");
|
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(0)).prefix().prefixProvider().get(),
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix(), "two");
|
"one");
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(2)).prefix(), "three");
|
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||||
Assertions.assertEquals(((NamedConfigMapNormalizedSource) sources.get(3)).prefix(), "");
|
"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
|
@Test
|
||||||
void testExplicitPrefixSet() {
|
void testExplicitPrefixSet() {
|
||||||
String result = ConfigUtils.findPrefix("explicitPrefix", null, false, "irrelevant");
|
ConfigUtils.Prefix result = ConfigUtils.findPrefix("explicitPrefix", null, false, "irrelevant");
|
||||||
Assertions.assertEquals(result, "explicitPrefix");
|
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||||
|
Assertions.assertEquals(result.prefixProvider().get(), "explicitPrefix");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUseNameAsPrefixTrue() {
|
void testUseNameAsPrefixTrue() {
|
||||||
String result = ConfigUtils.findPrefix("", Boolean.TRUE, false, "name-to-use");
|
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", Boolean.TRUE, false, "name-to-use");
|
||||||
Assertions.assertEquals(result, "name-to-use");
|
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||||
|
Assertions.assertEquals(result.prefixProvider().get(), "name-to-use");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUseNameAsPrefixFalse() {
|
void testUseNameAsPrefixFalse() {
|
||||||
String result = ConfigUtils.findPrefix("", Boolean.FALSE, false, "name-not-to-use");
|
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", Boolean.FALSE, false, "name-not-to-use");
|
||||||
Assertions.assertEquals(result, "");
|
Assertions.assertSame(result, ConfigUtils.Prefix.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDefaultUseNameAsPrefixTrue() {
|
void testDefaultUseNameAsPrefixTrue() {
|
||||||
String result = ConfigUtils.findPrefix("", null, true, "name-to-use");
|
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", null, true, "name-to-use");
|
||||||
Assertions.assertEquals(result, "name-to-use");
|
Assertions.assertSame(result, ConfigUtils.Prefix.KNOWN);
|
||||||
|
Assertions.assertEquals(result.prefixProvider().get(), "name-to-use");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testNoMatch() {
|
void testNoMatch() {
|
||||||
String result = ConfigUtils.findPrefix("", null, false, "name-not-to-use");
|
ConfigUtils.Prefix result = ConfigUtils.findPrefix("", null, false, "name-not-to-use");
|
||||||
Assertions.assertEquals(result, "");
|
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);
|
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
|
@Test
|
||||||
void testType() {
|
void testType() {
|
||||||
LabeledSecretNormalizedSource source = new LabeledSecretNormalizedSource("namespace", labels, false);
|
LabeledSecretNormalizedSource source = new LabeledSecretNormalizedSource("namespace", labels, false);
|
||||||
@@ -58,10 +75,12 @@ class LabeledSecretNormalizedSourceTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConstructorFields() {
|
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.assertTrue(source.name().isEmpty());
|
||||||
Assertions.assertEquals(source.namespace().get(), "namespace");
|
Assertions.assertEquals(source.namespace().get(), "namespace");
|
||||||
Assertions.assertFalse(source.failFast());
|
Assertions.assertFalse(source.failFast());
|
||||||
|
Assertions.assertSame(source.prefix(), prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,18 @@ import org.junit.jupiter.api.Test;
|
|||||||
*/
|
*/
|
||||||
class NamedConfigMapNormalizedSourceTests {
|
class NamedConfigMapNormalizedSourceTests {
|
||||||
|
|
||||||
|
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "prefix");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testEqualsAndHashCode() {
|
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);
|
true);
|
||||||
NamedConfigMapNormalizedSource right = new NamedConfigMapNormalizedSource("name", "namespace", true,
|
NamedConfigMapNormalizedSource right = new NamedConfigMapNormalizedSource("name", "namespace", true, knownRight,
|
||||||
"non-equal-prefix", false);
|
false);
|
||||||
|
|
||||||
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
||||||
Assertions.assertEquals(left, right);
|
Assertions.assertEquals(left, right);
|
||||||
@@ -37,21 +43,22 @@ class NamedConfigMapNormalizedSourceTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testType() {
|
void testType() {
|
||||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
|
||||||
|
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||||
true);
|
true);
|
||||||
Assertions.assertSame(one.type(), NormalizedSourceType.NAMED_CONFIG_MAP);
|
Assertions.assertSame(one.type(), NormalizedSourceType.NAMED_CONFIG_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testTarget() {
|
void testTarget() {
|
||||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||||
true);
|
true);
|
||||||
Assertions.assertEquals(one.target(), "configmap");
|
Assertions.assertEquals(one.target(), "configmap");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConstructorFields() {
|
void testConstructorFields() {
|
||||||
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, "prefix",
|
NamedConfigMapNormalizedSource one = new NamedConfigMapNormalizedSource("name", "namespace", false, PREFIX,
|
||||||
true);
|
true);
|
||||||
Assertions.assertEquals(one.name().get(), "name");
|
Assertions.assertEquals(one.name().get(), "name");
|
||||||
Assertions.assertEquals(one.namespace().get(), "namespace");
|
Assertions.assertEquals(one.namespace().get(), "namespace");
|
||||||
|
|||||||
@@ -24,10 +24,12 @@ import org.junit.jupiter.api.Test;
|
|||||||
*/
|
*/
|
||||||
class NamedSecretNormalizedSourceTests {
|
class NamedSecretNormalizedSourceTests {
|
||||||
|
|
||||||
|
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "prefix");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testEqualsAndHashCode() {
|
void testEqualsAndHashCode() {
|
||||||
NamedSecretNormalizedSource left = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
NamedSecretNormalizedSource left = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||||
NamedSecretNormalizedSource right = new NamedSecretNormalizedSource("name", "namespace", true, "");
|
NamedSecretNormalizedSource right = new NamedSecretNormalizedSource("name", "namespace", true);
|
||||||
|
|
||||||
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
Assertions.assertEquals(left.hashCode(), right.hashCode());
|
||||||
Assertions.assertEquals(left, right);
|
Assertions.assertEquals(left, right);
|
||||||
@@ -35,23 +37,23 @@ class NamedSecretNormalizedSourceTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testType() {
|
void testType() {
|
||||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||||
Assertions.assertSame(source.type(), NormalizedSourceType.NAMED_SECRET);
|
Assertions.assertSame(source.type(), NormalizedSourceType.NAMED_SECRET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testTarget() {
|
void testTarget() {
|
||||||
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false, "");
|
NamedSecretNormalizedSource source = new NamedSecretNormalizedSource("name", "namespace", false);
|
||||||
Assertions.assertEquals(source.target(), "secret");
|
Assertions.assertEquals(source.target(), "secret");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testConstructorFields() {
|
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.name().get(), "name");
|
||||||
Assertions.assertEquals(source.namespace().get(), "namespace");
|
Assertions.assertEquals(source.namespace().get(), "namespace");
|
||||||
Assertions.assertFalse(source.failFast());
|
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.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@@ -133,8 +134,7 @@ class SecretsConfigPropertiesTests {
|
|||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "",
|
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,8 +162,8 @@ class SecretsConfigPropertiesTests {
|
|||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
Assertions.assertEquals(sources.size(), 1, "empty sources must generate a List with a single NormalizedSource");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "",
|
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT,
|
||||||
"empty sources must generate a List with a single NormalizedSource, where prefix is empty,"
|
"empty sources must generate a List with a single NormalizedSource, where prefix is unset,"
|
||||||
+ "no matter of 'spring.cloud.kubernetes.secret.useNameAsPrefix' value");
|
+ "no matter of 'spring.cloud.kubernetes.secret.useNameAsPrefix' value");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +195,8 @@ class SecretsConfigPropertiesTests {
|
|||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 1, "a single NormalizedSource is expected");
|
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());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
Assertions.assertEquals(sources.size(), 3, "3 NormalizedSources are expected");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "");
|
Assertions.assertSame(((NamedSecretNormalizedSource) sources.get(0)).prefix(), ConfigUtils.Prefix.DEFAULT);
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix(), "secret-two");
|
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix().prefixProvider().get(),
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix(), "secret-three");
|
"secret-two");
|
||||||
|
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||||
|
"secret-three");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,31 +277,105 @@ class SecretsConfigPropertiesTests {
|
|||||||
properties.setNamespace("spring-k8s");
|
properties.setNamespace("spring-k8s");
|
||||||
|
|
||||||
SecretsConfigProperties.Source one = new SecretsConfigProperties.Source();
|
SecretsConfigProperties.Source one = new SecretsConfigProperties.Source();
|
||||||
one.setNamespace("secret-one");
|
one.setName("secret-one");
|
||||||
one.setUseNameAsPrefix(false);
|
one.setUseNameAsPrefix(false);
|
||||||
one.setExplicitPrefix("one");
|
one.setExplicitPrefix("one");
|
||||||
|
|
||||||
SecretsConfigProperties.Source two = new SecretsConfigProperties.Source();
|
SecretsConfigProperties.Source two = new SecretsConfigProperties.Source();
|
||||||
two.setNamespace("secret-two");
|
two.setName("secret-two");
|
||||||
two.setUseNameAsPrefix(true);
|
two.setUseNameAsPrefix(true);
|
||||||
two.setExplicitPrefix("two");
|
two.setExplicitPrefix("two");
|
||||||
|
|
||||||
SecretsConfigProperties.Source three = new SecretsConfigProperties.Source();
|
SecretsConfigProperties.Source three = new SecretsConfigProperties.Source();
|
||||||
three.setNamespace("secret-three");
|
three.setName("secret-three");
|
||||||
three.setExplicitPrefix("three");
|
three.setExplicitPrefix("three");
|
||||||
|
|
||||||
SecretsConfigProperties.Source four = new SecretsConfigProperties.Source();
|
SecretsConfigProperties.Source four = new SecretsConfigProperties.Source();
|
||||||
four.setNamespace("secret-four");
|
four.setName("secret-four");
|
||||||
|
|
||||||
properties.setSources(Arrays.asList(one, two, three, four));
|
properties.setSources(Arrays.asList(one, two, three, four));
|
||||||
|
|
||||||
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
List<NormalizedSource> sources = properties.determineSources(new MockEnvironment());
|
||||||
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
Assertions.assertEquals(sources.size(), 4, "4 NormalizedSources are expected");
|
||||||
|
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix(), "one");
|
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(0)).prefix().prefixProvider().get(), "one");
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix(), "two");
|
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(1)).prefix().prefixProvider().get(), "two");
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix(), "three");
|
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(2)).prefix().prefixProvider().get(),
|
||||||
Assertions.assertEquals(((NamedSecretNormalizedSource) sources.get(3)).prefix(), "");
|
"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 -> {
|
namespaces.forEach(space -> {
|
||||||
|
|
||||||
NamedConfigMapNormalizedSource source = new NamedConfigMapNormalizedSource(applicationName, space,
|
NamedConfigMapNormalizedSource source = new NamedConfigMapNormalizedSource(applicationName, space,
|
||||||
false, "", true);
|
false, true);
|
||||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
||||||
springEnv);
|
springEnv);
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ public class KubernetesConfigServerAutoConfiguration {
|
|||||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
List<MapPropertySource> propertySources = new ArrayList<>();
|
||||||
|
|
||||||
namespaces.forEach(space -> {
|
namespaces.forEach(space -> {
|
||||||
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, space, false, "");
|
NormalizedSource source = new NamedSecretNormalizedSource(applicationName, space, false);
|
||||||
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, space,
|
||||||
springEnv);
|
springEnv);
|
||||||
propertySources.add(new KubernetesClientSecretsPropertySource(context));
|
propertySources.add(new KubernetesClientSecretsPropertySource(context));
|
||||||
|
|||||||
@@ -101,12 +101,12 @@ class KubernetesEnvironmentRepositoryTests {
|
|||||||
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
||||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
List<MapPropertySource> propertySources = new ArrayList<>();
|
||||||
|
|
||||||
NormalizedSource defaultSource = new NamedConfigMapNormalizedSource(applicationName, "default", false, "",
|
NormalizedSource defaultSource = new NamedConfigMapNormalizedSource(applicationName, "default", false,
|
||||||
true);
|
true);
|
||||||
KubernetesClientConfigContext defaultContext = new KubernetesClientConfigContext(coreApi, defaultSource,
|
KubernetesClientConfigContext defaultContext = new KubernetesClientConfigContext(coreApi, defaultSource,
|
||||||
"default", springEnv);
|
"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",
|
KubernetesClientConfigContext devContext = new KubernetesClientConfigContext(coreApi, devSource, "dev",
|
||||||
springEnv);
|
springEnv);
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ class KubernetesEnvironmentRepositoryTests {
|
|||||||
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
kubernetesPropertySourceSuppliers.add((coreApi, applicationName, namespace, springEnv) -> {
|
||||||
List<MapPropertySource> propertySources = new ArrayList<>();
|
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",
|
KubernetesClientConfigContext context = new KubernetesClientConfigContext(coreApi, source, "default",
|
||||||
springEnv);
|
springEnv);
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
package org.springframework.cloud.kubernetes.fabric8.config;
|
package org.springframework.cloud.kubernetes.fabric8.config;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
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.ConfigUtils;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.LabeledSecretNormalizedSource;
|
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 org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||||
|
|
||||||
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException;
|
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException;
|
||||||
@@ -64,11 +67,12 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Fabric8
|
|||||||
return context -> {
|
return context -> {
|
||||||
|
|
||||||
LabeledSecretNormalizedSource source = ((LabeledSecretNormalizedSource) context.normalizedSource());
|
LabeledSecretNormalizedSource source = ((LabeledSecretNormalizedSource) context.normalizedSource());
|
||||||
|
Set<String> propertySourceNames = new LinkedHashSet<>();
|
||||||
Map<String, String> labels = source.labels();
|
Map<String, String> labels = source.labels();
|
||||||
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
String namespace = context.namespace();
|
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 {
|
try {
|
||||||
|
|
||||||
@@ -77,9 +81,43 @@ final class LabeledSecretContextToSourceDataProvider implements Supplier<Fabric8
|
|||||||
.getItems();
|
.getItems();
|
||||||
|
|
||||||
if (!secrets.isEmpty()) {
|
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));
|
.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 {
|
else {
|
||||||
LOG.info("No Secret(s) with labels '" + labels + "' in namespace '" + namespace + "' found.");
|
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);
|
onException(source.failFast(), message, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String propertySourceName = ConfigUtils.sourceName(source.target(), sourceName, namespace);
|
// if we could not find a secret with provided labels, we will compute a
|
||||||
return new SourceData(propertySourceName, result);
|
// 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())) {
|
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
// since we are in a named source, calling get on the supplier is safe
|
||||||
propertySourceNames);
|
String prefix = source.prefix().prefixProvider().get();
|
||||||
|
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,11 @@ final class NamedSecretContextToSourceDataProvider implements Supplier<Fabric8Co
|
|||||||
else {
|
else {
|
||||||
result = dataFromSecret(secret, namespace);
|
result = dataFromSecret(secret, namespace);
|
||||||
|
|
||||||
if (!"".equals(source.prefix())) {
|
if (source.prefix() != ConfigUtils.Prefix.DEFAULT) {
|
||||||
PrefixContext prefixContext = new PrefixContext(result, source.prefix(), namespace,
|
// since we are in a named source, calling get on the supplier is
|
||||||
propertySourceNames);
|
// safe
|
||||||
|
String prefix = source.prefix().prefixProvider().get();
|
||||||
|
PrefixContext prefixContext = new PrefixContext(result, prefix, namespace, propertySourceNames);
|
||||||
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
return ConfigUtils.withPrefix(source.target(), prefixContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class ConfigMapsTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
@@ -92,7 +92,7 @@ public class ConfigMapsTest {
|
|||||||
.addToData("application.yaml", ConfigMapTestUtil.readResourceFile("application.yaml")).build();
|
.addToData("application.yaml", ConfigMapTestUtil.readResourceFile("application.yaml")).build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
@@ -109,7 +109,7 @@ public class ConfigMapsTest {
|
|||||||
.addToData("adhoc.yml", ConfigMapTestUtil.readResourceFile("adhoc.yml")).build();
|
.addToData("adhoc.yml", ConfigMapTestUtil.readResourceFile("adhoc.yml")).build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
@@ -126,7 +126,7 @@ public class ConfigMapsTest {
|
|||||||
.addToData("application.properties", "somevalue").build();
|
.addToData("application.properties", "somevalue").build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
@@ -141,7 +141,7 @@ public class ConfigMapsTest {
|
|||||||
.addToData("application.yaml", "somevalue").build();
|
.addToData("application.yaml", "somevalue").build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
@@ -157,7 +157,7 @@ public class ConfigMapsTest {
|
|||||||
.addToData("adhoc.properties", ConfigMapTestUtil.readResourceFile("adhoc.properties")).build();
|
.addToData("adhoc.properties", ConfigMapTestUtil.readResourceFile("adhoc.properties")).build();
|
||||||
|
|
||||||
mockClient.configMaps().inNamespace("test").create(configMap);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
|
|
||||||
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource cmps = new Fabric8ConfigMapPropertySource(context);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class EventBasedConfigurationChangeDetectorTests {
|
|||||||
when(mixedOperation.inNamespace("default")).thenReturn(mixedOperation);
|
when(mixedOperation.inNamespace("default")).thenReturn(mixedOperation);
|
||||||
when(k8sClient.getNamespace()).thenReturn("default");
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(k8sClient, source, "default", new MockEnvironment());
|
||||||
Fabric8ConfigMapPropertySource fabric8ConfigMapPropertySource = new Fabric8ConfigMapPropertySource(context);
|
Fabric8ConfigMapPropertySource fabric8ConfigMapPropertySource = new Fabric8ConfigMapPropertySource(context);
|
||||||
env.getPropertySources().addFirst(new BootstrapPropertySource<>(fabric8ConfigMapPropertySource));
|
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.KubernetesNamespaceProvider;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
|
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.NamedConfigMapNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException;
|
import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
@@ -45,6 +46,8 @@ class Fabric8ConfigMapPropertySourceLocatorTests {
|
|||||||
|
|
||||||
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
||||||
|
|
||||||
|
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("prefix", false, false, "irrelevant");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
||||||
String name = "my-config";
|
String name = "my-config";
|
||||||
@@ -95,7 +98,7 @@ class Fabric8ConfigMapPropertySourceLocatorTests {
|
|||||||
Mockito.when(client.getNamespace()).thenReturn(null);
|
Mockito.when(client.getNamespace()).thenReturn(null);
|
||||||
Fabric8ConfigMapPropertySourceLocator source = new Fabric8ConfigMapPropertySourceLocator(client,
|
Fabric8ConfigMapPropertySourceLocator source = new Fabric8ConfigMapPropertySourceLocator(client,
|
||||||
configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment()));
|
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()))
|
assertThatThrownBy(() -> source.getMapPropertySource(normalizedSource, new MockEnvironment()))
|
||||||
.isInstanceOf(NamespaceResolutionFailedException.class);
|
.isInstanceOf(NamespaceResolutionFailedException.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mockito;
|
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.NamedConfigMapNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
@@ -43,6 +44,8 @@ class Fabric8ConfigMapPropertySourceTests {
|
|||||||
|
|
||||||
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
private final DefaultKubernetesClient client = Mockito.mock(DefaultKubernetesClient.class);
|
||||||
|
|
||||||
|
private static final ConfigUtils.Prefix DEFAULT = ConfigUtils.findPrefix("default", false, false, "irrelevant");
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
void constructorShouldThrowExceptionOnFailureWhenFailFastIsEnabled() {
|
||||||
final String name = "my-config";
|
final String name = "my-config";
|
||||||
@@ -50,7 +53,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
|||||||
final String path = String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, name);
|
final String path = String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, name);
|
||||||
|
|
||||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "default", new MockEnvironment());
|
||||||
assertThatThrownBy(() -> new Fabric8ConfigMapPropertySource(context)).isInstanceOf(IllegalStateException.class)
|
assertThatThrownBy(() -> new Fabric8ConfigMapPropertySource(context)).isInstanceOf(IllegalStateException.class)
|
||||||
.hasMessage("Unable to read ConfigMap with name '" + name + "' in namespace '" + namespace + "'");
|
.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);
|
final String path = String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, name);
|
||||||
|
|
||||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
assertThatNoException().isThrownBy(() -> new Fabric8ConfigMapPropertySource(context));
|
assertThatNoException().isThrownBy(() -> new Fabric8ConfigMapPropertySource(context));
|
||||||
}
|
}
|
||||||
@@ -72,7 +75,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
|||||||
void constructorWithClientNamespaceMustNotFail() {
|
void constructorWithClientNamespaceMustNotFail() {
|
||||||
|
|
||||||
Mockito.when(client.getNamespace()).thenReturn("namespace");
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
||||||
}
|
}
|
||||||
@@ -81,7 +84,7 @@ class Fabric8ConfigMapPropertySourceTests {
|
|||||||
void constructorWithNamespaceMustNotFail() {
|
void constructorWithNamespaceMustNotFail() {
|
||||||
|
|
||||||
Mockito.when(client.getNamespace()).thenReturn(null);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, source, "", new MockEnvironment());
|
||||||
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
assertThat(new Fabric8ConfigMapPropertySource(context)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Fabric8SecretsPropertySourceMockTests {
|
|||||||
final String namespace = "default";
|
final String namespace = "default";
|
||||||
final String path = String.format("/api/v1/namespaces/%s/secrets/%s", namespace, name);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(client, named, "default", new MockEnvironment());
|
||||||
|
|
||||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
||||||
@@ -77,7 +77,7 @@ class Fabric8SecretsPropertySourceMockTests {
|
|||||||
final String namespace = "default";
|
final String namespace = "default";
|
||||||
final String path = String.format("/api/v1/namespaces/%s/secrets/%s", namespace, name);
|
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());
|
Fabric8ConfigContext context = new Fabric8ConfigContext(client, named, "default", new MockEnvironment());
|
||||||
|
|
||||||
mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once();
|
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.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
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.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
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.LabeledSecretNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
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).
|
* does not (color=blue).
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@@ -186,4 +188,83 @@ class LabeledSecretContextToSourceDataProviderTests {
|
|||||||
Assertions.assertEquals(Map.of("secretName", "secretValue"), sourceData.sourceData());
|
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.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySource;
|
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.NamedConfigMapNormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
|
||||||
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
import org.springframework.cloud.kubernetes.commons.config.SourceData;
|
||||||
@@ -48,6 +49,8 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
private static KubernetesClient mockClient;
|
private static KubernetesClient mockClient;
|
||||||
|
|
||||||
|
private static final ConfigUtils.Prefix PREFIX = ConfigUtils.findPrefix("some", false, false, "irrelevant");
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void beforeAll() {
|
static void beforeAll() {
|
||||||
|
|
||||||
@@ -77,7 +80,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -131,7 +134,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
// add one more profile and specify that we want profile based config maps
|
// add one more profile and specify that we want profile based config maps
|
||||||
MockEnvironment env = new MockEnvironment();
|
MockEnvironment env = new MockEnvironment();
|
||||||
env.setActiveProfiles("with-profile");
|
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);
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||||
|
|
||||||
@@ -167,7 +170,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
// also append prefix
|
// also append prefix
|
||||||
MockEnvironment env = new MockEnvironment();
|
MockEnvironment env = new MockEnvironment();
|
||||||
env.setActiveProfiles("with-profile");
|
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);
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||||
|
|
||||||
@@ -207,7 +210,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
// also append prefix
|
// also append prefix
|
||||||
MockEnvironment env = new MockEnvironment();
|
MockEnvironment env = new MockEnvironment();
|
||||||
env.setActiveProfiles("with-taste", "with-shape");
|
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);
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE, env);
|
||||||
|
|
||||||
@@ -232,8 +235,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||||
|
|
||||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, "",
|
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("application", NAMESPACE, true, false);
|
||||||
false);
|
|
||||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -259,8 +261,7 @@ class NamedConfigMapContextToSourceDataProviderTests {
|
|||||||
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
mockClient.configMaps().inNamespace(NAMESPACE).create(configMap);
|
||||||
|
|
||||||
// different namespace
|
// different namespace
|
||||||
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE + "nope", true, "",
|
NormalizedSource normalizedSource = new NamedConfigMapNormalizedSource("red", NAMESPACE + "nope", true, false);
|
||||||
false);
|
|
||||||
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
mockClient.secrets().inNamespace(NAMESPACE).create(blue);
|
mockClient.secrets().inNamespace(NAMESPACE).create(blue);
|
||||||
mockClient.secrets().inNamespace(NAMESPACE).create(yellow);
|
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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
|
|
||||||
mockClient.secrets().inNamespace(NAMESPACE).create(pink);
|
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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
new MockEnvironment());
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ class NamedSecretContextToSourceDataProviderTests {
|
|||||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
||||||
|
|
||||||
// different namespace
|
// 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,
|
Fabric8ConfigContext context = new Fabric8ConfigContext(mockClient, normalizedSource, NAMESPACE,
|
||||||
new MockEnvironment());
|
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