Merge pull request #1914 from wind57/fix-1757

Fix #1757
This commit is contained in:
Ryan Baxter
2025-05-06 11:17:38 -04:00
committed by GitHub
49 changed files with 1361 additions and 634 deletions

View File

@@ -34,11 +34,10 @@ class LabeledConfigMapContextToSourceDataProvider implements Supplier<Kubernetes
* There could be many sources that are read based on incoming labels, for which we
* will be computing a single Map<String, Object> in the end.
*
* If there is no config maps found for the provided labels, we will return an "empty"
* SourceData. Its name is going to be the concatenated labels mapped to an empty Map.
* If there are no config maps found for the provided labels, we will return an
* "empty" SourceData. Its name is going to be the concatenated labels mapped to an
* empty Map.
*
* If we find config maps(s) for the provided labels, its name is going to be the
* concatenated names mapped to the data they hold as a Map.
*/
@Override
public KubernetesClientContextToSourceData get() {

View File

@@ -49,6 +49,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
@@ -318,10 +319,10 @@ class LabeledConfigMapContextToSourceDataProviderTests {
String secondKey = keys.next();
if (firstKey.contains("first")) {
Assertions.assertThat(firstKey).isEqualTo("another-blue-configmap.blue-configmap.first");
Assertions.assertThat(firstKey).isEqualTo("blue-configmap.first");
}
Assertions.assertThat(secondKey).isEqualTo("another-blue-configmap.blue-configmap.second");
Assertions.assertThat(secondKey).isEqualTo("another-blue-configmap.second");
Assertions.assertThat(properties.get(firstKey)).isEqualTo("blue");
Assertions.assertThat(properties.get(secondKey)).isEqualTo("blue");
}
@@ -445,11 +446,10 @@ class LabeledConfigMapContextToSourceDataProviderTests {
KubernetesClientContextToSourceData data = new LabeledConfigMapContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(2);
Assertions.assertThat(sourceData.sourceData().get("color-configmap.color-configmap-k8s.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-configmap.color-configmap-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceName())
.isEqualTo("configmap.color-configmap.color-configmap-k8s.default");
assertThat(sourceData.sourceData().size()).isEqualTo(2);
assertThat(sourceData.sourceData().get("color-configmap.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("color-configmap-k8s.two")).isEqualTo("2");
assertThat(sourceData.sourceName()).isEqualTo("configmap.color-configmap.color-configmap-k8s.default");
}
@@ -523,25 +523,13 @@ class LabeledConfigMapContextToSourceDataProviderTests {
KubernetesClientContextToSourceData data = new LabeledConfigMapContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(4);
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.one"))
.isEqualTo("1");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.two"))
.isEqualTo("2");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.four"))
.isEqualTo("4");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.five"))
.isEqualTo("5");
assertThat(sourceData.sourceData().size()).isEqualTo(4);
assertThat(sourceData.sourceData().get("color-configmap.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("shape-configmap.two")).isEqualTo("2");
assertThat(sourceData.sourceData().get("color-configmap-k8s.four")).isEqualTo("4");
assertThat(sourceData.sourceData().get("shape-configmap-k8s.five")).isEqualTo("5");
Assertions.assertThat(sourceData.sourceName())
assertThat(sourceData.sourceName())
.isEqualTo("configmap.color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.default");
}

View File

@@ -51,6 +51,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
@@ -292,10 +293,10 @@ class LabeledSecretContextToSourceDataProviderTests {
String secondKey = keys.next();
if (firstKey.contains("first")) {
Assertions.assertThat(firstKey).isEqualTo("another-blue-secret.blue-secret.first");
Assertions.assertThat(firstKey).isEqualTo("blue-secret.first");
}
Assertions.assertThat(secondKey).isEqualTo("another-blue-secret.blue-secret.second");
Assertions.assertThat(secondKey).isEqualTo("another-blue-secret.second");
Assertions.assertThat(properties.get(firstKey)).isEqualTo("blue");
Assertions.assertThat(properties.get(secondKey)).isEqualTo("blue");
}
@@ -383,8 +384,8 @@ class LabeledSecretContextToSourceDataProviderTests {
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(2);
Assertions.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceData().get("color-secret.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-secret-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceName()).isEqualTo("secret.color-secret.color-secret-k8s.default");
}
@@ -459,21 +460,13 @@ class LabeledSecretContextToSourceDataProviderTests {
KubernetesClientContextToSourceData data = new LabeledSecretContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(4);
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.one"))
.isEqualTo("1");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.two"))
.isEqualTo("2");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.four"))
.isEqualTo("4");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.five"))
.isEqualTo("5");
assertThat(sourceData.sourceData().size()).isEqualTo(4);
assertThat(sourceData.sourceData().get("color-secret.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("shape-secret.two")).isEqualTo("2");
assertThat(sourceData.sourceData().get("color-secret-k8s.four")).isEqualTo("4");
assertThat(sourceData.sourceData().get("shape-secret-k8s.five")).isEqualTo("5");
Assertions.assertThat(sourceData.sourceName())
assertThat(sourceData.sourceName())
.isEqualTo("secret.color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.default");
}

View File

@@ -169,18 +169,18 @@ class NamedConfigMapContextToSourceDataProviderTests {
CoreV1Api api = new CoreV1Api();
NormalizedSource source = new NamedConfigMapNormalizedSource(RED_CONFIG_MAP_NAME, NAMESPACE, true,
ConfigUtils.Prefix.DEFAULT, true, true);
ConfigUtils.Prefix.DEFAULT, true);
MockEnvironment environment = new MockEnvironment();
environment.setActiveProfiles("with-profile");
environment.addActiveProfile("with-profile");
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE, environment,
false);
true);
KubernetesClientContextToSourceData data = new NamedConfigMapContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceName()).isEqualTo("configmap.red.red-with-profile.default.with-profile");
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(1);
Assertions.assertThat(sourceData.sourceData().get("taste")).isEqualTo("mango");
Assertions.assertThat(sourceData.sourceName()).isEqualTo("configmap.red.red-with-profile.default");
Assertions.assertThat(sourceData.sourceData())
.containsExactlyInAnyOrderEntriesOf(Map.of("color", "really-red", "taste", "mango"));
}

View File

@@ -229,14 +229,15 @@ class NamedSecretContextToSourceDataProviderTests {
MockEnvironment environment = new MockEnvironment();
environment.addActiveProfile("with-profile");
KubernetesClientConfigContext context = new KubernetesClientConfigContext(api, source, NAMESPACE, environment,
false);
true);
KubernetesClientContextToSourceData data = new NamedSecretContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceName()).isEqualTo("secret.red.red-with-profile.default.with-profile");
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(1);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(2);
Assertions.assertThat(sourceData.sourceData().get("taste")).isEqualTo("mango");
Assertions.assertThat(sourceData.sourceData().get("color")).isEqualTo("really-red");
}

View File

@@ -21,12 +21,17 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenPurpleK8s;
/**
* @author wind57
*/
@SpringBootApplication
@EnableConfigurationProperties({ Blue.class, Green.class })
@EnableConfigurationProperties({ Blue.class, Green.class, GreenK8s.class, GreenProd.class, GreenPurple.class,
GreenPurpleK8s.class })
public class LabeledConfigMapWithProfileApp {
public static void main(String[] args) {

View File

@@ -17,14 +17,21 @@
package org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile;
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.applications.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.GreenPurpleK8s;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Stub data is in
* {@link org.springframework.cloud.kubernetes.client.config.bootstrap.stubs.LabeledConfigMapWithProfileConfigurationStub}
@@ -36,6 +43,24 @@ abstract class LabeledConfigMapWithProfileTests {
@Autowired
private WebTestClient webClient;
@Autowired
private Blue blue;
@Autowired
private Green green;
@Autowired
private GreenK8s greenK8s;
@Autowired
private GreenProd greenProd;
@Autowired
private GreenPurple greenPurple;
@Autowired
private GreenPurpleK8s greenPurpleK8s;
@AfterEach
void afterEach() {
WireMock.reset();
@@ -55,32 +80,35 @@ abstract class LabeledConfigMapWithProfileTests {
*/
@Test
void testBlue() {
this.webClient.get()
.uri("/labeled-configmap/profile/blue")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("1"));
assertThat(blue.getOne()).isEqualTo("1");
}
/**
* <pre>
* this one is taken from : ""green-configmap.green-configmap-k8s.green-configmap-prod.green-purple-configmap.green-purple-configmap-k8s"".
* We find "green-configmap" by labels, also "green-configmap-k8s", "green-configmap-prod" exists,
* because "includeProfileSpecificSources=true" is set. Also "green-purple-configmap" and "green-purple-configmap-k8s"
* are found.
* </pre>
*/
// found by labels
@Test
void testGreen() {
this.webClient.get()
.uri("/labeled-configmap/profile/green")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("2#6#7#eight-ish"));
assertThat(green.getTwo()).isEqualTo("2");
}
// found because above is found, plus active profile is included
@Test
void testGreenK8s() {
assertThat(greenK8s.getSix()).isEqualTo("6");
}
// found because above is found, plus active profile is included
@Test
void testGreenProd() {
assertThat(greenProd.getSeven()).isEqualTo("7");
}
@Test
void testGreenPurple() {
assertThat(greenPurple.getEight()).isEqualTo("8");
}
@Test
void testGreenPurpleK8s() {
assertThat(greenPurpleK8s.getEight()).isEqualTo("eight-ish");
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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_config_map_with_profile.controller;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_config_map_with_profile.properties.Green;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LabeledConfigMapWithProfileController {
private final Blue blue;
private final Green green;
public LabeledConfigMapWithProfileController(Blue blue, Green green) {
this.blue = blue;
this.green = green;
}
@GetMapping("/labeled-configmap/profile/blue")
public String blue() {
return blue.getOne();
}
@GetMapping("/labeled-configmap/profile/green")
public String green() {
return green.getTwo() + "#" + green.getSix() + "#" + green.getSeven() + "#" + green.getEight();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* Copyright 2013-2025 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.
@@ -18,17 +18,11 @@ package org.springframework.cloud.kubernetes.client.config.applications.labeled_
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap.green-configmap-k8s.green-configmap-prod.green-purple-configmap.green-purple-configmap-k8s")
@ConfigurationProperties("green-configmap")
public class Green {
private String two;
private String six;
private String seven;
private String eight;
public String getTwo() {
return two;
}
@@ -37,28 +31,4 @@ public class Green {
this.two = two;
}
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap-k8s")
public class GreenK8s {
private String six;
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap-prod")
public class GreenProd {
private String seven;
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-configmap")
public class GreenPurple {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-configmap-k8s")
public class GreenPurpleK8s {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -21,9 +21,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenPurpleK8s;
@SpringBootApplication
@EnableConfigurationProperties({ Blue.class, Green.class })
@EnableConfigurationProperties({ Blue.class, Green.class, GreenK8s.class, GreenProd.class, GreenPurple.class,
GreenPurpleK8s.class })
public class LabeledSecretWithProfileApp {
public static void main(String[] args) {

View File

@@ -17,13 +17,19 @@
package org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile;
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.test.web.reactive.server.WebTestClient;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.GreenPurpleK8s;
import static org.assertj.core.api.Assertions.assertThat;
/*
* <pre>
@@ -46,7 +52,22 @@ import org.springframework.test.web.reactive.server.WebTestClient;
abstract class LabeledSecretWithProfileTests {
@Autowired
private WebTestClient webClient;
private Blue blue;
@Autowired
private Green green;
@Autowired
private GreenK8s greenK8s;
@Autowired
private GreenProd greenProd;
@Autowired
private GreenPurple greenPurple;
@Autowired
private GreenPurpleK8s greenPurpleK8s;
@AfterEach
public void afterEach() {
@@ -67,32 +88,32 @@ abstract class LabeledSecretWithProfileTests {
*/
@Test
void testBlue() {
this.webClient.get()
.uri("/labeled-secret/profile/blue")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("1"));
assertThat(blue.getOne()).isEqualTo("1");
}
/**
* <pre>
* this one is taken from : "green-purple-secret.green-purple-secret-k8s.green-secret.green-secret-k8s.green-secret-prod".
* We find "green-secret" by labels, also "green-secrets-k8s" and "green-secrets-prod" exists,
* because "includeProfileSpecificSources=true" is set. Also "green-purple-secret" and "green-purple-secret-k8s"
* are found.
* </pre>
*/
@Test
void testGreen() {
this.webClient.get()
.uri("/labeled-secret/profile/green")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("2#6#7#eight-ish"));
assertThat(green.getTwo()).isEqualTo("2");
}
@Test
void testGreenK8s() {
assertThat(greenK8s.getSix()).isEqualTo("6");
}
@Test
void testGreenProd() {
assertThat(greenProd.getSeven()).isEqualTo("7");
}
@Test
void testGreenPurple() {
assertThat(greenPurple.getEight()).isEqualTo("8");
}
@Test
void testGreenPurpleK8s() {
assertThat(greenPurpleK8s.getEight()).isEqualTo("eight-ish");
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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_profile.controller;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.client.config.applications.labeled_secret_with_profile.properties.Green;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LabeledSecretWithProfileController {
private final Blue blue;
private final Green green;
public LabeledSecretWithProfileController(Blue blue, Green green) {
this.blue = blue;
this.green = green;
}
@GetMapping("/labeled-secret/profile/blue")
public String blue() {
return blue.getOne();
}
@GetMapping("/labeled-secret/profile/green")
public String green() {
return green.getTwo() + "#" + green.getSix() + "#" + green.getSeven() + "#" + green.getEight();
}
}

View File

@@ -18,17 +18,11 @@ package org.springframework.cloud.kubernetes.client.config.applications.labeled_
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret.green-purple-secret-k8s.green-secret.green-secret-k8s.green-secret-prod")
@ConfigurationProperties("green-secret")
public class Green {
private String two;
private String six;
private String seven;
private String eight;
public String getTwo() {
return two;
}
@@ -37,28 +31,4 @@ public class Green {
this.two = two;
}
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-secret-k8s")
public class GreenK8s {
private String six;
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-secret-prod")
public class GreenProd {
private String seven;
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret")
public class GreenPurple {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret-k8s")
public class GreenPurpleK8s {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -158,10 +158,11 @@ public final class ConfigUtils {
}
/*
* this method will return a SourceData that has a name in the form :
* This method will return a SourceData that has a name in the form :
* "configmap.my-configmap.my-configmap-2.namespace" and the "data" from the context
* is appended with prefix. So if incoming is "a=b", the result will be : "prefix.a=b"
*/
@Deprecated(forRemoval = true)
public static SourceData withPrefix(String target, PrefixContext context) {
Map<String, Object> withPrefix = CollectionUtils.newHashMap(context.data().size());
context.data().forEach((key, value) -> withPrefix.put(context.prefix() + "." + key, value));
@@ -189,7 +190,7 @@ public final class ConfigUtils {
}
/**
* transforms raw data from one or multiple sources into an entry of source names and
* Transforms raw data from one or multiple sources into an entry of source names and
* flattened data that they all hold (potentially overriding entries without any
* defined order).
*/
@@ -203,10 +204,10 @@ public final class ConfigUtils {
LinkedHashSet<String> foundSourceNames = new LinkedHashSet<>();
Map<String, Object> data = new HashMap<>();
// this is an ordered stream, and it means that non-profile based sources will be
// processed before profile based sources. This way, we replicate that
// "application-dev.yaml"
// overrides properties from "application.yaml"
// This is an ordered stream, and it means that non-profile-based sources will be
// processed before profile-based sources.
// This way, we replicate that "application-dev.yaml" overrides properties from
// "application.yaml"
sourceNames.forEach(sourceName -> {
StrippedSourceContainer stripped = hashByName.get(sourceName);
if (stripped != null) {
@@ -219,14 +220,16 @@ public final class ConfigUtils {
}
/*
* In some cases we want to include properties from the default profile
* along with any active profiles In these cases includeDefaultProfileData
* will be true If includeDefaultProfileData is false then we want to make
* sure that we only return properties from any active profiles
* In some cases, we want to include properties from the default profile
* along with any active profiles. In these cases,
* includeDefaultProfileData will be true If includeDefaultProfileData is
* false then we want to make sure that we only return properties from any
* active profiles
*/
if (processSource(includeDefaultProfileData, environment, sourceName, rawData)) {
data.putAll(SourceDataEntriesProcessor.processAllEntries(rawData == null ? Map.of() : rawData,
environment, includeDefaultProfileData));
Map<String, Object> processedData = SourceDataEntriesProcessor.processAllEntries(
rawData == null ? Map.of() : rawData, environment, includeDefaultProfileData);
data.put(sourceName, processedData);
}
}
else {
@@ -270,13 +273,17 @@ public final class ConfigUtils {
.anyMatch(activeProfile -> ENDS_WITH_PROFILE_AND_EXTENSION.test(keyName, activeProfile)));
}
static String sourceDataName(String target, LinkedHashSet<String> sourceNames, String namespace) {
String sortedNames = sourceNames.stream().sorted().collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
return sourceName(target, sortedNames, namespace);
}
/**
* transforms raw data from one or multiple sources into an entry of source names and
* Transforms raw data from one or multiple sources into an entry of source names and
* flattened data that they all hold (potentially overriding entries without any
* defined order). This method first searches by labels, find the sources, then uses
* these names to find any profile based sources.
* these names to find any profile-based sources.
*/
public static MultipleSourcesContainer processLabeledData(List<StrippedSourceContainer> containers,
Environment environment, Map<String, String> labels, String namespace, Set<String> profiles,
boolean decode) {
@@ -288,7 +295,7 @@ public final class ConfigUtils {
return labelsToSearchAgainst.entrySet().containsAll((labels.entrySet()));
}).toList();
// compute profile based source names (based on the ones we found by labels)
// Compute profile-based source names (based on the ones we found by labels)
List<String> sourceNamesByLabelsWithProfile = new ArrayList<>();
if (profiles != null && !profiles.isEmpty()) {
for (StrippedSourceContainer one : byLabels) {
@@ -299,7 +306,7 @@ public final class ConfigUtils {
}
}
// once we know sources by labels (and thus their names), we can find out
// Once we know sources by labels (and thus their names), we can find out
// profiles based sources from the above. This would get all sources
// we are interested in.
List<StrippedSourceContainer> byProfile = containers.stream()
@@ -312,7 +319,7 @@ public final class ConfigUtils {
all.addAll(byProfile);
LinkedHashSet<String> sourceNames = new LinkedHashSet<>();
Map<String, Object> result = new HashMap<>();
Map<String, Object> data = new HashMap<>();
all.forEach(source -> {
String foundSourceName = source.name();
@@ -323,10 +330,12 @@ public final class ConfigUtils {
if (decode) {
rawData = decodeData(rawData);
}
result.putAll(SourceDataEntriesProcessor.processAllEntries(rawData, environment));
Map<String, Object> dataFromOneSource = SourceDataEntriesProcessor.processAllEntries(rawData, environment);
data.put(foundSourceName, dataFromOneSource);
});
return new MultipleSourcesContainer(sourceNames, result);
return new MultipleSourcesContainer(sourceNames, data);
}
private static Map<String, String> decodeData(Map<String, String> data) {
@@ -390,7 +399,7 @@ public final class ConfigUtils {
/**
* prefix is known at the callsite.
*/
public static Prefix KNOWN;
public static Prefix KNOWN = new Prefix(() -> "", "KNOWN");
public Supplier<String> prefixProvider() {
return prefixProvider;
@@ -409,6 +418,10 @@ public final class ConfigUtils {
KNOWN = new Prefix(supplier, "KNOWN");
}
String getName() {
return name;
}
public String toString() {
return new ToStringCreator(this).append("name", name).toString();
}

View File

@@ -17,6 +17,7 @@
package org.springframework.cloud.kubernetes.commons.config;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -24,9 +25,15 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.Prefix;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.sourceDataName;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.sourceName;
import static org.springframework.cloud.kubernetes.commons.config.Constants.ERROR_PROPERTY;
import static org.springframework.cloud.kubernetes.commons.config.Constants.PROPERTY_SOURCE_NAME_SEPARATOR;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.defaultFlattenedSourceData;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.nameFlattenedSourceData;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.prefixFlattenedSourceData;
/**
* @author wind57
@@ -38,10 +45,11 @@ public abstract class LabeledSourceData {
private static final Log LOG = LogFactory.getLog(LabeledSourceData.class);
public final SourceData compute(Map<String, String> labels, ConfigUtils.Prefix prefix, String target,
boolean profileSources, boolean failFast, String namespace, String[] activeProfiles) {
public final SourceData compute(Map<String, String> labels, Prefix prefix, String target, boolean profileSources,
boolean failFast, String namespace, String[] activeProfiles) {
MultipleSourcesContainer data = MultipleSourcesContainer.empty();
String sourceDataName;
try {
Set<String> profiles = Set.of();
@@ -50,43 +58,49 @@ public abstract class LabeledSourceData {
}
data = dataSupplier(labels, profiles);
// need this check because when there is no data, the name of the property
// source is using provided labels,
// unlike when the data is present: when we use secret names
if (data.names().isEmpty()) {
String names = labels.keySet()
.stream()
.sorted()
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
return SourceData.emptyRecord(ConfigUtils.sourceName(target, names, namespace));
LinkedHashSet<String> sourceNames = data.names();
Map<String, Object> sourceDataForSourceName = data.data();
sourceDataName = sourceDataName(target, sourceNames, namespace);
if (sourceNames.isEmpty()) {
return emptySourceData(labels, target, namespace);
}
if (prefix != ConfigUtils.Prefix.DEFAULT) {
String prefixToUse;
if (prefix == ConfigUtils.Prefix.KNOWN) {
prefixToUse = prefix.prefixProvider().get();
}
else {
prefixToUse = data.names()
.stream()
.sorted()
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
}
PrefixContext prefixContext = new PrefixContext(data.data(), prefixToUse, namespace, data.names());
return ConfigUtils.withPrefix(target, prefixContext);
if (prefix.getName().equals(Prefix.DEFAULT.getName())) {
return new SourceData(sourceDataName, defaultFlattenedSourceData(sourceNames, sourceDataForSourceName));
}
if (prefix.getName().equals(Prefix.KNOWN.getName())) {
return new SourceData(sourceDataName,
prefixFlattenedSourceData(sourceNames, sourceDataForSourceName, prefix.prefixProvider().get()));
}
if (prefix.getName().equals(Prefix.DELAYED.getName())) {
return new SourceData(sourceDataName, nameFlattenedSourceData(sourceNames, sourceDataForSourceName));
}
throw new IllegalArgumentException("Unsupported prefix: " + prefix);
}
catch (Exception e) {
LOG.warn("Failure in reading labeled sources");
onException(failFast, e);
data = new MultipleSourcesContainer(data.names(), Map.of(ERROR_PROPERTY, "true"));
return new SourceData(sourceDataName(target, data.names(), namespace), Map.of(ERROR_PROPERTY, "true"));
}
String names = data.names().stream().sorted().collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
return new SourceData(ConfigUtils.sourceName(target, names, namespace), data.data());
}
/*
* When there is no data, the name of the property source is made from provided
* labels, unlike when the data is present: when we use secret names.
*/
private SourceData emptySourceData(Map<String, String> labels, String target, String namespace) {
String sourceName = labels.keySet()
.stream()
.sorted()
.collect(Collectors.collectingAndThen(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR),
sortedLabels -> sourceName(target, sortedLabels, namespace)));
return SourceData.emptyRecord(sourceName);
}
/**

View File

@@ -23,9 +23,14 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.Prefix;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.onException;
import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.sourceName;
import static org.springframework.cloud.kubernetes.commons.config.Constants.ERROR_PROPERTY;
import static org.springframework.cloud.kubernetes.commons.config.Constants.PROPERTY_SOURCE_NAME_SEPARATOR;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.defaultFlattenedSourceData;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.nameFlattenedSourceData;
import static org.springframework.cloud.kubernetes.commons.config.SourceDataFlattener.prefixFlattenedSourceData;
/**
* @author wind57
@@ -37,47 +42,68 @@ public abstract class NamedSourceData {
private static final Log LOG = LogFactory.getLog(NamedSourceData.class);
public final SourceData compute(String sourceName, ConfigUtils.Prefix prefix, String target, boolean profileSources,
public final SourceData compute(String sourceName, Prefix prefix, String target, boolean profileSources,
boolean failFast, String namespace, String[] activeProfiles) {
LinkedHashSet<String> sourceNames = new LinkedHashSet<>();
// first comes non-profile based source
sourceNames.add(sourceName);
// first comes a non-profile-based source
LinkedHashSet<String> sourceNamesToSearchFor = new LinkedHashSet<>();
sourceNamesToSearchFor.add(sourceName);
MultipleSourcesContainer data = MultipleSourcesContainer.empty();
String sourceDataName;
try {
if (profileSources) {
for (String activeProfile : activeProfiles) {
// add all profile based sources _after_ non-profile based one
sourceNames.add(sourceName + "-" + activeProfile);
sourceNamesToSearchFor.add(sourceName + "-" + activeProfile);
}
}
data = dataSupplier(sourceNames);
data = dataSupplier(sourceNamesToSearchFor);
Map<String, Object> sourceDataForSourceName = data.data();
LinkedHashSet<String> sourceNamesFound = data.names();
String sortedNames = data.names()
.stream()
.sorted()
.collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
sourceDataName = generateSourceName(target, sortedNames, namespace, activeProfiles);
if (data.names().isEmpty()) {
String emptySourceName = ConfigUtils.sourceName(target, sourceName, namespace);
LOG.debug("Will return empty source with name : " + emptySourceName);
return SourceData.emptyRecord(emptySourceName);
return emptySourceData(target, sourceName, namespace);
}
if (prefix != ConfigUtils.Prefix.DEFAULT) {
// since we are in a named source, calling get on the supplier is safe
String prefixToUse = prefix.prefixProvider().get();
PrefixContext prefixContext = new PrefixContext(data.data(), prefixToUse, namespace, data.names());
return ConfigUtils.withPrefix(target, prefixContext);
if (prefix.getName().equals(Prefix.DEFAULT.getName())) {
return new SourceData(sourceDataName,
defaultFlattenedSourceData(sourceNamesFound, sourceDataForSourceName));
}
if (prefix.getName().equals(Prefix.KNOWN.getName())) {
return new SourceData(sourceDataName, prefixFlattenedSourceData(sourceNamesFound,
sourceDataForSourceName, prefix.prefixProvider().get()));
}
if (prefix.getName().equals(Prefix.DELAYED.getName())) {
return new SourceData(sourceDataName,
nameFlattenedSourceData(sourceNamesFound, sourceDataForSourceName));
}
throw new IllegalArgumentException("Unsupported prefix: " + prefix);
}
catch (Exception e) {
LOG.warn("Failure in reading named sources");
onException(failFast, e);
data = new MultipleSourcesContainer(data.names(), Map.of(ERROR_PROPERTY, "true"));
String names = data.names().stream().sorted().collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
return new SourceData(generateSourceName(target, names, namespace, activeProfiles),
Map.of(ERROR_PROPERTY, "true"));
}
String names = data.names().stream().sorted().collect(Collectors.joining(PROPERTY_SOURCE_NAME_SEPARATOR));
return new SourceData(generateSourceName(target, names, namespace, activeProfiles), data.data());
}
private SourceData emptySourceData(String target, String sourceName, String namespace) {
String emptySourceName = sourceName(target, sourceName, namespace);
LOG.debug("Will return empty source with name : " + emptySourceName);
return SourceData.emptyRecord(emptySourceName);
}
protected String generateSourceName(String target, String sourceName, String namespace, String[] activeProfiles) {

View File

@@ -24,7 +24,9 @@ import java.util.Set;
* config map.
*
* @author wind57
* @deprecated will be deleted in a future release.
*/
public final record PrefixContext(Map<String, Object> data, String prefix, String namespace,
@Deprecated(forRemoval = true)
public record PrefixContext(Map<String, Object> data, String prefix, String namespace,
Set<String> propertySourceNames) {
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2013-2025 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.commons.config;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
/**
* @author wind57
*/
final class SourceDataFlattener {
private SourceDataFlattener() {
}
/**
* Flattens the data from rawData without any additional processing.
*/
static Map<String, Object> defaultFlattenedSourceData(LinkedHashSet<String> names, Map<String, Object> rawData) {
Map<String, Object> flattenedData = new HashMap<>();
names.forEach(name -> {
@SuppressWarnings("unchecked")
Map<String, Object> singleDataEntry = (Map<String, Object>) rawData.getOrDefault(name, Map.of());
flattenedData.putAll(singleDataEntry);
});
return flattenedData;
}
/**
* Flattens the data from rawData by adding a prefix for each key.
*/
static Map<String, Object> prefixFlattenedSourceData(LinkedHashSet<String> names, Map<String, Object> rawData,
String prefix) {
Map<String, Object> flattenedData = new HashMap<>();
names.forEach(name -> {
@SuppressWarnings("unchecked")
Map<String, Object> singleDataEntry = (Map<String, Object>) rawData.getOrDefault(name, Map.of());
singleDataEntry.forEach((key, value) -> flattenedData.put(prefix + "." + key, value));
});
return flattenedData;
}
/**
* Flattens the data from rawData by adding a prefix for each key, which is equal to
* the source name.
*/
static Map<String, Object> nameFlattenedSourceData(LinkedHashSet<String> names, Map<String, Object> rawData) {
Map<String, Object> flattenedData = new HashMap<>();
names.forEach(name -> {
@SuppressWarnings("unchecked")
Map<String, Object> singleDataEntry = (Map<String, Object>) rawData.getOrDefault(name, Map.of());
singleDataEntry.forEach((key, value) -> flattenedData.put(name + "." + key, value));
});
return flattenedData;
}
}

View File

@@ -81,7 +81,10 @@ class ConfigUtilsProcessSourceTests {
namespace, decode, includeDefaultProfileData);
Assertions.assertThat(result).isNotNull();
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("configmap-a");
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("configmap-a");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1"));
}
/**
@@ -173,7 +176,9 @@ class ConfigUtilsProcessSourceTests {
* since 'k8s' is not an active profile.
* </pre>
*/
Assertions.assertThat(result.data())
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("account");
Assertions.assertThat(data)
.containsExactlyInAnyOrderEntriesOf(Map.of("one", "1", "two", "2", "three", "3", "five", "5"));
Assertions.assertThat(output.getOut()).contains("entry : account-k8s.properties will be skipped");
}
@@ -269,7 +274,9 @@ class ConfigUtilsProcessSourceTests {
* 6. we do not have 'four=4' since we do not read 'account-k8s.properties'
* </pre>
*/
Assertions.assertThat(result.data())
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("account-default");
Assertions.assertThat(data)
.containsExactlyInAnyOrderEntriesOf(Map.of("one", "1", "two", "2", "three", "3", "five", "5"));
Assertions.assertThat(output.getOut()).contains("entry : account-k8s.properties will be skipped");
@@ -368,12 +375,13 @@ class ConfigUtilsProcessSourceTests {
Assertions.assertThat(result).isNotNull();
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("account");
/**
* <pre>
* - we only read from 'account-k8s.properties'
* </pre>
/*
* <pre> - we only read from 'account-k8s.properties' </pre>
*/
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1111", "four", "4"));
@SuppressWarnings("unchecked")
Map<String, Object> accountData = (Map<String, Object>) result.data().get("account");
Assertions.assertThat(accountData).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1111", "four", "4"));
Assertions.assertThat(output.getOut()).contains("entry : account.properties will be skipped");
Assertions.assertThat(output.getOut()).contains("entry : account-default.properties will be skipped");
@@ -473,7 +481,9 @@ class ConfigUtilsProcessSourceTests {
* (because 'prod' is not an active profile)
* </pre>
*/
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1111", "five", "5"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("account-k8s");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1111", "five", "5"));
Assertions.assertThat(output.getOut()).contains("entry : account-prod.properties will be skipped");
Assertions.assertThat(output.getOut()).contains("entry : account.properties will be skipped");
Assertions.assertThat(output.getOut()).contains("entry : account-default.properties will be skipped");

View File

@@ -28,6 +28,8 @@ import org.junit.jupiter.api.Test;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
*/
@@ -138,41 +140,13 @@ class ConfigUtilsTests {
Assertions.assertThat(ConfigUtils.includeProfileSpecificSources(true, false)).isFalse();
}
@Test
void testWithPrefix() {
PrefixContext context = new PrefixContext(Map.of("a", "b", "c", "d"), "prefix", "namespace",
Set.of("name1", "name2"));
SourceData result = ConfigUtils.withPrefix("configmap", context);
Assertions.assertThat(result.sourceName()).isEqualTo("configmap.name1.name2.namespace");
Assertions.assertThat(result.sourceData().get("prefix.a")).isEqualTo("b");
Assertions.assertThat(result.sourceData().get("prefix.c")).isEqualTo("d");
}
/*
* source names should be reproducible all the time, this test asserts this.
*/
@Test
void testWithPrefixSortedName() {
PrefixContext context = new PrefixContext(Map.of("a", "b", "c", "d"), "prefix", "namespace",
Set.of("namec", "namea", "nameb"));
SourceData result = ConfigUtils.withPrefix("configmap", context);
Assertions.assertThat(result.sourceName()).isEqualTo("configmap.namea.nameb.namec.namespace");
Assertions.assertThat(result.sourceData().get("prefix.a")).isEqualTo("b");
Assertions.assertThat(result.sourceData().get("prefix.c")).isEqualTo("d");
}
/**
* <pre>
*
* - we have configmap-one with an application.yaml with two properties propA = A, prop = B
* - we have configmap-one-kubernetes with an application.yaml with two properties propA = AA, probC = C
*
* As a result we should get three properties as output.
* As a result we should get two keys with 2 properties each.
*
* </pre>
*/
@@ -191,10 +165,17 @@ class ConfigUtilsTests {
MultipleSourcesContainer result = ConfigUtils.processNamedData(List.of(configMapOne, configMapOneK8s),
new MockEnvironment(), sourceNames, "default", false);
Assertions.assertThat(result.data().size()).isEqualTo(3);
Assertions.assertThat(result.data().get("propA")).isEqualTo("AA");
Assertions.assertThat(result.data().get("propB")).isEqualTo("B");
Assertions.assertThat(result.data().get("propC")).isEqualTo("C");
Assertions.assertThat(result.data().size()).isEqualTo(2);
@SuppressWarnings("unchecked")
Map<String, Object> one = (Map<String, Object>) result.data().get("configmap-one");
Assertions.assertThat(one.get("propA")).isEqualTo("A");
Assertions.assertThat(one.get("propB")).isEqualTo("B");
@SuppressWarnings("unchecked")
Map<String, Object> oneKubernetes = (Map<String, Object>) result.data().get("configmap-one-kubernetes");
Assertions.assertThat(oneKubernetes.get("propA")).isEqualTo("AA");
Assertions.assertThat(oneKubernetes.get("propC")).isEqualTo("C");
}
@Test
@@ -223,4 +204,30 @@ class ConfigUtilsTests {
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("prefix-a", "b", "prefix-c", "d"));
}
@Test
@SuppressWarnings("unchecked")
void testIssue1757() {
StrippedSourceContainer containerA = new StrippedSourceContainer(Map.of("load", "true"), "client-1",
Map.of("client-id", "clientA", "client-secret", "a"));
StrippedSourceContainer containerB = new StrippedSourceContainer(Map.of("load", "true"), "client-2",
Map.of("client-id", "clientB", "client-secret", "b"));
MultipleSourcesContainer container = ConfigUtils.processLabeledData(List.of(containerA, containerB),
new MockEnvironment(), Map.of("load", "true"), "default", Set.of(), false);
System.out.println(container);
assertThat(container.names()).containsExactlyInAnyOrder("client-1", "client-2");
Map<String, Object> client1Data = (Map<String, Object>) container.data().get("client-1");
assertThat(client1Data)
.containsExactlyInAnyOrderEntriesOf(Map.of("client-id", "clientA", "client-secret", "a"));
Map<String, Object> client2Data = (Map<String, Object>) container.data().get("client-2");
assertThat(client2Data)
.containsExactlyInAnyOrderEntriesOf(Map.of("client-id", "clientB", "client-secret", "b"));
}
}

View File

@@ -0,0 +1,169 @@
/*
* Copyright 2013-2025 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.commons.config;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
/**
* @author wind57
*/
class SourceDataFlattenerTests {
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* </pre>
*/
@Test
void defaultFlattenedSourceDataNoOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
Map<String, Object> result = SourceDataFlattener.defaultFlattenedSourceData(names, rawData);
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("a", "b", "c", "d"));
}
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* - nameC -> [a, w]
* </pre>
*/
@Test
void defaultFlattenedSourceDataOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
names.add("nameC");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
rawData.put("nameC", Map.of("a", "w"));
Map<String, Object> result = SourceDataFlattener.defaultFlattenedSourceData(names, rawData);
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("a", "w", "c", "d"));
}
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* - prefix -> one
* </pre>
*/
@Test
void prefixFlattenedSourceDataNoOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
Map<String, Object> result = SourceDataFlattener.prefixFlattenedSourceData(names, rawData, "one");
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("one.a", "b", "one.c", "d"));
}
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* - nameC -> [a, w]
* - prefix -> one
* </pre>
*/
@Test
void prefixFlattenedSourceDataOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
names.add("nameC");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
rawData.put("nameC", Map.of("a", "w"));
Map<String, Object> result = SourceDataFlattener.prefixFlattenedSourceData(names, rawData, "one");
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("one.a", "w", "one.c", "d"));
}
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* </pre>
*/
@Test
void nameFlattenedSourceDataNoOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
Map<String, Object> result = SourceDataFlattener.nameFlattenedSourceData(names, rawData);
Assertions.assertThat(result).containsExactlyInAnyOrderEntriesOf(Map.of("nameA.a", "b", "nameB.c", "d"));
}
/**
* <pre>
* - nameA -> [a, b]
* - nameB -> [c, d]
* - nameC -> [a, w]
* </pre>
*/
@Test
void nameFlattenedSourceDataOverlap() {
LinkedHashSet<String> names = new LinkedHashSet<>();
names.add("nameA");
names.add("nameB");
names.add("nameC");
Map<String, Object> rawData = new HashMap<>();
rawData.put("nameA", Map.of("a", "b"));
rawData.put("nameB", Map.of("c", "d"));
rawData.put("nameC", Map.of("a", "w"));
Map<String, Object> result = SourceDataFlattener.nameFlattenedSourceData(names, rawData);
Assertions.assertThat(result)
.containsExactlyInAnyOrderEntriesOf(Map.of("nameA.a", "b", "nameB.c", "d", "nameC.a", "w"));
}
}

View File

@@ -81,7 +81,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.secretsDataByLabels(client, "spring-k8s",
Map.of("color", "pink"), new MockEnvironment(), Set.of());
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("my-secret");
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-secret");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
}
// secret "my-secret" is deployed with label {color:pink}; we search for it by same
@@ -100,7 +103,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.secretsDataByLabels(client, "spring-k8s",
Map.of("color", "pink"), new MockEnvironment(), Set.of());
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("my-secret");
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("key1", "value1"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-secret");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("key1", "value1"));
}
// secrets "my-secret" and "my-secret-2" are deployed with label {color:pink};
@@ -129,8 +135,13 @@ class Fabric8ConfigUtilsTests {
Assertions.assertThat(result.names()).contains("my-secret");
Assertions.assertThat(result.names()).contains("my-secret-2");
Assertions.assertThat(result.data())
.containsExactlyInAnyOrderEntriesOf(Map.of("property-2", "value-2", "property", "value"));
@SuppressWarnings("unchecked")
Map<String, Object> mySecretData = (Map<String, Object>) result.data().get("my-secret");
Assertions.assertThat(mySecretData).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
@SuppressWarnings("unchecked")
Map<String, Object> mySecret2Data = (Map<String, Object>) result.data().get("my-secret-2");
Assertions.assertThat(mySecret2Data).containsExactlyInAnyOrderEntriesOf(Map.of("property-2", "value-2"));
}
/**
@@ -195,8 +206,18 @@ class Fabric8ConfigUtilsTests {
Assertions.assertThat(result.names()).contains("blue-square-secret");
Assertions.assertThat(result.names()).contains("blue-square-secret-k8s");
Assertions.assertThat(result.data())
.containsExactlyInAnyOrderEntriesOf(Map.of("one", "1", "two", "2", "four", "4"));
@SuppressWarnings("unchecked")
Map<String, Object> dataBlueSecret = (Map<String, Object>) result.data().get("blue-circle-secret");
Assertions.assertThat(dataBlueSecret).containsExactlyInAnyOrderEntriesOf(Map.of("one", "1"));
@SuppressWarnings("unchecked")
Map<String, Object> dataSquareSecret = (Map<String, Object>) result.data().get("blue-square-secret");
Assertions.assertThat(dataSquareSecret).containsExactlyInAnyOrderEntriesOf(Map.of("two", "2"));
@SuppressWarnings("unchecked")
Map<String, Object> dataSquareSecretK8s = (Map<String, Object>) result.data().get("blue-square-secret-k8s");
Assertions.assertThat(dataSquareSecretK8s).containsExactlyInAnyOrderEntriesOf(Map.of("four", "4"));
}
// secret "my-secret" is deployed; we search for it by name and do not find it.
@@ -229,7 +250,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.secretsDataByName(client, "spring-k8s", names,
new MockEnvironment());
Assertions.assertThat(result.names().size()).isEqualTo(1);
Assertions.assertThat(result.data().get("property")).isEqualTo("value");
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-secret");
Assertions.assertThat(data.get("property")).isEqualTo("value");
}
// secrets "my-secret" and "my-secret-2" are deployed;
@@ -259,8 +283,14 @@ class Fabric8ConfigUtilsTests {
Assertions.assertThat(result.names()).contains("my-secret-2");
Assertions.assertThat(result.data().size()).isEqualTo(2);
Assertions.assertThat(result.data().get("property")).isEqualTo("value");
Assertions.assertThat(result.data().get("property-2")).isEqualTo("value-2");
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-secret");
Assertions.assertThat(data.get("property")).isEqualTo("value");
@SuppressWarnings("unchecked")
Map<String, Object> data2 = (Map<String, Object>) result.data().get("my-secret-2");
Assertions.assertThat(data2.get("property-2")).isEqualTo("value-2");
}
// config-map "my-config-map" is deployed without any data; we search for it by name
@@ -278,7 +308,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.configMapsDataByName(client, "spring-k8s", names,
new MockEnvironment());
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("my-config-map");
Assertions.assertThat(result.data()).isEmpty();
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-config-map");
Assertions.assertThat(data).isEmpty();
}
// config-map "my-config-map" is deployed; we search for it and do not find it.
@@ -313,7 +346,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.configMapsDataByName(client, "spring-k8s", names,
new MockEnvironment());
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("my-config-map");
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-config-map");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
}
// config-map "my-config-map" is deployed; we search for it and find it.
@@ -333,7 +369,10 @@ class Fabric8ConfigUtilsTests {
MultipleSourcesContainer result = Fabric8ConfigUtils.configMapsDataByName(client, "spring-k8s", names,
new MockEnvironment());
Assertions.assertThat(result.names()).containsExactlyInAnyOrder("my-config-map");
Assertions.assertThat(result.data()).containsExactlyInAnyOrderEntriesOf(Map.of("key1", "value1"));
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-config-map");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("key1", "value1"));
}
// config-map "my-config-map" and "my-config-map-2" are deployed;
@@ -364,8 +403,14 @@ class Fabric8ConfigUtilsTests {
Assertions.assertThat(result.names()).contains("my-config-map-2");
Assertions.assertThat(result.data().size()).isEqualTo(2);
Assertions.assertThat(result.data().get("property")).isEqualTo("value");
Assertions.assertThat(result.data().get("property-2")).isEqualTo("value-2");
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) result.data().get("my-config-map");
Assertions.assertThat(data).containsExactlyInAnyOrderEntriesOf(Map.of("property", "value"));
@SuppressWarnings("unchecked")
Map<String, Object> data2 = (Map<String, Object>) result.data().get("my-config-map-2");
Assertions.assertThat(data2).containsExactlyInAnyOrderEntriesOf(Map.of("property-2", "value-2"));
}
@Test

View File

@@ -40,6 +40,8 @@ import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
import org.springframework.cloud.kubernetes.commons.config.SourceData;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
*/
@@ -292,10 +294,10 @@ class LabeledConfigMapContextToSourceDataProviderTests {
String secondKey = keys.next();
if (firstKey.contains("first")) {
Assertions.assertThat(firstKey).isEqualTo("another-blue-configmap.blue-configmap.first");
Assertions.assertThat(firstKey).isEqualTo("blue-configmap.first");
}
Assertions.assertThat(secondKey).isEqualTo("another-blue-configmap.blue-configmap.second");
Assertions.assertThat(secondKey).isEqualTo("another-blue-configmap.second");
Assertions.assertThat(properties.get(firstKey)).isEqualTo("blue");
Assertions.assertThat(properties.get(secondKey)).isEqualTo("blue");
}
@@ -410,11 +412,10 @@ class LabeledConfigMapContextToSourceDataProviderTests {
Fabric8ContextToSourceData data = new LabeledConfigMapContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(2);
Assertions.assertThat(sourceData.sourceData().get("color-configmap.color-configmap-k8s.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-configmap.color-configmap-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceName())
.isEqualTo("configmap.color-configmap.color-configmap-k8s.default");
assertThat(sourceData.sourceData().size()).isEqualTo(2);
assertThat(sourceData.sourceData().get("color-configmap.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("color-configmap-k8s.two")).isEqualTo("2");
assertThat(sourceData.sourceName()).isEqualTo("configmap.color-configmap.color-configmap-k8s.default");
}
@@ -480,25 +481,14 @@ class LabeledConfigMapContextToSourceDataProviderTests {
Fabric8ContextToSourceData data = new LabeledConfigMapContextToSourceDataProvider().get();
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(4);
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.one"))
.isEqualTo("1");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.two"))
.isEqualTo("2");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.four"))
.isEqualTo("4");
Assertions
.assertThat(sourceData.sourceData()
.get("color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.five"))
.isEqualTo("5");
assertThat(sourceData.sourceData().size()).isEqualTo(4);
Assertions.assertThat(sourceData.sourceName())
assertThat(sourceData.sourceData().get("color-configmap.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("shape-configmap.two")).isEqualTo("2");
assertThat(sourceData.sourceData().get("color-configmap-k8s.four")).isEqualTo("4");
assertThat(sourceData.sourceData().get("shape-configmap-k8s.five")).isEqualTo("5");
assertThat(sourceData.sourceName())
.isEqualTo("configmap.color-configmap.color-configmap-k8s.shape-configmap.shape-configmap-k8s.default");
}

View File

@@ -41,6 +41,8 @@ import org.springframework.cloud.kubernetes.commons.config.NormalizedSource;
import org.springframework.cloud.kubernetes.commons.config.SourceData;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests only for the happy-path scenarios. All others are tested elsewhere.
*
@@ -294,10 +296,10 @@ class LabeledSecretContextToSourceDataProviderTests {
String secondKey = keys.next();
if (firstKey.contains("first")) {
Assertions.assertThat(firstKey).isEqualTo("another-blue-secret.blue-secret.first");
Assertions.assertThat(firstKey).isEqualTo("blue-secret.first");
}
Assertions.assertThat(secondKey).isEqualTo("another-blue-secret.blue-secret.second");
Assertions.assertThat(secondKey).isEqualTo("another-blue-secret.second");
Assertions.assertThat(properties.get(firstKey)).isEqualTo("blue");
Assertions.assertThat(properties.get(secondKey)).isEqualTo("blue");
}
@@ -413,8 +415,8 @@ class LabeledSecretContextToSourceDataProviderTests {
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(2);
Assertions.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceData().get("color-secret.one")).isEqualTo("1");
Assertions.assertThat(sourceData.sourceData().get("color-secret-k8s.two")).isEqualTo("2");
Assertions.assertThat(sourceData.sourceName()).isEqualTo("secret.color-secret.color-secret-k8s.default");
}
@@ -482,20 +484,12 @@ class LabeledSecretContextToSourceDataProviderTests {
SourceData sourceData = data.apply(context);
Assertions.assertThat(sourceData.sourceData().size()).isEqualTo(4);
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.one"))
.isEqualTo("1");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.two"))
.isEqualTo("2");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.four"))
.isEqualTo("4");
Assertions
.assertThat(sourceData.sourceData().get("color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.five"))
.isEqualTo("5");
assertThat(sourceData.sourceData().get("color-secret.one")).isEqualTo("1");
assertThat(sourceData.sourceData().get("shape-secret.two")).isEqualTo("2");
assertThat(sourceData.sourceData().get("color-secret-k8s.four")).isEqualTo("4");
assertThat(sourceData.sourceData().get("shape-secret-k8s.five")).isEqualTo("5");
Assertions.assertThat(sourceData.sourceName())
assertThat(sourceData.sourceName())
.isEqualTo("secret.color-secret.color-secret-k8s.shape-secret.shape-secret-k8s.default");
}

View File

@@ -22,13 +22,19 @@ import java.util.Map;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
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.boot.test.context.SpringBootTest;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenPurpleK8s;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
@@ -42,7 +48,22 @@ abstract class LabeledConfigMapWithProfile {
private static KubernetesClient mockClient;
@Autowired
private WebTestClient webClient;
private Blue blue;
@Autowired
private Green green;
@Autowired
private GreenK8s greenK8s;
@Autowired
private GreenProd greenProd;
@Autowired
private GreenPurple greenPurple;
@Autowired
private GreenPurpleK8s greenPurpleK8s;
/**
* <pre>
@@ -129,32 +150,50 @@ abstract class LabeledConfigMapWithProfile {
*/
@Test
void testBlue() {
this.webClient.get()
.uri("/labeled-configmap/profile/blue")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("1"));
assertThat(blue.getOne()).isEqualTo("1");
}
/**
* <pre>
* this one is taken from : "green-configmap.green-configmap-k8s.green-configmap-prod.green-purple-configmap.green-purple-configmap-k8s".
* We find "green-configmap" by labels, also "green-configmap-k8s" and "green-configmap-prod" exists,
* because "includeProfileSpecificSources=true" is set. Also "green-purple-configmap" and "green-purple-configmap-k8s"
* are found.
* </pre>
* found by labels.
*/
@Test
void testGreen() {
this.webClient.get()
.uri("/labeled-configmap/profile/green")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("2#6#7#eight-ish"));
assertThat(green.getTwo()).isEqualTo("2");
}
/**
* we find "green-configmap" by labels, and since 'k8s' is an active profile, this one
* is taken also (includeProfileSpecificSources=true)
*/
@Test
void testGreenK8s() {
assertThat(greenK8s.getSix()).isEqualTo("6");
}
/**
* we find "green-configmap" by labels, and since 'prod' is an active profile, this
* one is taken also (includeProfileSpecificSources=true)
*/
@Test
void testGreenProd() {
assertThat(greenProd.getSeven()).isEqualTo("7");
}
/**
* found by labels.
*/
@Test
void testGreenPurple() {
assertThat(greenPurple.getEight()).isEqualTo("8");
}
/**
* we find "green-configmap" by labels, and since 'prod' is an active profile, this
* one is taken also (includeProfileSpecificSources=true)
*/
@Test
void testGreenPurpleK8s() {
assertThat(greenPurpleK8s.getEight()).isEqualTo("eight-ish");
}
}

View File

@@ -21,9 +21,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenProd;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.GreenPurpleK8s;
@SpringBootApplication
@EnableConfigurationProperties({ Blue.class, Green.class })
@EnableConfigurationProperties({ Blue.class, Green.class, GreenK8s.class, GreenProd.class, GreenPurple.class,
GreenPurpleK8s.class })
public class LabeledConfigMapWithProfileApp {
public static void main(String[] args) {

View File

@@ -1,46 +0,0 @@
/*
* 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_config_map_with_profile.controller;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_with_profile.properties.Green;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LabeledConfigMapWithProfileController {
private final Blue blue;
private final Green green;
public LabeledConfigMapWithProfileController(Blue blue, Green green) {
this.blue = blue;
this.green = green;
}
@GetMapping("/labeled-configmap/profile/blue")
public String blue() {
return blue.getOne();
}
@GetMapping("/labeled-configmap/profile/green")
public String green() {
return green.getTwo() + "#" + green.getSix() + "#" + green.getSeven() + "#" + green.getEight();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* Copyright 2013-2025 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.
@@ -18,17 +18,11 @@ package org.springframework.cloud.kubernetes.fabric8.config.labeled_config_map_w
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap.green-configmap-k8s.green-configmap-prod.green-purple-configmap.green-purple-configmap-k8s")
@ConfigurationProperties("green-configmap")
public class Green {
private String two;
private String six;
private String seven;
private String eight;
public String getTwo() {
return two;
}
@@ -37,28 +31,4 @@ public class Green {
this.two = two;
}
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap-k8s")
public class GreenK8s {
private String six;
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-configmap-prod")
public class GreenProd {
private String seven;
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-configmap")
public class GreenPurple {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_config_map_with_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-configmap-k8s")
public class GreenPurpleK8s {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -24,13 +24,19 @@ 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.boot.test.context.SpringBootTest;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenPurpleK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenSecretK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenSecretProd;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author wind57
@@ -43,7 +49,22 @@ abstract class LabeledSecretWithProfile {
private static KubernetesClient mockClient;
@Autowired
private WebTestClient webClient;
private Blue blue;
@Autowired
private Green green;
@Autowired
private GreenSecretK8s greenSecretK8s;
@Autowired
private GreenSecretProd greenSecretProd;
@Autowired
private GreenPurple greenPurple;
@Autowired
private GreenPurpleK8s greenPurpleK8s;
/**
* <pre>
@@ -55,8 +76,8 @@ abstract class LabeledSecretWithProfile {
* - secret with name "green-secret-k8s", with labels : "{color: green-k8s}"
* - secret with name "green-secret-prod", with labels : "{color: green-prod}"
*
* # a test that proves order: first read non-profile based secrets, thus profile based
* # secrets override non-profile ones.
* a test that proves order: first read non-profile based secrets, thus profile based
* secrets override non-profile ones.
* - secret with name "green-purple-secret", labels "{color: green, shape: round}", data: "{eight: 8}"
* - secret with name "green-purple-secret-k8s", labels "{color: black}", data: "{eight: eight-ish}"
* </pre>
@@ -139,32 +160,60 @@ abstract class LabeledSecretWithProfile {
*/
@Test
void testBlue() {
this.webClient.get()
.uri("/labeled-secret/profile/blue")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("1"));
assertThat(blue.getOne()).isEqualTo("1");
}
/**
* <pre>
* this one is taken from : "green-purple-secret.green-purple-secret-k8s.green-secret.green-secret-k8s.green-secret-prod".
* We find "green-secret" by labels, also "green-secrets-k8s" and "green-secrets-prod" exists,
* because "includeProfileSpecificSources=true" is set. Also "green-purple-secret" and "green-purple-secret-k8s"
* are found.
* We find "green-secret" by labels.
* </pre>
*/
@Test
void testGreen() {
this.webClient.get()
.uri("/labeled-secret/profile/green")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.value(Matchers.equalTo("2#6#7#eight-ish"));
assertThat(green.getTwo()).isEqualTo("2");
}
/**
* <pre>
* We find "green-secret" by labels, but also "green-secrets-k8s" and because
* "includeProfileSpecificSources=true", we take it also.
* </pre>
*/
@Test
void testGreenK8s() {
assertThat(greenSecretK8s.getSix()).isEqualTo("6");
}
/**
* <pre>
* We find "green-secret" by labels, but also "green-secrets-prod" and because
* "includeProfileSpecificSources=true", we take it also.
* </pre>
*/
@Test
void testGreenProd() {
assertThat(greenSecretProd.getSeven()).isEqualTo("7");
}
/**
* <pre>
* found by labels.
* </pre>
*/
@Test
void testGreenPurple() {
assertThat(greenPurple.getEight()).isEqualTo("8");
}
/**
* <pre>
* We find "green-purple" by labels, and since 'k8s' is an active profile,
* we will also find this one.
* </pre>
*/
@Test
void testGreenPurpleK8s() {
assertThat(greenPurpleK8s.getEight()).isEqualTo("eight-ish");
}
}

View File

@@ -21,9 +21,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Green;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenPurple;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenPurpleK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenSecretK8s;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.GreenSecretProd;
@SpringBootApplication
@EnableConfigurationProperties({ Blue.class, Green.class })
@EnableConfigurationProperties({ Blue.class, Green.class, GreenSecretK8s.class, GreenSecretProd.class,
GreenPurple.class, GreenPurpleK8s.class })
public class LabeledSecretWithProfileApp {
public static void main(String[] args) {

View File

@@ -1,46 +0,0 @@
/*
* 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_profile.controller;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Blue;
import org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_profile.properties.Green;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LabeledSecretWithProfileController {
private final Blue blue;
private final Green green;
public LabeledSecretWithProfileController(Blue blue, Green green) {
this.blue = blue;
this.green = green;
}
@GetMapping("/labeled-secret/profile/blue")
public String blue() {
return blue.getOne();
}
@GetMapping("/labeled-secret/profile/green")
public String green() {
return green.getTwo() + "#" + green.getSix() + "#" + green.getSeven() + "#" + green.getEight();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2021 the original author or authors.
* Copyright 2013-2025 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.
@@ -18,17 +18,11 @@ package org.springframework.cloud.kubernetes.fabric8.config.labeled_secret_with_
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret.green-purple-secret-k8s.green-secret.green-secret-k8s.green-secret-prod")
@ConfigurationProperties("green-secret")
public class Green {
private String two;
private String six;
private String seven;
private String eight;
public String getTwo() {
return two;
}
@@ -37,28 +31,4 @@ public class Green {
this.two = two;
}
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret")
public class GreenPurple {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-purple-secret-k8s")
public class GreenPurpleK8s {
private String eight;
public String getEight() {
return eight;
}
public void setEight(String eight) {
this.eight = eight;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-secret-k8s")
public class GreenSecretK8s {
private String six;
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2013-2025 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_profile.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("green-secret-prod")
public class GreenSecretProd {
private String seven;
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
}

View File

@@ -53,12 +53,12 @@ import io.kubernetes.client.util.Yaml;
import jakarta.annotation.Nullable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.assertj.core.api.Assertions;
import org.testcontainers.k3s.K3sContainer;
import org.springframework.cloud.kubernetes.integration.tests.commons.Images;
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
import static org.assertj.core.api.Fail.fail;
import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.loadImage;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.pomVersion;
@@ -548,7 +548,7 @@ public final class Util {
V1DeploymentList deployments = appsV1Api.listNamespacedDeployment(namespace, null, null, null,
"metadata.name=" + deploymentName, null, null, null, null, null, null, null);
if (deployments.getItems().isEmpty()) {
fail("No deployments with the name " + deploymentName);
Assertions.fail("No deployments with the name " + deploymentName);
}
V1Deployment deployment = deployments.getItems().get(0);
if (deployment.getStatus() != null) {
@@ -580,7 +580,7 @@ public final class Util {
V1DeploymentList deployments = new AppsV1Api().listNamespacedDeployment(namespace, null, null, null,
"metadata.name=" + deploymentName, null, null, null, null, null, null, null);
if (deployments.getItems().isEmpty()) {
fail("No deployment with name " + deploymentName);
Assertions.fail("No deployment with name " + deploymentName);
}
V1Deployment deployment = deployments.getItems().get(0);