Skip to content

Commit 78cf7fd

Browse files
author
Ryan Baxter
committed
Merge remote-tracking branch 'origin/1.0.x'
2 parents f0eab0e + 296bf1e commit 78cf7fd

File tree

4 files changed

+192
-2
lines changed

4 files changed

+192
-2
lines changed

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,59 @@ However, if the `production` profile is active, the configuration becomes:
182182

183183
If both profiles are active, the property that appears last within the `ConfigMap` overwrites any preceding values.
184184

185+
Another option is to create a different config map per profile and spring boot will automatically fetch it based
186+
on active profiles
187+
188+
====
189+
[source,yaml]
190+
----
191+
kind: ConfigMap
192+
apiVersion: v1
193+
metadata:
194+
name: demo
195+
data:
196+
application.yml: |-
197+
greeting:
198+
message: Say Hello to the World
199+
farewell:
200+
message: Say Goodbye
201+
----
202+
====
203+
====
204+
[source,yaml]
205+
----
206+
kind: ConfigMap
207+
apiVersion: v1
208+
metadata:
209+
name: demo-development
210+
data:
211+
application.yml: |-
212+
spring:
213+
profiles: development
214+
greeting:
215+
message: Say Hello to the Developers
216+
farewell:
217+
message: Say Goodbye to the Developers
218+
----
219+
====
220+
====
221+
[source,yaml]
222+
----
223+
kind: ConfigMap
224+
apiVersion: v1
225+
metadata:
226+
name: demo-production
227+
data:
228+
application.yml: |-
229+
spring:
230+
profiles: production
231+
greeting:
232+
message: Say Hello to the Ops
233+
farewell:
234+
message: Say Goodbye
235+
----
236+
====
237+
185238

186239
To tell Spring Boot which `profile` should be enabled at bootstrap, you can pass `SPRING_PROFILES_ACTIVE` environment variable.
187240
To do so, you can launch your Spring Boot application with an environment variable that you can define it in the PodSpec at the container specification.

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* A {@link MapPropertySource} that uses Kubernetes config maps.
4141
*
4242
* @author Ioannis Canellos
43+
* @author Ali Shahbour
4344
*/
4445
public class ConfigMapPropertySource extends MapPropertySource {
4546

@@ -59,7 +60,7 @@ public ConfigMapPropertySource(KubernetesClient client, String name) {
5960

6061
public ConfigMapPropertySource(KubernetesClient client, String name, String namespace,
6162
String[] profiles) {
62-
this(client, name, null, createEnvironmentWithActiveProfiles(profiles));
63+
this(client, name, namespace, createEnvironmentWithActiveProfiles(profiles));
6364
}
6465

6566
private static Environment createEnvironmentWithActiveProfiles(
@@ -88,13 +89,33 @@ private static String getName(KubernetesClient client, String name,
8889
private static Map<String, String> getData(KubernetesClient client, String name,
8990
String namespace, Environment environment) {
9091
try {
92+
Map<String, String> result = new HashMap<>();
9193
ConfigMap map = StringUtils.isEmpty(namespace)
9294
? client.configMaps().withName(name).get()
9395
: client.configMaps().inNamespace(namespace).withName(name).get();
9496

9597
if (map != null) {
96-
return processAllEntries(map.getData(), environment);
98+
result.putAll(processAllEntries(map.getData(), environment));
9799
}
100+
101+
if (environment != null) {
102+
for (String activeProfile:environment.getActiveProfiles()) {
103+
104+
String mapNameWithProfile = name + "-" + activeProfile;
105+
106+
ConfigMap mapWithProfile = StringUtils.isEmpty(namespace)
107+
? client.configMaps().withName(mapNameWithProfile).get()
108+
: client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get();
109+
110+
if (mapWithProfile != null) {
111+
result.putAll(processAllEntries(mapWithProfile.getData(), environment));
112+
}
113+
114+
}
115+
}
116+
117+
return result;
118+
98119
}
99120
catch (Exception e) {
100121
LOG.warn("Can't read configMap with name: [" + name + "] in namespace:["
@@ -104,6 +125,7 @@ private static Map<String, String> getData(KubernetesClient client, String name,
104125
return new HashMap<>();
105126
}
106127

128+
107129
private static Map<String, String> processAllEntries(Map<String, String> input,
108130
Environment environment) {
109131

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2013-2019 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+
* http://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.config;
18+
19+
import java.util.HashMap;
20+
21+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
22+
import io.fabric8.kubernetes.client.Config;
23+
import io.fabric8.kubernetes.client.KubernetesClient;
24+
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
25+
import org.junit.BeforeClass;
26+
import org.junit.ClassRule;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
30+
import org.springframework.beans.factory.annotation.Autowired;
31+
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
32+
import org.springframework.boot.test.context.SpringBootTest;
33+
import org.springframework.cloud.kubernetes.config.example.App;
34+
import org.springframework.test.context.ActiveProfiles;
35+
import org.springframework.test.context.junit4.SpringRunner;
36+
import org.springframework.test.web.reactive.server.WebTestClient;
37+
38+
import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
39+
40+
/**
41+
* @author Ali Shahbour
42+
*/
43+
@RunWith(SpringRunner.class)
44+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = {
45+
"spring.application.name=configmap-with-active-profile-name-example",
46+
"spring.cloud.kubernetes.reload.enabled=false" })
47+
@ActiveProfiles("development")
48+
@AutoConfigureWebTestClient
49+
public class ConfigMapsWithActiveProfilesNameSpringBootTest {
50+
51+
private static final String APPLICATION_NAME = "configmap-with-active-profile-name-example";
52+
53+
@ClassRule
54+
public static KubernetesServer server = new KubernetesServer();
55+
56+
private static KubernetesClient mockClient;
57+
58+
@Autowired(required = false)
59+
Config config;
60+
61+
@Autowired
62+
private WebTestClient webClient;
63+
64+
@BeforeClass
65+
public static void setUpBeforeClass() {
66+
mockClient = server.getClient();
67+
68+
// Configure the kubernetes master url to point to the mock server
69+
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY,
70+
mockClient.getConfiguration().getMasterUrl());
71+
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
72+
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
73+
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY,
74+
"false");
75+
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
76+
77+
HashMap<String, String> data = new HashMap<>();
78+
data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
79+
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
80+
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
81+
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
82+
.always();
83+
84+
HashMap<String, String> dataWithName = new HashMap<>();
85+
dataWithName.put("application.yml",
86+
readResourceFile("application-with-active-profiles-name.yaml"));
87+
server.expect()
88+
.withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME
89+
+ "-development")
90+
.andReturn(200,
91+
new ConfigMapBuilder().withNewMetadata()
92+
.withName(APPLICATION_NAME + "-development").endMetadata()
93+
.addToData(dataWithName).build())
94+
.always();
95+
}
96+
97+
@Test
98+
public void testGreetingEndpoint() {
99+
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
100+
.expectBody().jsonPath("content")
101+
.isEqualTo("Hello ConfigMap Active Profile Name, World!");
102+
}
103+
104+
@Test
105+
public void testFarewellEndpoint() {
106+
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
107+
.expectBody().jsonPath("content")
108+
.isEqualTo("Goodbye ConfigMap default, World!");
109+
}
110+
111+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
spring:
2+
profiles: development
3+
bean:
4+
greeting: "Hello ConfigMap Active Profile Name, %s!"

0 commit comments

Comments
 (0)