Skip to content

Commit dd4678c

Browse files
committed
Merge branch 'main' into drop_old_leader_election_implementation
2 parents c6fcbc3 + 3ac1d4e commit dd4678c

File tree

9 files changed

+140
-114
lines changed

9 files changed

+140
-114
lines changed

docs/modules/ROOT/pages/property-source-config.adoc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ an `application-profile.properties` or `application-profile.yaml` file that cont
77
application or Spring Boot starters. You can override these properties by specifying system properties or environment
88
variables.
99

10-
To enable this functionality you need to set the `spring.config.import` application configuration property to `kubernetes:` (escape with quotes when using yaml eg. `"kubernetes:"`).
11-
Currently you can not specify a ConfigMap or Secret to load using `spring.config.import`, by default Spring Cloud Kubernetes
12-
will load a ConfigMap and/or Secret based on the `spring.application.name` property. If `spring.application.name` is not set it will
13-
load a ConfigMap and/or Secret with the name `application`.
10+
To enable this functionality you need to set the `spring.config.import` application configuration property to `kubernetes:` (escape with quotes when using yaml eg. `"kubernetes:"`):
11+
12+
[source]
13+
----
14+
spring:
15+
config:
16+
import: "kubernetes:"
17+
----
1418

1519
If you would like to load Kubernetes ``PropertySource``s during the bootstrap phase like it worked prior to the 3.0.x release
1620
you can either add `spring-cloud-starter-bootstrap` to your application's classpath or set `spring.cloud.bootstrap.enabled=true`

docs/modules/ROOT/pages/property-source-config/configmap-propertysource.adoc

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,6 @@ spring:
542542

543543
NOTE: Since version `5.0.0`, `includeProfileSpecificSources` is only supported for named sources (`spring.cloud.kubernetes.sources.name=XXX`); support for labeled sources has been removed.
544544

545-
546545
Notice that just like before, there are two levels where you can specify this property: for all config maps or
547546
for individual ones; the latter having a higher priority.
548547

@@ -566,7 +565,24 @@ and want to enable fail-fast, but do not want retry to be enabled; you can disab
566565
by setting `spring.cloud.kubernetes.config.retry.enabled=false`.
567566

568567

569-
NOTE: Since version `5.0.0`, we have introduced the possibility to read sources individually. Until now, we would go to the namespace and read all the configmaps / secrets available and then filter out the ones requested. Since `5.0.0-M3` you can specify that you want to read them individually, by setting the property: `spring.cloud.kubernetes.config.read-type=SINGLE`. The previous option to read them all in a namespace is controlled by `spring.cloud.kubernetes.config.read-type=BATCH` and it is the default option.
568+
NOTE: As of 5.0.0-M3, Spring Cloud Kubernetes introduces two modes for retrieving configuration:
569+
570+
- BATCH (`spring.cloud.kubernetes.config.read-type=BATCH`) which is the Default mode: The framework retrieves all ConfigMaps and Secrets within a namespace before filtering. This requires broader RBAC permissions (Namespace-wide `List`).
571+
572+
- SINGLE (`spring.cloud.kubernetes.config.read-type=SINGLE`): Resources are fetched individually by name. This reduces API overhead and allows for high-security, fine-grained RBAC.
573+
574+
This enables you to restrict the service account to only see its own configuration:
575+
576+
[source]
577+
----
578+
- apiGroups: [""]
579+
resources: ["configmaps"]
580+
verbs: ["get", "watch"] # 'list' is often no longer required at the namespace level
581+
resourceNames: ["<my_app_name>"]
582+
----
583+
584+
RBAC rules using `resourceNames` are only compatible with `SINGLE` mode.
585+
570586

571587
.Properties:
572588
[options="header,footer"]

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@
1717
package org.springframework.cloud.kubernetes.client.config;
1818

1919
import java.util.List;
20+
import java.util.Map;
2021
import java.util.concurrent.ConcurrentHashMap;
22+
import java.util.stream.Collectors;
2123

2224
import io.kubernetes.client.openapi.ApiException;
2325
import io.kubernetes.client.openapi.apis.CoreV1Api;
26+
import io.kubernetes.client.openapi.models.V1ConfigMap;
27+
import io.kubernetes.client.openapi.models.V1Secret;
28+
import org.apache.commons.logging.LogFactory;
2429

2530
import org.springframework.cloud.kubernetes.commons.config.StrippedSourceContainer;
31+
import org.springframework.core.log.LogAccessor;
2632

2733
import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.stripConfigMaps;
2834
import static org.springframework.cloud.kubernetes.client.config.KubernetesClientConfigUtils.stripSecrets;
@@ -35,6 +41,8 @@
3541
*/
3642
public final class KubernetesClientSourcesBatchRead {
3743

44+
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(KubernetesClientSourcesBatchRead.class));
45+
3846
private KubernetesClientSourcesBatchRead() {
3947

4048
}
@@ -77,4 +85,61 @@ static List<StrippedSourceContainer> strippedSecrets(CoreV1Api coreV1Api, String
7785
});
7886
}
7987

88+
/**
89+
* read secrets by labels, without caching them.
90+
*/
91+
static List<StrippedSourceContainer> strippedSecrets(CoreV1Api client, String namespace,
92+
Map<String, String> labels) {
93+
94+
List<V1Secret> secrets;
95+
try {
96+
secrets = client.listNamespacedSecret(namespace).labelSelector(labelSelector(labels)).execute().getItems();
97+
}
98+
catch (ApiException e) {
99+
throw new RuntimeException(e.getResponseBody(), e);
100+
}
101+
for (V1Secret secret : secrets) {
102+
LOG.debug(() -> "Loaded secret '" + secret.getMetadata().getName() + "'");
103+
}
104+
105+
List<StrippedSourceContainer> strippedSecrets = stripSecrets(secrets);
106+
if (strippedSecrets.isEmpty()) {
107+
LOG.debug(() -> "No secrets in namespace '" + namespace + "'");
108+
}
109+
110+
return strippedSecrets;
111+
}
112+
113+
/**
114+
* read configmaps by labels, without caching them.
115+
*/
116+
static List<StrippedSourceContainer> strippedConfigMaps(CoreV1Api client, String namespace,
117+
Map<String, String> labels) {
118+
119+
List<V1ConfigMap> configMaps;
120+
try {
121+
configMaps = client.listNamespacedConfigMap(namespace)
122+
.labelSelector(labelSelector(labels))
123+
.execute()
124+
.getItems();
125+
}
126+
catch (ApiException e) {
127+
throw new RuntimeException(e.getResponseBody(), e);
128+
}
129+
for (V1ConfigMap configMap : configMaps) {
130+
LOG.debug(() -> "Loaded config map '" + configMap.getMetadata().getName() + "'");
131+
}
132+
133+
List<StrippedSourceContainer> strippedConfigMaps = stripConfigMaps(configMaps);
134+
if (strippedConfigMaps.isEmpty()) {
135+
LOG.debug(() -> "No configmaps in namespace '" + namespace + "'");
136+
}
137+
138+
return strippedConfigMaps;
139+
}
140+
141+
private static String labelSelector(Map<String, String> labels) {
142+
return labels.entrySet().stream().map(en -> en.getKey() + "=" + en.getValue()).collect(Collectors.joining("&"));
143+
}
144+
80145
}

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

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
import java.util.ArrayList;
2020
import java.util.LinkedHashSet;
2121
import java.util.List;
22-
import java.util.Map;
23-
import java.util.stream.Collectors;
2422

2523
import io.kubernetes.client.openapi.ApiException;
2624
import io.kubernetes.client.openapi.apis.CoreV1Api;
@@ -105,61 +103,4 @@ static List<StrippedSourceContainer> strippedSecrets(CoreV1Api client, String na
105103
return strippedSecrets;
106104
}
107105

108-
/**
109-
* read configmaps by labels, without caching them.
110-
*/
111-
static List<StrippedSourceContainer> strippedConfigMaps(CoreV1Api client, String namespace,
112-
Map<String, String> labels) {
113-
114-
List<V1ConfigMap> configMaps;
115-
try {
116-
configMaps = client.listNamespacedConfigMap(namespace)
117-
.labelSelector(labelSelector(labels))
118-
.execute()
119-
.getItems();
120-
}
121-
catch (ApiException e) {
122-
throw new RuntimeException(e.getResponseBody(), e);
123-
}
124-
for (V1ConfigMap configMap : configMaps) {
125-
LOG.debug(() -> "Loaded config map '" + configMap.getMetadata().getName() + "'");
126-
}
127-
128-
List<StrippedSourceContainer> strippedConfigMaps = stripConfigMaps(configMaps);
129-
if (strippedConfigMaps.isEmpty()) {
130-
LOG.debug(() -> "No configmaps in namespace '" + namespace + "'");
131-
}
132-
133-
return strippedConfigMaps;
134-
}
135-
136-
/**
137-
* read secrets by labels, without caching them.
138-
*/
139-
static List<StrippedSourceContainer> strippedSecrets(CoreV1Api client, String namespace,
140-
Map<String, String> labels) {
141-
142-
List<V1Secret> secrets;
143-
try {
144-
secrets = client.listNamespacedSecret(namespace).labelSelector(labelSelector(labels)).execute().getItems();
145-
}
146-
catch (ApiException e) {
147-
throw new RuntimeException(e.getResponseBody(), e);
148-
}
149-
for (V1Secret secret : secrets) {
150-
LOG.debug(() -> "Loaded secret '" + secret.getMetadata().getName() + "'");
151-
}
152-
153-
List<StrippedSourceContainer> strippedSecrets = stripSecrets(secrets);
154-
if (strippedSecrets.isEmpty()) {
155-
LOG.debug(() -> "No secrets in namespace '" + namespace + "'");
156-
}
157-
158-
return strippedSecrets;
159-
}
160-
161-
private static String labelSelector(Map<String, String> labels) {
162-
return labels.entrySet().stream().map(en -> en.getKey() + "=" + en.getValue()).collect(Collectors.joining("&"));
163-
}
164-
165106
}

spring-cloud-kubernetes-controllers/pom.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@
4242
<groupId>org.springframework.boot</groupId>
4343
<artifactId>spring-boot-maven-plugin</artifactId>
4444
<configuration>
45-
<buildpacks>
46-
<buildpack>docker://paketobuildpacks/java:latest</buildpack>
47-
</buildpacks>
4845
<image>
4946
<env>
5047
<BP_SPRING_CLOUD_BINDINGS_DISABLED>true</BP_SPRING_CLOUD_BINDINGS_DISABLED>

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@
1717
package org.springframework.cloud.kubernetes.fabric8.config;
1818

1919
import java.util.List;
20+
import java.util.Map;
2021
import java.util.concurrent.ConcurrentHashMap;
2122

23+
import io.fabric8.kubernetes.api.model.ConfigMap;
24+
import io.fabric8.kubernetes.api.model.Secret;
2225
import io.fabric8.kubernetes.client.KubernetesClient;
26+
import org.apache.commons.logging.LogFactory;
2327

2428
import org.springframework.cloud.kubernetes.commons.config.StrippedSourceContainer;
29+
import org.springframework.core.log.LogAccessor;
2530

2631
import static org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigUtils.stripConfigMaps;
2732
import static org.springframework.cloud.kubernetes.fabric8.config.Fabric8ConfigUtils.stripSecrets;
@@ -34,6 +39,8 @@
3439
*/
3540
final class Fabric8SourcesBatchRead {
3641

42+
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(Fabric8SourcesBatchRead.class));
43+
3744
private Fabric8SourcesBatchRead() {
3845

3946
}
@@ -64,4 +71,42 @@ static List<StrippedSourceContainer> strippedSecrets(KubernetesClient client, St
6471
x -> stripSecrets(client.secrets().inNamespace(namespace).list().getItems()));
6572
}
6673

74+
/**
75+
* read configmaps by labels, without caching them.
76+
*/
77+
static List<StrippedSourceContainer> strippedConfigMaps(KubernetesClient client, String namespace,
78+
Map<String, String> labels) {
79+
80+
List<ConfigMap> configMaps = client.configMaps().inNamespace(namespace).withLabels(labels).list().getItems();
81+
for (ConfigMap configMap : configMaps) {
82+
LOG.debug(() -> "Loaded config map '" + configMap.getMetadata().getName() + "'");
83+
}
84+
85+
List<StrippedSourceContainer> strippedConfigMaps = stripConfigMaps(configMaps);
86+
if (strippedConfigMaps.isEmpty()) {
87+
LOG.debug(() -> "No configmaps in namespace '" + namespace + "'");
88+
}
89+
90+
return strippedConfigMaps;
91+
}
92+
93+
/**
94+
* read secrets by labels, without caching them.
95+
*/
96+
static List<StrippedSourceContainer> strippedSecrets(KubernetesClient client, String namespace,
97+
Map<String, String> labels) {
98+
99+
List<Secret> secrets = client.secrets().inNamespace(namespace).withLabels(labels).list().getItems();
100+
for (Secret secret : secrets) {
101+
LOG.debug(() -> "Loaded secret '" + secret.getMetadata().getName() + "'");
102+
}
103+
104+
List<StrippedSourceContainer> strippedSecrets = stripSecrets(secrets);
105+
if (strippedSecrets.isEmpty()) {
106+
LOG.debug(() -> "No secrets in namespace '" + namespace + "'");
107+
}
108+
109+
return strippedSecrets;
110+
}
111+
67112
}

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

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.ArrayList;
2020
import java.util.LinkedHashSet;
2121
import java.util.List;
22-
import java.util.Map;
2322

2423
import io.fabric8.kubernetes.api.model.ConfigMap;
2524
import io.fabric8.kubernetes.api.model.Secret;
@@ -95,42 +94,4 @@ static List<StrippedSourceContainer> strippedSecrets(KubernetesClient client, St
9594
return strippedSecrets;
9695
}
9796

98-
/**
99-
* read configmaps by labels, without caching them.
100-
*/
101-
static List<StrippedSourceContainer> strippedConfigMaps(KubernetesClient client, String namespace,
102-
Map<String, String> labels) {
103-
104-
List<ConfigMap> configMaps = client.configMaps().inNamespace(namespace).withLabels(labels).list().getItems();
105-
for (ConfigMap configMap : configMaps) {
106-
LOG.debug(() -> "Loaded config map '" + configMap.getMetadata().getName() + "'");
107-
}
108-
109-
List<StrippedSourceContainer> strippedConfigMaps = stripConfigMaps(configMaps);
110-
if (strippedConfigMaps.isEmpty()) {
111-
LOG.debug(() -> "No configmaps in namespace '" + namespace + "'");
112-
}
113-
114-
return strippedConfigMaps;
115-
}
116-
117-
/**
118-
* read secrets by labels, without caching them.
119-
*/
120-
static List<StrippedSourceContainer> strippedSecrets(KubernetesClient client, String namespace,
121-
Map<String, String> labels) {
122-
123-
List<Secret> secrets = client.secrets().inNamespace(namespace).withLabels(labels).list().getItems();
124-
for (Secret secret : secrets) {
125-
LOG.debug(() -> "Loaded secret '" + secret.getMetadata().getName() + "'");
126-
}
127-
128-
List<StrippedSourceContainer> strippedSecrets = stripSecrets(secrets);
129-
if (strippedSecrets.isEmpty()) {
130-
LOG.debug(() -> "No secrets in namespace '" + namespace + "'");
131-
}
132-
133-
return strippedSecrets;
134-
}
135-
13697
}

spring-cloud-kubernetes-integration-tests/pom.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,8 @@
3737
<env>
3838
<BP_SPRING_CLOUD_BINDINGS_DISABLED>true</BP_SPRING_CLOUD_BINDINGS_DISABLED>
3939
</env>
40+
<name>docker.io/springcloud/${project.artifactId}:${project.version}</name>
4041
</image>
41-
<buildpacks>
42-
<buildpack>docker://paketobuildpacks/java:latest</buildpack>
43-
</buildpacks>
44-
<imageName>docker.io/springcloud/${project.artifactId}:${project.version}</imageName>
4542
</configuration>
4643
<executions>
4744
<execution>

spring-cloud-kubernetes-test-support/src/main/resources/current-images.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ busybox:1.37.0
22
istio/istioctl:1.27.3
33
istio/proxyv2:1.27.3
44
istio/pilot:1.27.3
5-
confluentinc/confluent-local:8.1.0
6-
rabbitmq:4.1.4-management
7-
wiremock/wiremock:3.13.1
5+
confluentinc/confluent-local:8.1.1
6+
rabbitmq:4.2.4-management
7+
wiremock/wiremock:3.13.2

0 commit comments

Comments
 (0)