Skip to content

Commit 2600cb6

Browse files
authored
fix 1338 (#1340)
1 parent d3e718a commit 2600cb6

File tree

26 files changed

+983
-1
lines changed

26 files changed

+983
-1
lines changed

docs/src/main/asciidoc/property-source-config.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,11 @@ such a method. This, in turn, could be configured via environment properties. Fo
725725

726726
Failure to find a namespace from the above steps will result in an Exception being raised.
727727

728+
[[order_of_configMaps_and_secrets]]
729+
=== Order of ConfigMaps and Secrets
730+
731+
If, for whatever reason, you enabled both configmaps and secrets, and there is a common property between them, the value from the ConfigMap will have a higher precedence. That is: it will override whatever values are found in secrets.
732+
728733
=== `PropertySource` Reload
729734

730735
WARNING: This functionality has been deprecated in the 2020.0 release. Please see

spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
2424
import org.springframework.cloud.kubernetes.commons.config.ConfigMapPropertySourceLocator;
2525
import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException;
26+
import org.springframework.core.annotation.Order;
2627
import org.springframework.core.env.ConfigurableEnvironment;
2728
import org.springframework.core.env.MapPropertySource;
2829
import org.springframework.util.StringUtils;
@@ -31,6 +32,7 @@
3132
* @author Ryan Baxter
3233
* @author Isik Erhan
3334
*/
35+
@Order(0)
3436
public class KubernetesClientConfigMapPropertySourceLocator extends ConfigMapPropertySourceLocator {
3537

3638
private final CoreV1Api coreV1Api;

spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException;
2424
import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
2525
import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySourceLocator;
26+
import org.springframework.core.annotation.Order;
2627
import org.springframework.core.env.ConfigurableEnvironment;
2728
import org.springframework.core.env.MapPropertySource;
2829
import org.springframework.util.StringUtils;
@@ -33,6 +34,7 @@
3334
* @author Ryan Baxter
3435
* @author Isik Erhan
3536
*/
37+
@Order(1)
3638
public class KubernetesClientSecretsPropertySourceLocator extends SecretsPropertySourceLocator {
3739

3840
private final CoreV1Api coreV1Api;

spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/RetryableKubernetesClientConfigMapPropertySourceLocator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
2424
import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
25+
import org.springframework.core.annotation.Order;
2526
import org.springframework.core.env.Environment;
2627
import org.springframework.core.env.PropertySource;
2728
import org.springframework.retry.annotation.Retryable;
@@ -31,6 +32,7 @@
3132
*
3233
* @author Ryan Baxter
3334
*/
35+
@Order(0)
3436
class RetryableKubernetesClientConfigMapPropertySourceLocator extends KubernetesClientConfigMapPropertySourceLocator {
3537

3638
RetryableKubernetesClientConfigMapPropertySourceLocator(CoreV1Api coreV1Api, ConfigMapConfigProperties properties,

spring-cloud-kubernetes-client-config/src/main/java/org/springframework/cloud/kubernetes/client/config/RetryableKubernetesClientSecretsPropertySourceLocator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider;
2424
import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
25+
import org.springframework.core.annotation.Order;
2526
import org.springframework.core.env.Environment;
2627
import org.springframework.core.env.PropertySource;
2728
import org.springframework.retry.annotation.Retryable;
@@ -31,6 +32,7 @@
3132
*
3233
* @author Ryan Baxter
3334
*/
35+
@Order(1)
3436
class RetryableKubernetesClientSecretsPropertySourceLocator extends KubernetesClientSecretsPropertySourceLocator {
3537

3638
RetryableKubernetesClientSecretsPropertySourceLocator(CoreV1Api coreV1Api,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.config;
18+
19+
import com.github.tomakehurst.wiremock.client.WireMock;
20+
import org.hamcrest.Matchers;
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
26+
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.cloud.kubernetes.client.config.applications.sources_order.SourcesOrderApp;
30+
import org.springframework.test.context.junit.jupiter.SpringExtension;
31+
import org.springframework.test.web.reactive.server.WebTestClient;
32+
33+
/**
34+
* The stub data for this test is in :
35+
* {@link org.springframework.cloud.kubernetes.client.config.boostrap.stubs.SourcesOrderConfigurationStub}
36+
*
37+
* @author wind57
38+
*/
39+
@ExtendWith(SpringExtension.class)
40+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SourcesOrderApp.class,
41+
properties = { "spring.cloud.bootstrap.name=sources-order", "sources.order.stub=true" })
42+
@AutoConfigureWebTestClient
43+
class KubernetesClientSourcesOrderTests {
44+
45+
@Autowired
46+
private WebTestClient webClient;
47+
48+
@AfterEach
49+
void afterEach() {
50+
WireMock.reset();
51+
}
52+
53+
@AfterAll
54+
static void afterAll() {
55+
WireMock.shutdownServer();
56+
}
57+
58+
/**
59+
* <pre>
60+
* 1. There is one secret deployed: my-secret. It has two properties: {my.one=one, my.key=from-secret}
61+
* 2. There is one configmap deployed: my-configmap. It has two properties: {my.two=two, my.key=from-configmap}
62+
*
63+
* We invoke three endpoints: /one, /two, /key.
64+
* The first two prove that both the secret and configmap have been read, the last one proves that
65+
* config maps have a higher precedence.
66+
* </pre>
67+
*/
68+
@Test
69+
void test() {
70+
this.webClient.get().uri("/one").exchange().expectStatus().isOk().expectBody(String.class)
71+
.value(Matchers.equalTo("one"));
72+
this.webClient.get().uri("/two").exchange().expectStatus().isOk().expectBody(String.class)
73+
.value(Matchers.equalTo("two"));
74+
75+
this.webClient.get().uri("/key").exchange().expectStatus().isOk().expectBody(String.class)
76+
.value(Matchers.equalTo("from-configmap"));
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.config;
18+
19+
import com.github.tomakehurst.wiremock.client.WireMock;
20+
import org.hamcrest.Matchers;
21+
import org.junit.jupiter.api.AfterAll;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
26+
import org.springframework.beans.factory.annotation.Autowired;
27+
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.cloud.kubernetes.client.config.applications.sources_order.SourcesOrderApp;
30+
import org.springframework.test.context.junit.jupiter.SpringExtension;
31+
import org.springframework.test.web.reactive.server.WebTestClient;
32+
33+
/**
34+
* The stub data for this test is in :
35+
* {@link org.springframework.cloud.kubernetes.client.config.boostrap.stubs.SourcesOrderConfigurationStub}
36+
*
37+
* @author wind57
38+
*/
39+
@ExtendWith(SpringExtension.class)
40+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SourcesOrderApp.class,
41+
properties = { "spring.cloud.bootstrap.name=retryable-sources-order", "sources.order.stub=true" })
42+
@AutoConfigureWebTestClient
43+
class RetryableKubernetesClientSourcesOrderTests {
44+
45+
@Autowired
46+
private WebTestClient webClient;
47+
48+
@AfterEach
49+
void afterEach() {
50+
WireMock.reset();
51+
}
52+
53+
@AfterAll
54+
static void afterAll() {
55+
WireMock.shutdownServer();
56+
}
57+
58+
/**
59+
* <pre>
60+
* 1. There is one secret deployed: my-secret. It has two properties: {my.one=one, my.key=from-secret}
61+
* 2. There is one configmap deployed: my-configmap. It has two properties: {my.two=two, my.key=from-configmap}
62+
*
63+
* We invoke three endpoints: /one, /two, /key.
64+
* The first two prove that both the secret and configmap have been read, the last one proves that
65+
* config maps have a higher precedence.
66+
* </pre>
67+
*/
68+
@Test
69+
void test() {
70+
this.webClient.get().uri("/one").exchange().expectStatus().isOk().expectBody(String.class)
71+
.value(Matchers.equalTo("one"));
72+
this.webClient.get().uri("/two").exchange().expectStatus().isOk().expectBody(String.class)
73+
.value(Matchers.equalTo("two"));
74+
75+
this.webClient.get().uri("/key").exchange().expectStatus().isOk().expectBody(String.class)
76+
.value(Matchers.equalTo("from-configmap"));
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.config.applications.sources_order;
18+
19+
import org.springframework.boot.SpringApplication;
20+
import org.springframework.boot.autoconfigure.SpringBootApplication;
21+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
22+
import org.springframework.cloud.kubernetes.client.config.applications.sources_order.properties.Properties;
23+
24+
/**
25+
* @author wind57
26+
*/
27+
@SpringBootApplication
28+
@EnableConfigurationProperties(Properties.class)
29+
public class SourcesOrderApp {
30+
31+
public static void main(String[] args) {
32+
SpringApplication.run(SourcesOrderApp.class, args);
33+
}
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.config.applications.sources_order.controller;
18+
19+
import org.springframework.cloud.kubernetes.client.config.applications.sources_order.properties.Properties;
20+
import org.springframework.web.bind.annotation.GetMapping;
21+
import org.springframework.web.bind.annotation.RestController;
22+
23+
/**
24+
* @author wind57
25+
*/
26+
@RestController
27+
public class SourcesOrderController {
28+
29+
private final Properties properties;
30+
31+
SourcesOrderController(Properties properties) {
32+
this.properties = properties;
33+
}
34+
35+
@GetMapping("/key")
36+
String key() {
37+
return properties.getKey();
38+
}
39+
40+
@GetMapping("/one")
41+
String one() {
42+
return properties.getOne();
43+
}
44+
45+
@GetMapping("/two")
46+
String two() {
47+
return properties.getTwo();
48+
}
49+
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2013-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.client.config.applications.sources_order.properties;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
21+
/**
22+
* @author wind57
23+
*/
24+
@ConfigurationProperties("my")
25+
public class Properties {
26+
27+
private String key;
28+
29+
private String one;
30+
31+
private String two;
32+
33+
public String getKey() {
34+
return key;
35+
}
36+
37+
public void setKey(String key) {
38+
this.key = key;
39+
}
40+
41+
public String getOne() {
42+
return one;
43+
}
44+
45+
public void setOne(String one) {
46+
this.one = one;
47+
}
48+
49+
public String getTwo() {
50+
return two;
51+
}
52+
53+
public void setTwo(String two) {
54+
this.two = two;
55+
}
56+
57+
}

0 commit comments

Comments
 (0)