From dfc830d2ee9e33bc3b8f071ab2d6a5d79dc3ef79 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 5 Oct 2025 11:12:05 +0300 Subject: [PATCH 1/3] doc changes Signed-off-by: wind57 --- .../configmap-propertysource.adoc | 24 ------------------- .../secrets-propertysource.adoc | 17 ------------- ...loud-kubernetes-configuration-watcher.adoc | 2 +- docs/modules/ROOT/partials/_configprops.adoc | 8 +++---- 4 files changed, 4 insertions(+), 47 deletions(-) diff --git a/docs/modules/ROOT/pages/property-source-config/configmap-propertysource.adoc b/docs/modules/ROOT/pages/property-source-config/configmap-propertysource.adoc index 4df253f7e8..ffe8451e6b 100644 --- a/docs/modules/ROOT/pages/property-source-config/configmap-propertysource.adoc +++ b/docs/modules/ROOT/pages/property-source-config/configmap-propertysource.adoc @@ -549,29 +549,6 @@ for individual ones; the latter having a higher priority. NOTE: You should check the security configuration section. To access config maps from inside a pod you need to have the correct Kubernetes service accounts, roles and role bindings. -Another option for using `ConfigMap` instances is to mount them into the Pod by running the Spring Cloud Kubernetes application -and having Spring Cloud Kubernetes read them from the file system. - -NOTE: This feature is deprecated and will be removed in a future release (Use `spring.config.import` instead). -This behavior is controlled by the `spring.cloud.kubernetes.config.paths` property. You can use it in -addition to or instead of the mechanism described earlier. -`spring.cloud.kubernetes.config.paths` expects a List of full paths to each property file, because directories are not being recursively parsed. For example: - -[source,yaml] ----- -spring: - cloud: - kubernetes: - config: - paths: - - /tmp/application.properties - - /var/application.yaml ----- - -NOTE: If you use `spring.cloud.kubernetes.config.paths` or `spring.cloud.kubernetes.secrets.path` the automatic reload -functionality will not work. You will need to make a `POST` request to the `/actuator/refresh` endpoint or -restart/redeploy the application. - [#config-map-fail-fast] In some cases, your application may be unable to load some of your `ConfigMaps` using the Kubernetes API. If you want your application to fail the start-up process in such cases, you can set @@ -598,7 +575,6 @@ NOTE: Since version `5.0.0-M3`, we have introduced the possibility to read sourc | `spring.cloud.kubernetes.config.enabled` | `Boolean` | `true` | Enable ConfigMaps `PropertySource` | `spring.cloud.kubernetes.config.name` | `String` | `${spring.application.name}` | Sets the name of `ConfigMap` to look up | `spring.cloud.kubernetes.config.namespace` | `String` | Client namespace | Sets the Kubernetes namespace where to lookup -| `spring.cloud.kubernetes.config.paths` | `List` | `null` | Sets the paths where `ConfigMap` instances are mounted | `spring.cloud.kubernetes.config.enableApi` | `Boolean` | `true` | Enable or disable consuming `ConfigMap` instances through APIs | `spring.cloud.kubernetes.config.fail-fast` | `Boolean` | `false` | Enable or disable failing the application start-up when an error occurred while loading a `ConfigMap` | `spring.cloud.kubernetes.config.retry.enabled` | `Boolean` | `true` | Enable or disable config retry. diff --git a/docs/modules/ROOT/pages/property-source-config/secrets-propertysource.adoc b/docs/modules/ROOT/pages/property-source-config/secrets-propertysource.adoc index 46493a84c6..aa82d61d0b 100644 --- a/docs/modules/ROOT/pages/property-source-config/secrets-propertysource.adoc +++ b/docs/modules/ROOT/pages/property-source-config/secrets-propertysource.adoc @@ -77,20 +77,6 @@ spec: You can select the Secrets to consume in a number of ways: -. By listing the directories where secrets are mapped: -+ -[source,bash] ----- --Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql ----- -+ -If you have all the secrets mapped to a common root, you can set them like: -+ -[source,bash] ----- --Dspring.cloud.kubernetes.secrets.paths=/etc/secrets ----- - . By setting a named secret: + [source,bash] @@ -165,7 +151,6 @@ This setting is supported since `3.0.6` and upwards. | `spring.cloud.kubernetes.secrets.name` | `String` | `${spring.application.name}` | Sets the name of the secret to look up | `spring.cloud.kubernetes.secrets.namespace` | `String` | Client namespace | Sets the Kubernetes namespace where to look up | `spring.cloud.kubernetes.secrets.labels` | `Map` | `null` | Sets the labels used to lookup secrets -| `spring.cloud.kubernetes.secrets.paths` | `List` | `null` | Sets the paths where secrets are mounted (example 1) | `spring.cloud.kubernetes.secrets.enableApi` | `Boolean` | `false` | Enables or disables consuming secrets through APIs (examples 2 and 3) | `spring.cloud.kubernetes.secrets.fail-fast` | `Boolean` | `false` | Enable or disable failing the application start-up when an error occurred while loading a `Secret` | `spring.cloud.kubernetes.secrets.retry.enabled` | `Boolean` | `true` | Enable or disable secrets retry. @@ -179,8 +164,6 @@ Notes: * The `spring.cloud.kubernetes.secrets.labels` property behaves as defined by https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#map-based-binding[Map-based binding]. -* The `spring.cloud.kubernetes.secrets.paths` property behaves as defined by -https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#collection-based-binding[Collection-based binding]. * Access to secrets through the API may be restricted for security reasons. The preferred way is to mount secrets to the Pod. You can find an example of an application that uses secrets (though it has not been updated to use the new `spring-cloud-kubernetes` project) at diff --git a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc index 30b6f17f49..f177f1911f 100644 --- a/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc +++ b/docs/modules/ROOT/pages/spring-cloud-kubernetes-configuration-watcher.adoc @@ -54,7 +54,7 @@ SPRING_CLOUD_KUBERNETES_CONFIG_INFORMER_ENABLED=TRUE This will tell watcher to only monitor sources that have a label: `spring.cloud.kubernetes.config.informer.enabled=true`. -One more important configuration, especially for configmaps and secrets that are mounted as volumes (via `spring.cloud.kubernetes.config.paths`/`spring.cloud.kubernetes.secrets.paths` or using `spring.config.import`) is: +One more important configuration, especially for configmaps and secrets that are mounted as volumes (via `spring.config.import`) is: [source] ---- diff --git a/docs/modules/ROOT/partials/_configprops.adoc b/docs/modules/ROOT/partials/_configprops.adoc index 366d0862df..600c4ab359 100644 --- a/docs/modules/ROOT/partials/_configprops.adoc +++ b/docs/modules/ROOT/partials/_configprops.adoc @@ -53,8 +53,7 @@ |spring.cloud.kubernetes.config.labels | | |spring.cloud.kubernetes.config.name | | |spring.cloud.kubernetes.config.namespace | | -|spring.cloud.kubernetes.config.paths | | -|spring.cloud.kubernetes.config.retry | | +|spring.cloud.kubernetes.config.retry | | |spring.cloud.kubernetes.config.sources | | |spring.cloud.kubernetes.config.use-name-as-prefix | `+++false+++` | |spring.cloud.kubernetes.discovery.all-namespaces | `+++false+++` | if discovery is enabled for all namespaces @@ -108,9 +107,8 @@ |spring.cloud.kubernetes.secrets.labels | | |spring.cloud.kubernetes.secrets.name | | |spring.cloud.kubernetes.secrets.namespace | | -|spring.cloud.kubernetes.secrets.paths | | -|spring.cloud.kubernetes.secrets.retry | | +|spring.cloud.kubernetes.secrets.retry | | |spring.cloud.kubernetes.secrets.sources | | |spring.cloud.kubernetes.secrets.use-name-as-prefix | `+++false+++` | -|=== \ No newline at end of file +|=== From dea54b49eb80903383dae032dfb342ade563bc60 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 5 Oct 2025 11:25:21 +0300 Subject: [PATCH 2/3] started work Signed-off-by: wind57 --- ...ientConfigMapErrorOnReadingSourceTests.java | 16 ++++++++-------- .../config/ConfigMapConfigProperties.java | 2 +- .../config/SecretsConfigProperties.java | 2 +- .../ConfigMapConfigPropertiesBindingTests.java | 6 ------ .../config/ConfigMapConfigPropertiesTests.java | 18 +++++++++--------- .../SecretsConfigPropertiesBindingTests.java | 6 ------ .../config/SecretsConfigPropertiesTests.java | 16 ++++++++-------- 7 files changed, 27 insertions(+), 39 deletions(-) diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java index 3cc072fb5a..383769a920 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java @@ -110,7 +110,7 @@ void namedSingleConfigMapFails(CapturedOutput output) { stubFor(get(path).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); CoreV1Api api = new CoreV1Api(); @@ -142,7 +142,7 @@ void namedTwoConfigMapsOneFails(CapturedOutput output) { .inScenario("started") .willSetStateTo("go-to-next")); - stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(SINGLE_CONFIGMAP_LIST))) + stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(JSON.serialize(SINGLE_CONFIGMAP_LIST))) .inScenario("started") .whenScenarioStateIs("go-to-next") .willSetStateTo("done")); @@ -152,7 +152,7 @@ void namedTwoConfigMapsOneFails(CapturedOutput output) { ConfigMapConfigProperties.Source sourceTwo = new ConfigMapConfigProperties.Source(configMapNameTwo, namespace, Map.of(), null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of(), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -199,7 +199,7 @@ void namedTwoConfigMapsBothFail(CapturedOutput output) { ConfigMapConfigProperties.Source sourceTwo = new ConfigMapConfigProperties.Source(configMapNameTwo, namespace, Map.of(), null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of(), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -243,7 +243,7 @@ void labeledSingleConfigMapFails(CapturedOutput output) { ConfigMapConfigProperties.Source configMapSource = new ConfigMapConfigProperties.Source(null, namespace, labels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(configMapSource), labels, true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -285,7 +285,7 @@ void labeledTwoConfigMapsOneFails(CapturedOutput output) { .willSetStateTo("second")); // one that passes - stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(DOUBLE_CONFIGMAP_LIST))) + stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(JSON.serialize(DOUBLE_CONFIGMAP_LIST))) .inScenario("started") .whenScenarioStateIs("second") .willSetStateTo("done")); @@ -295,7 +295,7 @@ void labeledTwoConfigMapsOneFails(CapturedOutput output) { ConfigMapConfigProperties.Source sourceTwo = new ConfigMapConfigProperties.Source(null, namespace, configMapTwoLabels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of("one", "1", "two", "2"), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -349,7 +349,7 @@ void labeledTwoConfigMapsBothFail(CapturedOutput output) { ConfigMapConfigProperties.Source sourceTwo = new ConfigMapConfigProperties.Source(null, namespace, configMapTwoLabels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of("one", "1", "two", "2"), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java index e082ad0c63..11c5cfd539 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java @@ -35,7 +35,7 @@ * @author Isik Erhan */ @ConfigurationProperties(ConfigMapConfigProperties.PREFIX) -public record ConfigMapConfigProperties(@DefaultValue("true") boolean enableApi, @DefaultValue List paths, +public record ConfigMapConfigProperties(@DefaultValue("true") boolean enableApi, @DefaultValue List sources, @DefaultValue Map labels, @DefaultValue("true") boolean enabled, String name, String namespace, boolean useNameAsPrefix, @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java index 8ad636d805..f681248016 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java @@ -37,7 +37,7 @@ */ @ConfigurationProperties(SecretsConfigProperties.PREFIX) public record SecretsConfigProperties(boolean enableApi, @DefaultValue Map labels, - @DefaultValue List paths, @DefaultValue List sources, @DefaultValue("true") boolean enabled, + @DefaultValue List sources, @DefaultValue("true") boolean enabled, String name, String namespace, boolean useNameAsPrefix, @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, @DefaultValue RetryProperties retry, @DefaultValue("BATCH") ReadType readType) { diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesBindingTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesBindingTests.java index 0043b4586a..2d5c7eb57a 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesBindingTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesBindingTests.java @@ -40,7 +40,6 @@ void testWithDefaults() { ConfigMapConfigProperties props = context.getBean(ConfigMapConfigProperties.class); Assertions.assertThat(props).isNotNull(); Assertions.assertThat(props.enableApi()).isTrue(); - Assertions.assertThat(props.paths().isEmpty()).isTrue(); Assertions.assertThat(props.sources().isEmpty()).isTrue(); Assertions.assertThat(props.labels().isEmpty()).isTrue(); Assertions.assertThat(props.enabled()).isTrue(); @@ -64,7 +63,6 @@ void testWithDefaults() { void testWithNonDefaults() { new ApplicationContextRunner().withUserConfiguration(Config.class) .withPropertyValues("spring.cloud.kubernetes.config.enableApi=false", - "spring.cloud.kubernetes.config.paths[0]=a", "spring.cloud.kubernetes.config.paths[1]=b", "spring.cloud.kubernetes.config.sources[0].name=source-a", "spring.cloud.kubernetes.config.sources[0].namespace=source-namespace-a", "spring.cloud.kubernetes.config.sources[0].labels.key=source-value", @@ -88,10 +86,6 @@ void testWithNonDefaults() { Assertions.assertThat(props).isNotNull(); Assertions.assertThat(props.enableApi()).isFalse(); - Assertions.assertThat(props.paths().size()).isEqualTo(2); - Assertions.assertThat(props.paths().get(0)).isEqualTo("a"); - Assertions.assertThat(props.paths().get(1)).isEqualTo("b"); - Assertions.assertThat(props.sources().size()).isEqualTo(1); ConfigMapConfigProperties.Source source = props.sources().get(0); Assertions.assertThat(source.name()).isEqualTo("source-a"); diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java index 75b991b33a..d38d8f2648 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java @@ -48,7 +48,7 @@ class ConfigMapConfigPropertiesTests { */ @Test void testUseNameAsPrefixUnsetEmptySources() { - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -74,7 +74,7 @@ void testUseNameAsPrefixUnsetEmptySources() { */ @Test void testUseNameAsPrefixSetEmptySources() { - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -105,7 +105,7 @@ void testUseNameAsPrefixUnsetNonEmptySources() { ConfigMapConfigProperties.Source one = new ConfigMapConfigProperties.Source("config-map-one", null, Collections.emptyMap(), null, null, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(one), Map.of(), + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one), Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -148,7 +148,7 @@ void testUseNameAsPrefixSetNonEmptySources() { ConfigMapConfigProperties.Source three = new ConfigMapConfigProperties.Source("config-map-three", null, Collections.emptyMap(), null, true, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(one, two, three), + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -198,7 +198,7 @@ void testMultipleCases() { ConfigMapConfigProperties.Source four = new ConfigMapConfigProperties.Source(null, "config-map-four", Collections.emptyMap(), null, false, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three, four), Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); @@ -232,7 +232,7 @@ void testMultipleCases() { @Test void testUseIncludeProfileSpecificSourcesNoChanges() { - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), Map.of(), true, "config-map-a", "spring-k8s", false, true, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -261,7 +261,7 @@ void testUseIncludeProfileSpecificSourcesNoChanges() { @Test void testUseIncludeProfileSpecificSourcesDefaultChanged() { - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -305,7 +305,7 @@ void testUseIncludeProfileSpecificSourcesDefaultChangedSourceOverride() { ConfigMapConfigProperties.Source three = new ConfigMapConfigProperties.Source("config-map-three", null, Collections.emptyMap(), null, null, false); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), List.of(one, two, three), + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -362,7 +362,7 @@ void testLabelsMultipleCases() { ConfigMapConfigProperties.Source four = new ConfigMapConfigProperties.Source(null, null, Map.of("fourth-label", "configmap-four"), null, null, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three, four), Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesBindingTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesBindingTests.java index ca90173861..6b67610eaf 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesBindingTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesBindingTests.java @@ -40,7 +40,6 @@ void testWithDefaults() { SecretsConfigProperties props = context.getBean(SecretsConfigProperties.class); Assertions.assertThat(props).isNotNull(); Assertions.assertThat(props.enableApi()).isFalse(); - Assertions.assertThat(props.paths()).isEmpty(); Assertions.assertThat(props.sources()).isEmpty(); Assertions.assertThat(props.labels()).isEmpty(); Assertions.assertThat(props.enabled()).isTrue(); @@ -64,7 +63,6 @@ void testWithDefaults() { void testWithNonDefaults() { new ApplicationContextRunner().withUserConfiguration(Config.class) .withPropertyValues("spring.cloud.kubernetes.secrets.enableApi=false", - "spring.cloud.kubernetes.secrets.paths[0]=a", "spring.cloud.kubernetes.secrets.paths[1]=b", "spring.cloud.kubernetes.secrets.sources[0].name=source-a", "spring.cloud.kubernetes.secrets.sources[0].namespace=source-namespace-a", "spring.cloud.kubernetes.secrets.sources[0].labels.key=source-value", @@ -88,10 +86,6 @@ void testWithNonDefaults() { Assertions.assertThat(props).isNotNull(); Assertions.assertThat(props.enableApi()).isFalse(); - Assertions.assertThat(props.paths().size()).isEqualTo(2); - Assertions.assertThat(props.paths().get(0)).isEqualTo("a"); - Assertions.assertThat(props.paths().get(1)).isEqualTo("b"); - Assertions.assertThat(props.sources().size()).isEqualTo(1); SecretsConfigProperties.Source source = props.sources().get(0); Assertions.assertThat(source.name()).isEqualTo("source-a"); diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java index b24571dcd8..25bf8bef82 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java @@ -38,7 +38,7 @@ class SecretsConfigPropertiesTests { @Test void emptySourcesSecretName() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), List.of(), true, + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, null, "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List source = properties.determineSources(new MockEnvironment()); @@ -79,7 +79,7 @@ void multipleSources() { SecretsConfigProperties.Source three = new SecretsConfigProperties.Source(null, "spring-k8s", Map.of("three", "3"), null, false, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three), true, null, "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -122,7 +122,7 @@ void multipleSources() { @Test void testUseNameAsPrefixUnsetEmptySources() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), List.of(), true, + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, "secret-a", "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -149,7 +149,7 @@ void testUseNameAsPrefixUnsetEmptySources() { @Test void testUseNameAsPrefixSetEmptySources() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), List.of(), true, + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, "secret-a", "namespace", true, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -180,7 +180,7 @@ void testUseNameAsPrefixUnsetNonEmptySources() { SecretsConfigProperties.Source one = new SecretsConfigProperties.Source("secret-one", "spring-k8s", Map.of(), null, true, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), List.of(one), true, + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one), true, "secret-one", null, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); @@ -223,7 +223,7 @@ void testUseNameAsPrefixSetNonEmptySources() { SecretsConfigProperties.Source three = new SecretsConfigProperties.Source("secret-three", "spring-k8s", Map.of(), null, true, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three), true, "secret-one", null, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -274,7 +274,7 @@ void testMultipleCases() { SecretsConfigProperties.Source four = new SecretsConfigProperties.Source("secret-four", "spring-k8s", Map.of(), null, false, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three, four), true, "secret-one", "spring-k8s", false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -336,7 +336,7 @@ void testLabelsMultipleCases() { SecretsConfigProperties.Source four = new SecretsConfigProperties.Source(null, "spring-k8s", Map.of("fourth-label", "secret-four"), null, false, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three, four), false, null, "spring-k8s", false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); From 3ddaeb6028dd729468daf2df8f4bde0be9388fd9 Mon Sep 17 00:00:00 2001 From: wind57 Date: Sun, 5 Oct 2025 12:18:31 +0300 Subject: [PATCH 3/3] initial work started Signed-off-by: wind57 --- ...entConfigMapErrorOnReadingSourceTests.java | 4 +- ...ntConfigMapPropertySourceLocatorTests.java | 27 ++-- ...ientSecretsPropertySourceLocatorTests.java | 18 +-- .../reload_it/EventReloadConfigMapTest.java | 8 +- .../reload_it/EventReloadSecretTest.java | 7 +- .../reload_it/PollingReloadConfigMapTest.java | 6 +- .../reload_it/PollingReloadSecretTest.java | 7 +- .../config/ConfigMapConfigProperties.java | 7 +- .../ConfigMapPropertySourceLocator.java | 65 -------- .../config/MountConfigMapPropertySource.java | 32 ---- .../config/SecretsConfigProperties.java | 5 +- .../config/SecretsPropertySourceLocator.java | 106 +------------ .../config/reload/ConfigReloadUtil.java | 18 --- .../kubernetes/commons/SanitizeTests.java | 15 +- .../ConfigMapConfigPropertiesTests.java | 22 ++- ...rnetesConfigDataLocationResolverTests.java | 11 +- .../config/SecretsConfigPropertiesTests.java | 22 ++- .../config/reload/ConfigReloadUtilTests.java | 36 +---- .../fabric8/config/ConfigMapTestUtil.java | 7 - ...ic8ConfigMapErrorOnReadingSourceTests.java | 14 +- ...nfigMapPropertySourceLocatorMockTests.java | 4 +- ...c8ConfigMapPropertySourceLocatorTests.java | 8 +- ...abric8SecretErrorOnReadingSourceTests.java | 18 +-- ...ric8SecretsPropertySourceLocatorTests.java | 8 +- .../config_maps_mixed/ConfigMapsMixed.java | 60 +------- ...BootstrapConfigMapsFromFilePathsTests.java | 38 ----- ...onfigDataConfigMapsFromFilePathsTests.java | 38 ----- .../ConfigMapsFromFilePaths.java | 142 ------------------ ...gFailFastEnabledButRetryDisabledTests.java | 2 +- .../reload_it/EventReloadConfigMapTest.java | 6 +- .../reload_it/EventReloadSecretTest.java | 7 +- .../reload_it/PollingReloadConfigMapTest.java | 6 +- .../reload_it/PollingReloadSecretTest.java | 7 +- .../kubernetes/fabric8/client/reload/App.java | 2 +- .../reload/ConfigMapNoMountProperties.java | 20 ++- .../client/reload/ConfigMapProperties.java | 4 +- .../resources/application-configtree.yaml | 16 ++ .../src/main/resources/application-mount.yaml | 16 -- .../src/main/resources/application-three.yaml | 4 - .../resources/application-with-bootstrap.yaml | 12 -- .../resources/bootstrap-with-bootstrap.yaml | 6 - ...java => Fabric8ConfigMapConfigTreeIT.java} | 65 ++++---- ...bric8ConfigMapMountPollingBootstrapIT.java | 130 ---------------- .../fabric8/client/reload/TestAssertions.java | 2 +- .../manifests/configmap-configtree.yaml | 7 + .../test/resources/manifests/deployment.yaml | 6 +- .../client/reload/ConfigMapProperties.java | 8 +- .../src/main/resources/application-mount.yaml | 26 ++-- .../resources/application-with-bootstrap.yaml | 19 ++- .../resources/application-with-secret.yaml | 7 - .../resources/bootstrap-with-bootstrap.yaml | 8 +- ...va => K8sClientConfigMapConfigTreeIT.java} | 90 +++++------ ....java => K8sClientSecretConfigTreeIT.java} | 59 +++++--- .../src/test/resources/configmap-mount.yaml | 7 + .../src/test/resources/mount/configmap.yaml | 3 +- .../src/test/resources/mount/secret.yaml | 3 +- .../tests/commons/fabric8_client/Util.java | 16 ++ .../tests/commons/native_client/Util.java | 13 ++ .../resources/config-watcher/deployment.yaml | 37 +++++ .../resources/config-watcher/service.yaml | 14 ++ 60 files changed, 400 insertions(+), 981 deletions(-) delete mode 100644 spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountConfigMapPropertySource.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/BootstrapConfigMapsFromFilePathsTests.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigDataConfigMapsFromFilePathsTests.java delete mode 100644 spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigMapsFromFilePaths.java rename spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountSecretPropertySource.java => spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapNoMountProperties.java (65%) create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-configtree.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-mount.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-bootstrap.yaml delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml rename spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/{Fabric8ConfigMapMountPollingReloadIT.java => Fabric8ConfigMapConfigTreeIT.java} (61%) delete mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingBootstrapIT.java create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/configmap-configtree.yaml rename spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/{K8sClientConfigMapMountPollingIT.java => K8sClientConfigMapConfigTreeIT.java} (50%) rename spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/{K8sClientSecretMountBootstrapPollingIT.java => K8sClientSecretConfigTreeIT.java} (59%) create mode 100644 spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/configmap-mount.yaml create mode 100644 spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/deployment.yaml create mode 100644 spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/service.yaml diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java index 383769a920..74a52adfb5 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapErrorOnReadingSourceTests.java @@ -110,8 +110,8 @@ void namedSingleConfigMapFails(CapturedOutput output) { stubFor(get(path).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - Map.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); CoreV1Api api = new CoreV1Api(); KubernetesClientConfigMapPropertySourceLocator locator = new KubernetesClientConfigMapPropertySourceLocator(api, diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java index cc6e2059e5..063aeee14f 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientConfigMapPropertySourceLocatorTests.java @@ -106,8 +106,8 @@ void locateWithoutSources() { CoreV1Api api = new CoreV1Api(); stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(PROPERTIES_CONFIGMAP_LIST)))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); MockEnvironment mockEnvironment = new MockEnvironment(); mockEnvironment.setProperty("spring.cloud.kubernetes.client.namespace", "default"); PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(api, @@ -125,9 +125,8 @@ void locateWithSources() { ConfigMapConfigProperties.Source source = new ConfigMapConfigProperties.Source("bootstrap-640", "default", Collections.emptyMap(), null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - List.of(source), Map.of(), true, "fake-name", null, false, false, false, RetryProperties.DEFAULT, - ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(source), + Map.of(), true, "fake-name", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())) @@ -149,8 +148,8 @@ void testLocateWithoutNamespaceConstructor() { stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(PROPERTIES_CONFIGMAP_LIST)))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); assertThatThrownBy(() -> new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())) @@ -169,8 +168,8 @@ void testLocateWithoutNamespace() { CoreV1Api api = new CoreV1Api(); stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(200).withBody(JSON.serialize(PROPERTIES_CONFIGMAP_LIST)))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "bootstrap-640", null, false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); assertThatThrownBy(() -> new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(ENV)) .locate(ENV)).isInstanceOf(NamespaceResolutionFailedException.class); @@ -182,9 +181,8 @@ public void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() { stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "bootstrap-640", "default", false, false, true, RetryProperties.DEFAULT, - ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "bootstrap-640", "default", false, false, true, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesClientConfigMapPropertySourceLocator locator = new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -199,9 +197,8 @@ public void locateShouldNotThrowExceptionOnFailureWhenFailFastIsDisabled(Capture stubFor(get("/api/v1/namespaces/default/configmaps") .willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "bootstrap-640", "default", false, false, false, RetryProperties.DEFAULT, - ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "bootstrap-640", "default", false, false, false, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesClientConfigMapPropertySourceLocator locator = new KubernetesClientConfigMapPropertySourceLocator(api, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java index e26cf30ed6..0ad31d67b6 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/KubernetesClientSecretsPropertySourceLocatorTests.java @@ -147,7 +147,7 @@ void getLocateWithSources() { SecretsConfigProperties.Source source2 = new SecretsConfigProperties.Source("rabbit-password", "", Collections.emptyMap(), null, null, null); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(source1, source2), true, "app", "default", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -162,8 +162,8 @@ void getLocateWithSources() { void getLocateWithOutSources() { CoreV1Api api = new CoreV1Api(); stubFor(get(LIST_API).willReturn(aResponse().withStatus(200).withBody(LIST_BODY))); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, "db-secret", "default", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + "db-secret", "default", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); PropertySource propertySource = new KubernetesClientSecretsPropertySourceLocator(api, new KubernetesNamespaceProvider(new MockEnvironment()), secretsConfigProperties) @@ -184,8 +184,8 @@ void testLocateWithoutNamespaceConstructor() { CoreV1Api api = new CoreV1Api(); stubFor(get(LIST_API).willReturn(aResponse().withStatus(200).withBody(LIST_BODY))); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, "db-secret", "", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + "db-secret", "", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); assertThatThrownBy(() -> new KubernetesClientSecretsPropertySourceLocator(api, new KubernetesNamespaceProvider(new MockEnvironment()), secretsConfigProperties) @@ -197,8 +197,8 @@ void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() { CoreV1Api api = new CoreV1Api(); stubFor(get(LIST_API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, "db-secret", "default", false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + "db-secret", "default", false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesClientSecretsPropertySourceLocator locator = new KubernetesClientSecretsPropertySourceLocator(api, new KubernetesNamespaceProvider(new MockEnvironment()), secretsConfigProperties); @@ -212,8 +212,8 @@ void locateShouldNotThrowExceptionOnFailureWhenFailFastIsDisabled(CapturedOutput CoreV1Api api = new CoreV1Api(); stubFor(get(LIST_API).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, "db-secret", "default", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + "db-secret", "default", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesClientSecretsPropertySourceLocator locator = new KubernetesClientSecretsPropertySourceLocator(api, new KubernetesNamespaceProvider(new MockEnvironment()), secretsConfigProperties); diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java index e44925efda..ec4b7f2dbb 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java @@ -217,8 +217,8 @@ AbstractEnvironment environment() { // KubernetesClientConfigMapPropertySource, // otherwise we can't properly test reload functionality ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, FAIL_FAST, - RetryProperties.DEFAULT, ReadType.BATCH); + Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, FAIL_FAST, RetryProperties.DEFAULT, + ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); PropertySource propertySource = new KubernetesClientConfigMapPropertySourceLocator(coreV1Api, @@ -240,8 +240,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary ConfigMapConfigProperties configMapConfigProperties() { - return new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new ConfigMapConfigProperties(true, List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, + true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java index 9aa33e46fc..fcd6d97095 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java @@ -222,8 +222,7 @@ AbstractEnvironment environment() { // KubernetesClientConfigMapPropertySource, // otherwise we can't properly test reload functionality SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, SECRET_NAME, NAMESPACE, false, true, FAIL_FAST, RetryProperties.DEFAULT, - ReadType.BATCH); + true, SECRET_NAME, NAMESPACE, false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); PropertySource propertySource = new KubernetesClientSecretsPropertySourceLocator(coreV1Api, @@ -245,8 +244,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary SecretsConfigProperties secretsConfigProperties() { - return new SecretsConfigProperties(true, Map.of(), List.of(), List.of(), true, SECRET_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new SecretsConfigProperties(true, Map.of(), List.of(), true, SECRET_NAME, NAMESPACE, false, true, + FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java index 6ced5a499b..54b795190c 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadConfigMapTest.java @@ -193,7 +193,7 @@ AbstractEnvironment environment() { // KubernetesClientConfigMapPropertySource, // otherwise we can't properly test reload functionality ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, + Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); @@ -216,8 +216,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary ConfigMapConfigProperties configMapConfigProperties() { - return new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new ConfigMapConfigProperties(true, List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, + true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java index 641eb717bb..2da37c5fb0 100644 --- a/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java +++ b/spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/PollingReloadSecretTest.java @@ -195,8 +195,7 @@ AbstractEnvironment environment() { // KubernetesClientSecretPropertySource, // otherwise we can't properly test reload functionality SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, SECRET_NAME, NAMESPACE, false, true, false, RetryProperties.DEFAULT, - ReadType.BATCH); + true, SECRET_NAME, NAMESPACE, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); PropertySource propertySource = new KubernetesClientSecretsPropertySourceLocator(coreV1Api, @@ -218,8 +217,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary SecretsConfigProperties secretsConfigProperties() { - return new SecretsConfigProperties(true, Map.of(), List.of(), List.of(), true, SECRET_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new SecretsConfigProperties(true, Map.of(), List.of(), true, SECRET_NAME, NAMESPACE, false, true, + FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java index 11c5cfd539..9b082217c5 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java @@ -35,10 +35,9 @@ * @author Isik Erhan */ @ConfigurationProperties(ConfigMapConfigProperties.PREFIX) -public record ConfigMapConfigProperties(@DefaultValue("true") boolean enableApi, - @DefaultValue List sources, @DefaultValue Map labels, - @DefaultValue("true") boolean enabled, String name, String namespace, boolean useNameAsPrefix, - @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, +public record ConfigMapConfigProperties(@DefaultValue("true") boolean enableApi, @DefaultValue List sources, + @DefaultValue Map labels, @DefaultValue("true") boolean enabled, String name, String namespace, + boolean useNameAsPrefix, @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, @DefaultValue RetryProperties retry, @DefaultValue("BATCH") ReadType readType) { /** diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java index dd5710fd20..980a8741a9 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapPropertySourceLocator.java @@ -16,16 +16,9 @@ package org.springframework.cloud.kubernetes.commons.config; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Collection; -import java.util.HashMap; import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Map; import java.util.Set; -import java.util.function.Function; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -37,10 +30,6 @@ import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; -import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.KEY_VALUE_TO_PROPERTIES; -import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.PROPERTIES_TO_MAP; -import static org.springframework.cloud.kubernetes.commons.config.PropertySourceUtils.yamlParserGenerator; - /** * A {@link PropertySourceLocator} that uses config maps. * @@ -82,8 +71,6 @@ public PropertySource locate(Environment environment) { }); } - addPropertySourcesFromPaths(environment, composite); - return composite; } return null; @@ -94,56 +81,4 @@ public Collection> locateCollection(Environment environment) { return PropertySourceLocator.super.locateCollection(environment); } - private void addPropertySourcesFromPaths(Environment environment, CompositePropertySource composite) { - Set uniquePaths = new LinkedHashSet<>(properties.paths()); - if (!uniquePaths.isEmpty()) { - LOG.warn( - "path support is deprecated and will be removed in a future release. Please use spring.config.import"); - } - LOG.debug("paths property sources : " + uniquePaths); - uniquePaths.stream().map(Paths::get).filter(p -> { - boolean exists = Files.exists(p); - if (!exists) { - LOG.warn("Configured input path: " + p - + " will be ignored because it does not exist on the file system"); - } - return exists; - }).filter(p -> { - boolean regular = Files.isRegularFile(p); - if (!regular) { - LOG.warn("Configured input path: " + p + " will be ignored because it is not a regular file"); - } - return regular; - }).toList().forEach(p -> { - try { - String content = new String(Files.readAllBytes(p)).trim(); - String filename = p.toAbsolutePath().toString().toLowerCase(Locale.ROOT); - if (filename.endsWith(".properties")) { - addPropertySourceIfNeeded(c -> PROPERTIES_TO_MAP.apply(KEY_VALUE_TO_PROPERTIES.apply(c)), content, - filename, composite); - } - else if (filename.endsWith(".yml") || filename.endsWith(".yaml")) { - addPropertySourceIfNeeded(c -> yamlParserGenerator(environment).apply(c), content, filename, - composite); - } - } - catch (IOException e) { - LOG.warn("Error reading input file", e); - } - }); - } - - private void addPropertySourceIfNeeded(Function> contentToMapFunction, String content, - String name, CompositePropertySource composite) { - - Map map = new HashMap<>(contentToMapFunction.apply(content)); - if (map.isEmpty()) { - LOG.warn("Property source: " + name + "will be ignored because no properties could be found"); - } - else { - LOG.debug("will add file-based property source : " + name); - composite.addFirstPropertySource(new MountConfigMapPropertySource(name, map)); - } - } - } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountConfigMapPropertySource.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountConfigMapPropertySource.java deleted file mode 100644 index 522360deec..0000000000 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountConfigMapPropertySource.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013-present 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.Map; - -import org.springframework.core.env.MapPropertySource; - -/** - * @author wind57 - */ -public final class MountConfigMapPropertySource extends MapPropertySource { - - public MountConfigMapPropertySource(String name, Map source) { - super(name, source); - } - -} diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java index f681248016..af0ce7e57f 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java @@ -37,9 +37,8 @@ */ @ConfigurationProperties(SecretsConfigProperties.PREFIX) public record SecretsConfigProperties(boolean enableApi, @DefaultValue Map labels, - @DefaultValue List sources, @DefaultValue("true") boolean enabled, - String name, String namespace, boolean useNameAsPrefix, - @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, + @DefaultValue List sources, @DefaultValue("true") boolean enabled, String name, String namespace, + boolean useNameAsPrefix, @DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast, @DefaultValue RetryProperties retry, @DefaultValue("BATCH") ReadType readType) { /** diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java index 9602d8b8d6..85636a442b 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsPropertySourceLocator.java @@ -16,25 +16,10 @@ package org.springframework.cloud.kubernetes.commons.config; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; import java.util.Collection; -import java.util.EnumSet; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collector; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -64,6 +49,9 @@ public SecretsPropertySourceLocator(SecretsConfigProperties properties) { this.properties = properties; } + protected abstract SecretsPropertySource getPropertySource(ConfigurableEnvironment environment, + NormalizedSource normalizedSource, ReadType readType); + @Override public PropertySource locate(Environment environment) { if (environment instanceof ConfigurableEnvironment env) { @@ -72,8 +60,6 @@ public PropertySource locate(Environment environment) { Set uniqueSources = new HashSet<>(sources); LOG.debug("Secrets normalized sources : " + sources); CompositePropertySource composite = new CompositePropertySource("composite-secrets"); - // read for secrets mount - putPathConfig(composite); if (this.properties.enableApi()) { uniqueSources.forEach(secretSource -> { @@ -99,90 +85,4 @@ public Collection> locateCollection(Environment environment) { return PropertySourceLocator.super.locateCollection(environment); } - protected abstract SecretsPropertySource getPropertySource(ConfigurableEnvironment environment, - NormalizedSource normalizedSource, ReadType readType); - - protected void putPathConfig(CompositePropertySource composite) { - - Set uniquePaths = new LinkedHashSet<>(properties.paths()); - - if (!uniquePaths.isEmpty()) { - LOG.warn( - "path support is deprecated and will be removed in a future release. Please use spring.config.import"); - } - - LOG.debug("paths property sources : " + uniquePaths); - - uniquePaths.stream().map(Paths::get).filter(Files::exists).flatMap(x -> { - try { - return Files.walk(x); - } - catch (IOException e) { - LOG.warn("Error walking properties files", e); - return null; - } - }) - .filter(Objects::nonNull) - .filter(Files::isRegularFile) - .collect(new SecretsPropertySourceCollector()) - .forEach(composite::addPropertySource); - } - - /** - * @author wind57 - */ - private static class SecretsPropertySourceCollector - implements Collector, List> { - - @Override - public Supplier> supplier() { - return ArrayList::new; - } - - @Override - public BiConsumer, Path> accumulator() { - return (list, filePath) -> { - MountSecretPropertySource source = property(filePath); - if (source != null) { - list.add(source); - } - }; - } - - @Override - public BinaryOperator> combiner() { - return (left, right) -> { - left.addAll(right); - return left; - }; - } - - @Override - public Function, List> finisher() { - return Function.identity(); - } - - @Override - public Set characteristics() { - return EnumSet.of(Characteristics.UNORDERED, Characteristics.IDENTITY_FINISH); - } - - private MountSecretPropertySource property(Path filePath) { - - String fileName = filePath.getFileName().toString(); - - try { - String content = new String(Files.readAllBytes(filePath)).trim(); - String sourceName = fileName.toLowerCase(Locale.ROOT); - SourceData sourceData = new SourceData(sourceName, Map.of(fileName, content)); - return new MountSecretPropertySource(sourceData); - } - catch (IOException e) { - LOG.warn("Error reading properties file", e); - return null; - } - } - - } - } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java index 7685f705b0..caaf79100c 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtil.java @@ -26,8 +26,6 @@ import org.springframework.cloud.bootstrap.config.BootstrapPropertySource; import org.springframework.cloud.bootstrap.config.PropertySourceLocator; -import org.springframework.cloud.kubernetes.commons.config.MountConfigMapPropertySource; -import org.springframework.cloud.kubernetes.commons.config.MountSecretPropertySource; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; @@ -106,28 +104,12 @@ static > List findPropertySources(Class source else if (sourceClass.isInstance(source)) { managedSources.add(sourceClass.cast(source)); } - else if (source instanceof MountConfigMapPropertySource mountConfigMapPropertySource) { - // we know that the type is correct here - managedSources.add((S) mountConfigMapPropertySource); - } - else if (source instanceof MountSecretPropertySource mountSecretPropertySource) { - // we know that the type is correct here - managedSources.add((S) mountSecretPropertySource); - } else if (source instanceof BootstrapPropertySource bootstrapPropertySource) { PropertySource propertySource = bootstrapPropertySource.getDelegate(); LOG.debug(() -> "bootstrap delegate class : " + propertySource.getClass()); if (sourceClass.isInstance(propertySource)) { sources.add(propertySource); } - else if (propertySource instanceof MountConfigMapPropertySource mountConfigMapPropertySource) { - // we know that the type is correct here - managedSources.add((S) mountConfigMapPropertySource); - } - else if (propertySource instanceof MountSecretPropertySource mountSecretPropertySource) { - // we know that the type is correct here - managedSources.add((S) mountSecretPropertySource); - } } } diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/SanitizeTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/SanitizeTests.java index 13c5526c95..151a3eed03 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/SanitizeTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/SanitizeTests.java @@ -26,11 +26,11 @@ import org.springframework.boot.actuate.endpoint.Sanitizer; import org.springframework.boot.actuate.endpoint.SanitizingFunction; import org.springframework.cloud.bootstrap.config.BootstrapPropertySource; -import org.springframework.cloud.kubernetes.commons.config.MountConfigMapPropertySource; import org.springframework.cloud.kubernetes.commons.config.SecretsPropertySource; import org.springframework.cloud.kubernetes.commons.config.SourceData; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MapPropertySource; import static org.springframework.boot.actuate.endpoint.SanitizableData.SANITIZED_VALUE; @@ -82,7 +82,7 @@ void bootstrapPropertySourceSecrets() { void notSecretsPropertySource() { BootstrapPropertySource bootstrapPropertySource = new BootstrapPropertySource<>( - new MountConfigMapPropertySource("mount-source", Map.of())); + new DummyPropertySource("mount-source", Map.of())); Sanitizer sanitizer = new Sanitizer(SANITIZING_FUNCTIONS); SanitizableData sanitizableData = new SanitizableData(bootstrapPropertySource, "secret", "xyz"); @@ -107,8 +107,7 @@ void compositeOneSecretOneMount() { CompositePropertySource compositePropertySource = new CompositePropertySource("composite"); compositePropertySource.addFirstPropertySource( new SecretsPropertySource(new SourceData("secret-source", Map.of("secret", "xyz")))); - compositePropertySource - .addFirstPropertySource(new MountConfigMapPropertySource("mount-source", Map.of("mount", "abc"))); + compositePropertySource.addFirstPropertySource(new DummyPropertySource("mount-source", Map.of("mount", "abc"))); Sanitizer sanitizer = new Sanitizer(SANITIZING_FUNCTIONS); SanitizableData sanitizableDataSecret = new SanitizableData(compositePropertySource, "secret", "xyz"); @@ -118,4 +117,12 @@ void compositeOneSecretOneMount() { Assertions.assertThat(sanitizer.sanitize(sanitizableDataMount, SHOW_UNSANITIZED)).isEqualTo("abc"); } + static class DummyPropertySource extends MapPropertySource { + + DummyPropertySource(String name, Map source) { + super(name, source); + } + + } + } diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java index d38d8f2648..227b07b98a 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigPropertiesTests.java @@ -105,8 +105,8 @@ void testUseNameAsPrefixUnsetNonEmptySources() { ConfigMapConfigProperties.Source one = new ConfigMapConfigProperties.Source("config-map-one", null, Collections.emptyMap(), null, null, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one), Map.of(), - true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one), Map.of(), true, + "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(1); @@ -148,8 +148,8 @@ void testUseNameAsPrefixSetNonEmptySources() { ConfigMapConfigProperties.Source three = new ConfigMapConfigProperties.Source("config-map-three", null, Collections.emptyMap(), null, true, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), - Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), Map.of(), + true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(3); @@ -198,9 +198,8 @@ void testMultipleCases() { ConfigMapConfigProperties.Source four = new ConfigMapConfigProperties.Source(null, "config-map-four", Collections.emptyMap(), null, false, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, - List.of(one, two, three, four), Map.of(), true, "config-map-a", "spring-k8s", true, false, false, - RetryProperties.DEFAULT, BATCH); + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three, four), + Map.of(), true, "config-map-a", "spring-k8s", true, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(4); @@ -305,8 +304,8 @@ void testUseIncludeProfileSpecificSourcesDefaultChangedSourceOverride() { ConfigMapConfigProperties.Source three = new ConfigMapConfigProperties.Source("config-map-three", null, Collections.emptyMap(), null, null, false); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), - Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three), Map.of(), + true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(3); @@ -362,9 +361,8 @@ void testLabelsMultipleCases() { ConfigMapConfigProperties.Source four = new ConfigMapConfigProperties.Source(null, null, Map.of("fourth-label", "configmap-four"), null, null, null); - ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, - List.of(one, two, three, four), Map.of(), true, "config-map-a", "spring-k8s", false, false, false, - RetryProperties.DEFAULT, BATCH); + ConfigMapConfigProperties properties = new ConfigMapConfigProperties(true, List.of(one, two, three, four), + Map.of(), true, "config-map-a", "spring-k8s", false, false, false, RetryProperties.DEFAULT, BATCH); List sources = properties.determineSources(new MockEnvironment()); // we get 8 property sources, since "named" ones with "application" are diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java index 264379e224..759fd37cbc 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/KubernetesConfigDataLocationResolverTests.java @@ -229,11 +229,11 @@ void testResolveProfileSpecificFour() { // 'one' and 'two' prove that we have not registered ConfigMapConfigProperties and // SecretsConfigProperties in the bootstrap context - ConfigMapConfigProperties one = new ConfigMapConfigProperties(false, List.of(), List.of(), Map.of(), false, - null, null, false, false, false, null, BATCH); + ConfigMapConfigProperties one = new ConfigMapConfigProperties(false, List.of(), Map.of(), false, null, null, + false, false, false, null, BATCH); - SecretsConfigProperties two = new SecretsConfigProperties(false, Map.of(), List.of(), List.of(), false, null, - null, false, false, false, null, ReadType.BATCH); + SecretsConfigProperties two = new SecretsConfigProperties(false, Map.of(), List.of(), false, null, null, false, + false, false, null, ReadType.BATCH); KubernetesClientProperties kubernetesClientProperties = RESOLVER_CONTEXT.getBootstrapContext() .get(KubernetesClientProperties.class); @@ -299,9 +299,6 @@ void testResolveProfileSpecificSix() { // on the other hand, @Default will be picked here Assertions.assertThat(result.get(0).getConfigMapProperties().enabled()).isTrue(); - // we have @DefaultValue enabled on paths, but it is not going to be picked up - // because of the explicit property we set in environment - Assertions.assertThat(result.get(0).getSecretsConfigProperties().paths().get(0)).isEqualTo("a"); // on the other hand, @Default will be picked here Assertions.assertThat(result.get(0).getSecretsConfigProperties().includeProfileSpecificSources()).isTrue(); } diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java index 25bf8bef82..925269a127 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigPropertiesTests.java @@ -38,8 +38,8 @@ class SecretsConfigPropertiesTests { @Test void emptySourcesSecretName() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, - null, "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, null, + "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List source = properties.determineSources(new MockEnvironment()); Assertions.assertThat(source.size()).isEqualTo(1); @@ -79,9 +79,8 @@ void multipleSources() { SecretsConfigProperties.Source three = new SecretsConfigProperties.Source(null, "spring-k8s", Map.of("three", "3"), null, false, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), - List.of(one, two, three), true, null, "namespace", false, true, false, RetryProperties.DEFAULT, - ReadType.BATCH); + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three), + true, null, "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List result = properties.determineSources(new MockEnvironment()); Assertions.assertThat(result.size()).isEqualTo(6); @@ -122,8 +121,8 @@ void multipleSources() { @Test void testUseNameAsPrefixUnsetEmptySources() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, - "secret-a", "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, "secret-a", + "namespace", false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(1); @@ -149,8 +148,8 @@ void testUseNameAsPrefixUnsetEmptySources() { @Test void testUseNameAsPrefixSetEmptySources() { - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, - "secret-a", "namespace", true, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(), true, "secret-a", + "namespace", true, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(1); @@ -223,9 +222,8 @@ void testUseNameAsPrefixSetNonEmptySources() { SecretsConfigProperties.Source three = new SecretsConfigProperties.Source("secret-three", "spring-k8s", Map.of(), null, true, false); - SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), - List.of(one, two, three), true, "secret-one", null, false, true, false, RetryProperties.DEFAULT, - ReadType.BATCH); + SecretsConfigProperties properties = new SecretsConfigProperties(false, Map.of(), List.of(one, two, three), + true, "secret-one", null, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); List sources = properties.determineSources(new MockEnvironment()); Assertions.assertThat(sources.size()).isEqualTo(3); diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtilTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtilTests.java index 418ebee0f7..4b1f3ff132 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtilTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/config/reload/ConfigReloadUtilTests.java @@ -26,9 +26,6 @@ import org.junit.jupiter.api.Test; import org.springframework.cloud.bootstrap.config.BootstrapPropertySource; -import org.springframework.cloud.kubernetes.commons.config.MountConfigMapPropertySource; -import org.springframework.cloud.kubernetes.commons.config.MountSecretPropertySource; -import org.springframework.cloud.kubernetes.commons.config.SourceData; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.MapPropertySource; @@ -141,43 +138,16 @@ public Object getProperty(String name) { return null; } })); - propertySources.addFirst(new MountConfigMapPropertySource("mounted", Map.of("a", "b"))); List result = ConfigReloadUtil.findPropertySources(PlainPropertySource.class, environment); - Assertions.assertThat(result.size()).isEqualTo(3); - Assertions.assertThat(result.get(0).getProperty("a")).isEqualTo("b"); - Assertions.assertThat(result.get(1).getProperty("")).isEqualTo("plain"); - Assertions.assertThat(result.get(2).getProperty("")).isEqualTo("from-inner-two-composite"); + Assertions.assertThat(result.size()).isEqualTo(2); + Assertions.assertThat(result.get(0).getProperty("a")).isEqualTo("plain"); + Assertions.assertThat(result.get(1).getProperty("")).isEqualTo("from-inner-two-composite"); } - @Test - void testSecretsPropertySource() { - MockEnvironment environment = new MockEnvironment(); - MutablePropertySources propertySources = environment.getPropertySources(); - propertySources.addFirst(new MountSecretPropertySource(new SourceData("secret", Map.of("a", "b")))); - - List result = ConfigReloadUtil.findPropertySources(PlainPropertySource.class, - environment); - assertThat(result.size()).isEqualTo(1); - assertThat(result.get(0).getProperty("a")).isEqualTo("b"); - } - - @Test - void testBootstrapSecretsPropertySource() { - MockEnvironment environment = new MockEnvironment(); - MutablePropertySources propertySources = environment.getPropertySources(); - propertySources - .addFirst(new OneBootstrap<>(new MountSecretPropertySource(new SourceData("secret", Map.of("a", "b"))))); - - List result = ConfigReloadUtil.findPropertySources(PlainPropertySource.class, - environment); - assertThat(result.size()).isEqualTo(1); - assertThat(result.get(0).getProperty("a")).isEqualTo("b"); - } - private static final class OneComposite extends CompositePropertySource { private OneComposite() { diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java index 35316dfad1..b697e18362 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/ConfigMapTestUtil.java @@ -17,9 +17,6 @@ package org.springframework.cloud.kubernetes.fabric8.config; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.Objects; import io.fabric8.kubernetes.client.utils.IOHelpers; @@ -41,8 +38,4 @@ public static String readResourceFile(String file) { return resource; } - public static void createFileWithContent(String file, String content) throws IOException { - Files.write(Paths.get(file), content.getBytes(), StandardOpenOption.CREATE); - } - } diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapErrorOnReadingSourceTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapErrorOnReadingSourceTests.java index 3b9bbdf84d..4450048b3d 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapErrorOnReadingSourceTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapErrorOnReadingSourceTests.java @@ -72,8 +72,8 @@ void namedSingleConfigMapFails(CapturedOutput output) { mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once(); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8ConfigMapPropertySourceLocator locator = new Fabric8ConfigMapPropertySourceLocator(mockClient, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -107,7 +107,7 @@ void namedTwoConfigMapsOneFails(CapturedOutput output) { Source sourceOne = new Source(configMapNameOne, namespace, Map.of(), null, null, null); Source sourceTwo = new Source(configMapNameTwo, namespace, Map.of(), null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of(), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -141,7 +141,7 @@ void namedTwoConfigMapsBothFail(CapturedOutput output) { Source sourceOne = new Source(configMapNameOne, namespace, Map.of(), null, null, null); Source sourceTwo = new Source(configMapNameTwo, namespace, Map.of(), null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of(), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -173,7 +173,7 @@ void labeledSingleConfigMapFails(CapturedOutput output) { Source configMapSource = new Source(null, namespace, labels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(configMapSource), labels, true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -217,7 +217,7 @@ void labeledTwoConfigMapsOneFails(CapturedOutput output) { Source sourceOne = new Source(null, namespace, configMapOneLabels, null, null, null); Source sourceTwo = new Source(null, namespace, configMapTwoLabels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of("one", "1", "two", "2"), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -256,7 +256,7 @@ void labeledTwoConfigMapsBothFail(CapturedOutput output) { Source sourceOne = new Source(null, namespace, configMapOneLabels, null, null, null); Source sourceTwo = new Source(null, namespace, configMapTwoLabels, null, null, null); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(sourceOne, sourceTwo), Map.of("one", "1", "two", "2"), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorMockTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorMockTests.java index 1bc1cee9b1..ad8a7821e3 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorMockTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorMockTests.java @@ -47,8 +47,8 @@ class Fabric8ConfigMapPropertySourceLocatorMockTests { @Test void constructorWithoutClientNamespaceMustFail() { - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, "name", null, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, "name", null, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); Mockito.when(client.getNamespace()).thenReturn(null); Fabric8ConfigMapPropertySourceLocator source = new Fabric8ConfigMapPropertySourceLocator(client, diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorTests.java index b9cad8cf82..7c74fa95ff 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8ConfigMapPropertySourceLocatorTests.java @@ -65,8 +65,8 @@ void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() { mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").always(); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, name, namespace, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, name, namespace, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8ConfigMapPropertySourceLocator locator = new Fabric8ConfigMapPropertySourceLocator(mockClient, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -83,8 +83,8 @@ void locateShouldNotThrowExceptionOnFailureWhenFailFastIsDisabled(CapturedOutput mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").always(); - ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), List.of(), - Map.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), Map.of(), + true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8ConfigMapPropertySourceLocator locator = new Fabric8ConfigMapPropertySourceLocator(mockClient, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretErrorOnReadingSourceTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretErrorOnReadingSourceTests.java index 3add57b598..243eb7b208 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretErrorOnReadingSourceTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretErrorOnReadingSourceTests.java @@ -71,8 +71,8 @@ void namedSingleSecretFails(CapturedOutput output) { mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").once(); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8SecretsPropertySourceLocator locator = new Fabric8SecretsPropertySourceLocator(mockClient, secretsConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -105,7 +105,7 @@ void namedTwoSecretsOneFails(CapturedOutput output) { Source sourceOne = new Source(secretNameOne, namespace, Map.of(), null, null, null); Source sourceTwo = new Source(secretNameTwo, namespace, Map.of(), null, null, null); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(sourceOne, sourceTwo), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -141,7 +141,7 @@ void namedTwoSecretsBothFail(CapturedOutput output) { Source sourceOne = new Source(secretNameOne, namespace, Map.of(), null, null, null); Source sourceTwo = new Source(secretNameTwo, namespace, Map.of(), null, null, null); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(sourceOne, sourceTwo), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -173,7 +173,7 @@ void labeledSingleSecretFails(CapturedOutput output) { Source secretSource = new Source(null, namespace, labels, null, null, null); - SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, labels, List.of(), + SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, labels, List.of(secretSource), true, null, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); @@ -219,8 +219,8 @@ void labeledTwoSecretsOneFails(CapturedOutput output) { Source sourceTwo = new Source(null, namespace, secretTwoLabels, null, null, null); SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, - Map.of("one", "1", "two", "2"), List.of(), List.of(sourceOne, sourceTwo), true, null, namespace, false, - true, false, RetryProperties.DEFAULT, ReadType.BATCH); + Map.of("one", "1", "two", "2"), List.of(sourceOne, sourceTwo), true, null, namespace, false, true, + false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8SecretsPropertySourceLocator locator = new Fabric8SecretsPropertySourceLocator(mockClient, secretsConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -259,8 +259,8 @@ void labeledTwoConfigMapsBothFail(CapturedOutput output) { Source sourceTwo = new Source(null, namespace, secretTwoLabels, null, null, null); SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, - Map.of("one", "1", "two", "2"), List.of(), List.of(sourceOne, sourceTwo), true, null, namespace, false, - true, false, RetryProperties.DEFAULT, ReadType.BATCH); + Map.of("one", "1", "two", "2"), List.of(sourceOne, sourceTwo), true, null, namespace, false, true, + false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8SecretsPropertySourceLocator locator = new Fabric8SecretsPropertySourceLocator(mockClient, secretsConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorTests.java index 74f82a498c..f91859ea38 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/Fabric8SecretsPropertySourceLocatorTests.java @@ -65,8 +65,8 @@ void locateShouldThrowExceptionOnFailureWhenFailFastIsEnabled() { mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").always(); - SecretsConfigProperties configMapConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, name, namespace, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties configMapConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + name, namespace, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8SecretsPropertySourceLocator locator = new Fabric8SecretsPropertySourceLocator(mockClient, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); @@ -83,8 +83,8 @@ void locateShouldNotThrowExceptionOnFailureWhenFailFastIsDisabled(CapturedOutput mockServer.expect().withPath(path).andReturn(500, "Internal Server Error").always(); - SecretsConfigProperties configMapConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); + SecretsConfigProperties configMapConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), true, + name, namespace, false, true, false, RetryProperties.DEFAULT, ReadType.BATCH); Fabric8SecretsPropertySourceLocator locator = new Fabric8SecretsPropertySourceLocator(mockClient, configMapConfigProperties, new KubernetesNamespaceProvider(new MockEnvironment())); diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/config_maps_mixed/ConfigMapsMixed.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/config_maps_mixed/ConfigMapsMixed.java index c0ccfe1605..011cedcb40 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/config_maps_mixed/ConfigMapsMixed.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/config_maps_mixed/ConfigMapsMixed.java @@ -16,45 +16,30 @@ package org.springframework.cloud.kubernetes.fabric8.config.config_maps_mixed; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.HashMap; import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import org.junit.jupiter.api.AfterAll; 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.ConfigMapTestUtil; import org.springframework.cloud.kubernetes.fabric8.config.TestApplication; import org.springframework.test.web.reactive.server.WebTestClient; -import static org.assertj.core.util.Lists.newArrayList; - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = TestApplication.class, - properties = { "spring.application.name=" + BootstrapConfigMapsMixedTests.APPLICATION_NAME, - "spring.cloud.kubernetes.config.enableApi=true", - "spring.cloud.kubernetes.config.paths=" + BootstrapConfigMapsMixedTests.FILE_NAME_FULL_PATH, - "spring.main.cloud-platform=KUBERNETES" }) + properties = { "spring.application.name=" + ConfigMapsMixed.APPLICATION_NAME, + "spring.cloud.kubernetes.config.enableApi=true", "spring.main.cloud-platform=KUBERNETES" }) abstract class ConfigMapsMixed { - protected static final String FILES_ROOT_PATH = "/tmp/scktests"; - - protected static final String FILE_NAME = "application-path.yaml"; - - protected static final String FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + FILE_NAME; - protected static final String APPLICATION_NAME = "configmap-mixed-example"; @Autowired private WebTestClient webClient; - static void setUpBeforeClass(KubernetesClient mockClient) throws IOException { + static void setUpBeforeClass(KubernetesClient mockClient) { // Configure the kubernetes master url to point to the mock server System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); @@ -64,10 +49,6 @@ static void setUpBeforeClass(KubernetesClient mockClient) throws IOException { System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); - Files.createDirectories(Paths.get(FILES_ROOT_PATH)); - ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH, - ConfigMapTestUtil.readResourceFile("application-path.yaml")); - HashMap data = new HashMap<>(); data.put("bean.morning", "Buenos Dias ConfigMap, %s"); @@ -80,41 +61,6 @@ static void setUpBeforeClass(KubernetesClient mockClient) throws IOException { mockClient.configMaps().inNamespace("test").resource(configMap).create(); } - @AfterAll - static void teardownAfterClass() { - newArrayList(FILE_NAME_FULL_PATH, FILES_ROOT_PATH).forEach(fn -> { - try { - Files.delete(Paths.get(fn)); - } - catch (IOException ignored) { - } - }); - } - - @Test - void greetingInputShouldReturnPropertyFromFile() { - this.webClient.get() - .uri("/api/greeting") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Hello ConfigMap, World from path"); - } - - @Test - void farewellInputShouldReturnPropertyFromFile() { - this.webClient.get() - .uri("/api/farewell") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Bye ConfigMap, World from path"); - } - @Test void morningInputShouldReturnPropertyFromApi() { this.webClient.get() diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/BootstrapConfigMapsFromFilePathsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/BootstrapConfigMapsFromFilePathsTests.java deleted file mode 100644 index a86437c038..0000000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/BootstrapConfigMapsFromFilePathsTests.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013-present 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.configmaps_from_file_paths; - -import java.io.IOException; - -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeAll; - -import org.springframework.test.context.TestPropertySource; - -@TestPropertySource(properties = { "spring.cloud.bootstrap.enabled=true" }) -@EnableKubernetesMockClient(crud = true, https = false) -class BootstrapConfigMapsFromFilePathsTests extends ConfigMapsFromFilePaths { - - private static KubernetesClient mockClient; - - @BeforeAll - static void setUpBeforeClass() throws IOException { - setUpBeforeClass(mockClient); - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigDataConfigMapsFromFilePathsTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigDataConfigMapsFromFilePathsTests.java deleted file mode 100644 index 6b6c577bf8..0000000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigDataConfigMapsFromFilePathsTests.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2013-present 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.configmaps_from_file_paths; - -import java.io.IOException; - -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeAll; - -import org.springframework.test.context.TestPropertySource; - -@TestPropertySource(properties = { "spring.config.import=kubernetes:" }) -@EnableKubernetesMockClient(crud = true, https = false) -class ConfigDataConfigMapsFromFilePathsTests extends ConfigMapsFromFilePaths { - - private static KubernetesClient mockClient; - - @BeforeAll - static void setUpBeforeClass() throws IOException { - setUpBeforeClass(mockClient); - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigMapsFromFilePaths.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigMapsFromFilePaths.java deleted file mode 100644 index ee00bda564..0000000000 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/configmaps_from_file_paths/ConfigMapsFromFilePaths.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2013-present 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.configmaps_from_file_paths; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; - -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.KubernetesClient; -import org.junit.jupiter.api.AfterAll; -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.commons.config.Constants; -import org.springframework.cloud.kubernetes.fabric8.config.ConfigMapTestUtil; -import org.springframework.cloud.kubernetes.fabric8.config.TestApplication; -import org.springframework.test.web.reactive.server.WebTestClient; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = TestApplication.class, - properties = { "spring.application.name=configmap-path-example", - "spring.cloud.kubernetes.config.enableApi=false", - "spring.cloud.kubernetes.config.paths=" + ConfigMapsFromFilePaths.FIRST_FILE_NAME_FULL_PATH + "," - + ConfigMapsFromFilePaths.SECOND_FILE_NAME_FULL_PATH + "," - + ConfigMapsFromFilePaths.FIRST_FILE_NAME_DUPLICATED_FULL_PATH, - "spring.main.cloud-platform=KUBERNETES" }) -abstract class ConfigMapsFromFilePaths { - - protected static final String FILES_ROOT_PATH = "/tmp/scktests"; - - protected static final String FILES_SUB_PATH = "another-directory"; - - protected static final String SECOND_FILE_NAME = "extra.properties"; - - protected static final String UNUSED_FILE_NAME = "unused.properties"; - - protected static final String FIRST_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + Constants.APPLICATION_PROPERTIES; - - protected static final String SECOND_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + SECOND_FILE_NAME; - - protected static final String UNUSED_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + UNUSED_FILE_NAME; - - protected static final String FIRST_FILE_NAME_DUPLICATED_FULL_PATH = FILES_ROOT_PATH + "/" + FILES_SUB_PATH + "/" - + Constants.APPLICATION_PROPERTIES; - - @Autowired - private WebTestClient webClient; - - static void setUpBeforeClass(KubernetesClient mockClient) throws IOException { - - // Configure the kubernetes master url to point to the mock server - System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl()); - System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true"); - System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); - System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); - System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); - Files.createDirectories(Paths.get(FILES_ROOT_PATH + "/" + FILES_SUB_PATH)); - ConfigMapTestUtil.createFileWithContent(FIRST_FILE_NAME_FULL_PATH, "bean.greeting=Hello from path!"); - ConfigMapTestUtil.createFileWithContent(SECOND_FILE_NAME_FULL_PATH, "bean.farewell=Bye from path!"); - ConfigMapTestUtil.createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, "bean.morning=Morning from path!"); - ConfigMapTestUtil.createFileWithContent(FIRST_FILE_NAME_DUPLICATED_FULL_PATH, - "bean.bonjour=Bonjour from path!"); - } - - @AfterAll - static void teardownAfterClass() { - List.of(FIRST_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH, FILES_ROOT_PATH) - .forEach(fn -> { - try { - Files.delete(Paths.get(fn)); - } - catch (IOException ignored) { - } - }); - } - - @Test - void greetingInputShouldReturnPropertyFromFirstFile() { - this.webClient.get() - .uri("/api/greeting") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Hello from path!"); - } - - @Test - void farewellInputShouldReturnPropertyFromSecondFile() { - this.webClient.get() - .uri("/api/farewell") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Bye from path!"); - } - - @Test - void morningInputShouldReturnDefaultValue() { - this.webClient.get() - .uri("/api/morning") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Good morning, World!"); - } - - @Test - void bonjourInputShouldReturnPropertyFromDuplicatedFile() { - this.webClient.get() - .uri("/api/bonjour") - .exchange() - .expectStatus() - .isOk() - .expectBody() - .jsonPath("content") - .isEqualTo("Bonjour from path!"); - } - -} diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/fail_fast_enabled_retry_disabled/ConfigDataConfigFailFastEnabledButRetryDisabledTests.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/fail_fast_enabled_retry_disabled/ConfigDataConfigFailFastEnabledButRetryDisabledTests.java index 0e7996e368..db1dd2b9b8 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/fail_fast_enabled_retry_disabled/ConfigDataConfigFailFastEnabledButRetryDisabledTests.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/locator_retry/fail_fast_enabled_retry_disabled/ConfigDataConfigFailFastEnabledButRetryDisabledTests.java @@ -72,7 +72,7 @@ static class LocalConfig { */ @Bean ConfigMapConfigProperties properties(Environment environment) { - return new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, null, null, false, true, + return new ConfigMapConfigProperties(true, List.of(), Map.of(), true, null, null, false, true, Boolean.parseBoolean(environment.getProperty("spring.cloud.kubernetes.config.fail-fast")), RetryProperties.DEFAULT, ReadType.BATCH); } diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java index c0fd79ec7d..d6fb749b05 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadConfigMapTest.java @@ -163,7 +163,7 @@ AbstractEnvironment environment() { // simulate that environment already has a Fabric8ConfigMapPropertySource, // otherwise we can't properly test reload functionality ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, + Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.SINGLE); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); @@ -186,8 +186,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary ConfigMapConfigProperties configMapConfigProperties() { - return new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); + return new ConfigMapConfigProperties(true, List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, + true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java index c65f782af5..04ce163c7b 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/EventReloadSecretTest.java @@ -170,8 +170,7 @@ AbstractEnvironment environment() { // Fabric8SecretsPropertySourceLocator, // otherwise we can't properly test reload functionality SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, SECRET_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, - ReadType.SINGLE); + true, SECRET_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.SINGLE); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); PropertySource propertySource = new VisibleFabric8SecretsPropertySourceLocator(kubernetesClient, @@ -193,8 +192,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary SecretsConfigProperties secretsConfigProperties() { - return new SecretsConfigProperties(true, Map.of(), List.of(), List.of(), true, SECRET_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); + return new SecretsConfigProperties(true, Map.of(), List.of(), true, SECRET_NAME, NAMESPACE, false, true, + FAIL_FAST, RetryProperties.DEFAULT, ReadType.SINGLE); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java index 93b1e3bbe6..8094a52524 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadConfigMapTest.java @@ -153,7 +153,7 @@ AbstractEnvironment environment() { // simulate that environment already has a Fabric8ConfigMapPropertySource, // otherwise we can't properly test reload functionality ConfigMapConfigProperties configMapConfigProperties = new ConfigMapConfigProperties(true, List.of(), - List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, + Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); @@ -176,8 +176,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary ConfigMapConfigProperties configMapConfigProperties() { - return new ConfigMapConfigProperties(true, List.of(), List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new ConfigMapConfigProperties(true, List.of(), Map.of(), true, CONFIG_MAP_NAME, NAMESPACE, false, + true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java index 2819b1e502..1a1fa462e9 100644 --- a/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java +++ b/spring-cloud-kubernetes-fabric8-config/src/test/java/org/springframework/cloud/kubernetes/fabric8/config/reload_it/PollingReloadSecretTest.java @@ -160,8 +160,7 @@ AbstractEnvironment environment() { // simulate that environment already has a Fabric8SecretsPropertySource, // otherwise we can't properly test reload functionality SecretsConfigProperties secretsConfigProperties = new SecretsConfigProperties(true, Map.of(), List.of(), - List.of(), true, SECRET_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, - ReadType.BATCH); + true, SECRET_NAME, NAMESPACE, false, true, true, RetryProperties.DEFAULT, ReadType.BATCH); KubernetesNamespaceProvider namespaceProvider = new KubernetesNamespaceProvider(mockEnvironment); PropertySource propertySource = new VisibleFabric8SecretsPropertySourceLocator(kubernetesClient, @@ -183,8 +182,8 @@ ConfigReloadProperties configReloadProperties() { @Bean @Primary SecretsConfigProperties secretsConfigProperties() { - return new SecretsConfigProperties(true, Map.of(), List.of(), List.of(), true, SECRET_NAME, NAMESPACE, - false, true, FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); + return new SecretsConfigProperties(true, Map.of(), List.of(), true, SECRET_NAME, NAMESPACE, false, true, + FAIL_FAST, RetryProperties.DEFAULT, ReadType.BATCH); } @Bean diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/App.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/App.java index 0024e25254..357d5ffbb8 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/App.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/App.java @@ -25,7 +25,7 @@ */ @SpringBootApplication @EnableConfigurationProperties({ LeftProperties.class, RightProperties.class, RightWithLabelsProperties.class, - ConfigMapProperties.class, SecretProperties.class }) + ConfigMapProperties.class, SecretProperties.class, ConfigMapNoMountProperties.class }) public class App { public static void main(String[] args) { diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountSecretPropertySource.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapNoMountProperties.java similarity index 65% rename from spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountSecretPropertySource.java rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapNoMountProperties.java index b07c1f0311..b1375ea771 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/MountSecretPropertySource.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapNoMountProperties.java @@ -14,15 +14,21 @@ * limitations under the License. */ -package org.springframework.cloud.kubernetes.commons.config; +package org.springframework.cloud.kubernetes.fabric8.client.reload; -/** - * @author wind57 - */ -public final class MountSecretPropertySource extends SecretsPropertySource { +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("props") +public class ConfigMapNoMountProperties { + + private String key; + + public String getKey() { + return key; + } - public MountSecretPropertySource(SourceData sourceData) { - super(sourceData); + public void setKey(String key) { + this.key = key; } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapProperties.java index 39c7f11c13..34b0d3a470 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapProperties.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/java/org/springframework/cloud/kubernetes/fabric8/client/reload/ConfigMapProperties.java @@ -30,8 +30,8 @@ String getKey() { return key; } - void setKey(String key1) { - this.key = key1; + void setKey(String key) { + this.key = key; } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-configtree.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-configtree.yaml new file mode 100644 index 0000000000..5e7e8c0983 --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-configtree.yaml @@ -0,0 +1,16 @@ +spring: + application: + name: poll-reload + config: + import: "kubernetes:,configtree:/tmp/" + +management: + endpoint: + refresh: + access: unrestricted + restart: + access: unrestricted + endpoints: + web: + exposure: + include: '*' diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-mount.yaml deleted file mode 100644 index 2edaa955b0..0000000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-mount.yaml +++ /dev/null @@ -1,16 +0,0 @@ -spring: - application: - name: poll-reload-mount - cloud: - kubernetes: - reload: - enabled: true - monitoring-config-maps: true - strategy: refresh - mode: polling - period: 5s - config: - paths: - - /tmp/application.properties - config: - import: "kubernetes:" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml index 2b083c7ed3..72f6a44c1e 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-three.yaml @@ -1,7 +1,3 @@ -logging: - level: - root: DEBUG - spring: application: name: event-reload diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-bootstrap.yaml deleted file mode 100644 index 2f71477613..0000000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/application-with-bootstrap.yaml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - application: - name: poll-reload-mount-boostrap - cloud: - kubernetes: - reload: - enabled: true - monitoring-config-maps: true - strategy: refresh - mode: polling - period: 5s - diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml deleted file mode 100644 index 0aed2eb9dd..0000000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - cloud: - kubernetes: - config: - paths: - - /tmp/application.properties diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingReloadIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapConfigTreeIT.java similarity index 61% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingReloadIT.java rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapConfigTreeIT.java index cd6037f928..56747ee322 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingReloadIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapConfigTreeIT.java @@ -18,17 +18,17 @@ import java.io.InputStream; import java.time.Duration; +import java.util.HashMap; import java.util.Map; +import java.util.Optional; import io.fabric8.kubernetes.api.model.ConfigMap; -import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.utils.Serialization; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.testcontainers.k3s.K3sContainer; -import org.springframework.cloud.kubernetes.commons.config.Constants; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; @@ -44,58 +44,54 @@ /** * @author wind57 */ -class Fabric8ConfigMapMountPollingReloadIT { +class Fabric8ConfigMapConfigTreeIT { private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-reload"; + private static final String CONFIGURATION_WATCHER_IMAGE_NAME = "spring-cloud-kubernetes-configuration-watcher"; + private static final String NAMESPACE = "default"; private static final K3sContainer K3S = Commons.container(); private static Util util; - private static KubernetesClient client; - @BeforeAll static void beforeAll() throws Exception { K3S.start(); Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); + Commons.validateImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + Commons.loadSpringCloudKubernetesImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + util = new Util(K3S); - client = util.client(); util.setUp(NAMESPACE); manifests(Phase.CREATE, util, NAMESPACE); + util.configWatcher(Phase.CREATE); } @AfterAll static void afterAll() { manifests(Phase.DELETE, util, NAMESPACE); + util.configWatcher(Phase.DELETE); } /** *
-	 *     - we have "spring.config.import: kubernetes", which means we will 'locate' property sources
+	 *     - we have "spring.config.import: kubernetes:,configtree:/tmp/", which means we will 'locate' property sources
 	 *       from config maps.
 	 *     - the property above means that at the moment we will be searching for config maps that only
 	 *       match the application name, in this specific test there is no such config map.
-	 *     - what we will also read, is 'spring.cloud.kubernetes.config.paths', which we have set to
-	 *     	 '/tmp/application.properties'
-	 *       in this test. That is populated by the volumeMounts (see deployment-mount.yaml)
-	 *     - we first assert that we are actually reading the path based source via (1), (2) and (3).
+	 *     - what we will also read, is /tmp directory according to configtree rules.
+	 *       As such, a property "props.key" will be in environment.
 	 *
-	 *     - we then change the config map content, wait for k8s to pick it up and replace them
-	 *     - our polling will then detect that change, and trigger a reload.
+	 *     - we then change the config map content, wait for configuration watcher to pick up the change
+	 *       and schedule a refresh event, based on http.
 	 * 
*/ @Test void test() { - // (1) - Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", K3S, IMAGE_NAME); - // (2) - Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", K3S, - IMAGE_NAME); - // (3) WebClient webClient = builder().baseUrl("http://localhost:32321/key").build(); String result = webClient.method(HttpMethod.GET) .retrieve() @@ -106,17 +102,26 @@ void test() { // we first read the initial value from the configmap assertThat(result).isEqualTo("as-mount-initial"); - // replace data in configmap and wait for k8s to pick it up - // our polling will detect that and restart the app - InputStream configMapStream = util.inputStream("manifests/configmap.yaml"); - ConfigMap configMap = Serialization.unmarshal(configMapStream, ConfigMap.class); - configMap.setData(Map.of(Constants.APPLICATION_PROPERTIES, "from.properties.key=as-mount-changed")); - client.configMaps().inNamespace("default").resource(configMap).createOrReplace(); - - Commons.waitForLogStatement("Detected change in config maps/secrets, reload will be triggered", K3S, - IMAGE_NAME); - - await().atMost(Duration.ofSeconds(120)) + // replace data in configmap and wait for configuration watcher to pick it up. + InputStream configMapConfigTreeStream = util.inputStream("manifests/configmap-configtree.yaml"); + ConfigMap configMapConfigTree = Serialization.unmarshal(configMapConfigTreeStream, ConfigMap.class); + configMapConfigTree.setData(Map.of("from.properties.key", "as-mount-changed")); + // add label so that configuration-watcher picks this up + Map existingLabels = new HashMap<>( + Optional.ofNullable(configMapConfigTree.getMetadata().getLabels()).orElse(new HashMap<>())); + existingLabels.put("spring.cloud.kubernetes.config", "true"); + configMapConfigTree.getMetadata().setLabels(existingLabels); + + // add app annotation + Map existingAnnotations = new HashMap<>( + Optional.ofNullable(configMapConfigTree.getMetadata().getAnnotations()).orElse(new HashMap<>())); + existingAnnotations.put("spring.cloud.kubernetes.configmap.apps", + "spring-cloud-kubernetes-fabric8-client-reload"); + configMapConfigTree.getMetadata().setAnnotations(existingAnnotations); + + util.client().configMaps().resource(configMapConfigTree).createOrReplace(); + + await().atMost(Duration.ofSeconds(180)) .pollInterval(Duration.ofSeconds(1)) .until(() -> webClient.method(HttpMethod.GET) .retrieve() diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingBootstrapIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingBootstrapIT.java deleted file mode 100644 index e369c05306..0000000000 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/Fabric8ConfigMapMountPollingBootstrapIT.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2013-present 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.client.reload; - -import java.io.InputStream; -import java.time.Duration; -import java.util.Map; - -import io.fabric8.kubernetes.api.model.ConfigMap; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.utils.Serialization; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.testcontainers.k3s.K3sContainer; - -import org.springframework.cloud.kubernetes.commons.config.Constants; -import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; -import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; -import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util; -import org.springframework.http.HttpMethod; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.manifests; -import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.builder; -import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.retrySpec; - -/** - * @author wind57 - */ -class Fabric8ConfigMapMountPollingBootstrapIT { - - private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-reload"; - - private static final String NAMESPACE = "default"; - - private static final K3sContainer K3S = Commons.container(); - - private static Util util; - - private static KubernetesClient client; - - @BeforeAll - static void beforeAll() throws Exception { - K3S.start(); - Commons.validateImage(IMAGE_NAME, K3S); - Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - - util = new Util(K3S); - client = util.client(); - util.setUp(NAMESPACE); - manifests(Phase.CREATE, util, NAMESPACE); - } - - @AfterAll - static void afterAll() { - manifests(Phase.DELETE, util, NAMESPACE); - } - - /** - *
-	 *     - we have bootstrap enabled, which means we will 'locate' property sources
-	 *       from config maps.
-	 *     - there are no explicit config maps to search for, but what we will also read,
-	 *     	 is 'spring.cloud.kubernetes.config.paths', which we have set to
-	 *     	 '/tmp/application.properties'
-	 *       in this test. That is populated by the volumeMounts (see deployment-mount.yaml)
-	 *     - we first assert that we are actually reading the path based source via (1), (2) and (3).
-	 *
-	 *     - we then change the config map content, wait for k8s to pick it up and replace them
-	 *     - our polling will then detect that change, and trigger a reload.
-	 * 
- */ - @Test - void test() { - // (1) - Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", K3S, IMAGE_NAME); - // (2) - Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", K3S, - IMAGE_NAME); - // (3) - WebClient webClient = builder().baseUrl("http://localhost:32321/key").build(); - String result = webClient.method(HttpMethod.GET) - .retrieve() - .bodyToMono(String.class) - .retryWhen(retrySpec()) - .block(); - - // we first read the initial value from the configmap - assertThat(result).isEqualTo("as-mount-initial"); - - // replace data in configmap and wait for k8s to pick it up - // our polling will detect that and restart the app - InputStream configMapStream = util.inputStream("manifests/configmap.yaml"); - ConfigMap configMap = Serialization.unmarshal(configMapStream, ConfigMap.class); - configMap.setData(Map.of(Constants.APPLICATION_PROPERTIES, "from.properties.key=as-mount-changed")); - client.configMaps().inNamespace("default").resource(configMap).createOrReplace(); - - System.out.println("Waiting for reload change to be observed"); - Commons.waitForLogStatement("Detected change in config maps/secrets, reload will be triggered", K3S, - IMAGE_NAME); - System.out.println("reload change observed"); - - await().atMost(Duration.ofSeconds(120)) - .pollInterval(Duration.ofSeconds(1)) - .until(() -> webClient.method(HttpMethod.GET) - .retrieve() - .bodyToMono(String.class) - .retryWhen(retrySpec()) - .block() - .equals("as-mount-changed")); - } - -} diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/TestAssertions.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/TestAssertions.java index 92c84f1df1..cafa48d756 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/TestAssertions.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/java/org/springframework/cloud/kubernetes/fabric8/client/reload/TestAssertions.java @@ -89,7 +89,7 @@ static void manifests(Phase phase, Util util, String namespace) { InputStream deploymentStream = util.inputStream("manifests/deployment.yaml"); InputStream serviceStream = util.inputStream("manifests/service.yaml"); - InputStream configMapAsStream = util.inputStream("manifests/configmap.yaml"); + InputStream configMapAsStream = util.inputStream("manifests/configmap-configtree.yaml"); Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class); diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/configmap-configtree.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/configmap-configtree.yaml new file mode 100644 index 0000000000..3bbd98796f --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/configmap-configtree.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: poll-reload-configtree + namespace: default +data: + from.properties.key: "as-mount-initial" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/deployment.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/deployment.yaml index a430c69bf2..ae5d51f519 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/deployment.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-client-reload/src/test/resources/manifests/deployment.yaml @@ -30,9 +30,7 @@ spec: - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_FABRIC8_CONFIG_RELOAD value: "DEBUG" - name: SPRING_PROFILES_ACTIVE - value: "with-bootstrap" - - name: SPRING_CLOUD_BOOTSTRAP_ENABLED - value: "TRUE" + value: "configtree" - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG value: "DEBUG" @@ -44,4 +42,4 @@ spec: - name: "config-map-volume" configMap: defaultMode: 420 - name: "poll-reload" + name: "poll-reload-configtree" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/java/org/springframework/cloud/kubernetes/k8s/client/reload/ConfigMapProperties.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/java/org/springframework/cloud/kubernetes/k8s/client/reload/ConfigMapProperties.java index 3887708414..389bee207c 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/java/org/springframework/cloud/kubernetes/k8s/client/reload/ConfigMapProperties.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/java/org/springframework/cloud/kubernetes/k8s/client/reload/ConfigMapProperties.java @@ -22,16 +22,16 @@ * @author wind57 */ @ConfigurationProperties("from.properties.configmap") -public class ConfigMapProperties { +class ConfigMapProperties { private String key; - public String getKey() { + String getKey() { return key; } - public void setKey(String key1) { - this.key = key1; + void setKey(String key) { + this.key = key; } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-mount.yaml index ab5b15fad7..d47d8012a6 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-mount.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-mount.yaml @@ -1,18 +1,16 @@ spring: application: - name: poll-reload - cloud: - kubernetes: - reload: - enabled: true - monitoring-config-maps: true - strategy: shutdown - mode: polling - period: 5000 - config: - paths: - - /tmp/application.properties - + name: poll-reload-mount config: - import: "kubernetes:" + import: "kubernetes:,configtree:/tmp/" +management: + endpoint: + refresh: + access: unrestricted + restart: + access: unrestricted + endpoints: + web: + exposure: + include: '*' diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-bootstrap.yaml index 9002bcf66c..f79cbc8385 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-bootstrap.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-bootstrap.yaml @@ -1,11 +1,14 @@ spring: application: name: poll-reload-mount-boostrap - cloud: - kubernetes: - reload: - enabled: true - strategy: refresh - mode: polling - period: 5000 - monitoring-secrets: true + +management: + endpoint: + refresh: + access: unrestricted + restart: + access: unrestricted + endpoints: + web: + exposure: + include: '*' diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml index 2208fa1ad3..34b03786b2 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/application-with-secret.yaml @@ -1,10 +1,3 @@ -logging: - level: - org: - springframework: - cloud: - kubernetes: debug - spring: application: name: event-reload diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml index 8808c39e78..efca193f3e 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/main/resources/bootstrap-with-bootstrap.yaml @@ -2,11 +2,9 @@ spring: cloud: kubernetes: secrets: - paths: - # at the moment, we do not support reading properties/yaml/yml - # files when mounting via 'paths' - - /tmp/from.properties.secret.key enabled: true - config: enabled: false + + config: + import: "file:/tmp/application.properties" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapMountPollingIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapConfigTreeIT.java similarity index 50% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapMountPollingIT.java rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapConfigTreeIT.java index 9e70911fe8..b5f736c3ec 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapMountPollingIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientConfigMapConfigTreeIT.java @@ -17,20 +17,19 @@ package org.springframework.cloud.kubernetes.k8s.client.reload.it; import java.time.Duration; +import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.V1ConfigMap; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.testcontainers.k3s.K3sContainer; -import org.springframework.cloud.kubernetes.commons.config.Constants; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; -import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.web.reactive.function.client.WebClient; @@ -42,17 +41,13 @@ /** * @author wind57 */ -class K8sClientConfigMapMountPollingIT extends K8sClientReloadBase { +class K8sClientConfigMapConfigTreeIT extends K8sClientReloadBase { private static final String IMAGE_NAME = "spring-cloud-kubernetes-k8s-client-reload"; - private static final String NAMESPACE = "default"; - - private static final K3sContainer K3S = Commons.container(); + private static final String CONFIGURATION_WATCHER_IMAGE_NAME = "spring-cloud-kubernetes-configuration-watcher"; - private static Util util; - - private static CoreV1Api coreV1Api; + private static final String NAMESPACE = "default"; @BeforeAll static void beforeAllLocal() throws Exception { @@ -60,41 +55,35 @@ static void beforeAllLocal() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - util = new Util(K3S); - coreV1Api = new CoreV1Api(); + Commons.validateImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + Commons.loadSpringCloudKubernetesImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + util.setUp(NAMESPACE); manifests(Phase.CREATE, util, NAMESPACE, IMAGE_NAME); + util.configWatcher(Phase.CREATE); } @AfterAll static void afterAll() { manifests(Phase.DELETE, util, NAMESPACE, IMAGE_NAME); + util.configWatcher(Phase.DELETE); } /** *
-	 *     - we have bootstrap disabled
-	 *     - we will 'locate' property sources from config maps.
-	 *     - there are no explicit config maps to search for, but what we will also read,
-	 *     	 is 'spring.cloud.kubernetes.config.paths', which we have set to
-	 *     	 '/tmp/application.properties'
-	 *       in this test. That is populated by the volumeMounts (see mount/deployment.yaml)
-	 *     - we first assert that we are actually reading the path based source via (1), (2) and (3).
+	 *     - we have "spring.config.import: kubernetes:,configtree:/tmp/", which means we will 'locate' property sources
+	 *       from config maps.
+	 *     - the property above means that at the moment we will be searching for config maps that only
+	 *       match the application name, in this specific test there is no such config map.
+	 *     - what we will also read, is /tmp directory according to configtree rules.
+	 *       As such, a property "props.key" will be in environment.
 	 *
-	 *     - we then change the config map content, wait for k8s to pick it up and replace them
-	 *     - our polling will then detect that change, and trigger a reload.
+	 *     - we then change the config map content, wait for configuration watcher to pick up the change
+	 *       and schedule a refresh event, based on http.
 	 * 
*/ @Test - // TODO This fails intermittently on Jenkins - @Disabled - void test() throws Exception { - // (1) - Commons.waitForLogStatement("paths property sources : [/tmp/application.properties]", K3S, IMAGE_NAME); - // (2) - Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", K3S, - IMAGE_NAME); - // (3) + void test() throws ApiException { WebClient webClient = builder().baseUrl("http://localhost:32321/configmap").build(); String result = webClient.method(HttpMethod.GET) .retrieve() @@ -105,23 +94,34 @@ void test() throws Exception { // we first read the initial value from the configmap assertThat(result).isEqualTo("as-mount-initial"); - // replace data in configmap and wait for k8s to pick it up - // our polling will detect that and restart the app - V1ConfigMap configMap = (V1ConfigMap) util.yaml("mount/configmap.yaml"); - configMap.setData(Map.of(Constants.APPLICATION_PROPERTIES, "from.properties.configmap.key=as-mount-changed")); - coreV1Api.replaceNamespacedConfigMap("configmap-reload", NAMESPACE, configMap).execute(); - - Commons.waitForLogStatement("Detected change in config maps/secrets, reload will be triggered", K3S, - IMAGE_NAME); - - await().atMost(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(1)).until(() -> { - String local = webClient.method(HttpMethod.GET) + // replace data in configmap and wait for configuration watcher to pick it up. + V1ConfigMap configMapConfigTree = (V1ConfigMap) util.yaml("mount/configmap.yaml"); + configMapConfigTree.setData(Map.of("from.properties.configmap.key", "as-mount-changed")); + // add label so that configuration-watcher picks this up + Map existingLabels = new HashMap<>( + Optional.ofNullable(configMapConfigTree.getMetadata().getLabels()).orElse(new HashMap<>())); + existingLabels.put("spring.cloud.kubernetes.config", "true"); + configMapConfigTree.getMetadata().setLabels(existingLabels); + + // add app annotation + Map existingAnnotations = new HashMap<>( + Optional.ofNullable(configMapConfigTree.getMetadata().getAnnotations()).orElse(new HashMap<>())); + existingAnnotations.put("spring.cloud.kubernetes.configmap.apps", IMAGE_NAME); + configMapConfigTree.getMetadata().setAnnotations(existingAnnotations); + + new CoreV1Api() + .replaceNamespacedConfigMap(configMapConfigTree.getMetadata().getName(), + configMapConfigTree.getMetadata().getNamespace(), configMapConfigTree) + .execute(); + + await().atMost(Duration.ofSeconds(180)) + .pollInterval(Duration.ofSeconds(1)) + .until(() -> webClient.method(HttpMethod.GET) .retrieve() .bodyToMono(String.class) .retryWhen(retrySpec()) - .block(); - return "as-mount-changed".equals(local); - }); + .block() + .equals("as-mount-changed")); } } diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretMountBootstrapPollingIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretConfigTreeIT.java similarity index 59% rename from spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretMountBootstrapPollingIT.java rename to spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretConfigTreeIT.java index 94419ab891..7c90ced9e9 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretMountBootstrapPollingIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/java/org/springframework/cloud/kubernetes/k8s/client/reload/it/K8sClientSecretConfigTreeIT.java @@ -18,18 +18,18 @@ import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.HashMap; import java.util.Map; +import java.util.Optional; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.V1Secret; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.testcontainers.k3s.K3sContainer; import org.springframework.cloud.kubernetes.integration.tests.commons.Commons; import org.springframework.cloud.kubernetes.integration.tests.commons.Phase; -import org.springframework.cloud.kubernetes.integration.tests.commons.native_client.Util; import org.springframework.http.HttpMethod; import org.springframework.web.reactive.function.client.WebClient; @@ -41,17 +41,13 @@ /** * @author wind57 */ -class K8sClientSecretMountBootstrapPollingIT extends K8sClientReloadBase { +class K8sClientSecretConfigTreeIT extends K8sClientReloadBase { private static final String IMAGE_NAME = "spring-cloud-kubernetes-k8s-client-reload"; - private static final String NAMESPACE = "default"; - - private static final K3sContainer K3S = Commons.container(); + private static final String CONFIGURATION_WATCHER_IMAGE_NAME = "spring-cloud-kubernetes-configuration-watcher"; - private static Util util; - - private static CoreV1Api coreV1Api; + private static final String NAMESPACE = "default"; @BeforeAll static void beforeAllLocal() throws Exception { @@ -59,29 +55,31 @@ static void beforeAllLocal() throws Exception { Commons.validateImage(IMAGE_NAME, K3S); Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S); - util = new Util(K3S); - coreV1Api = new CoreV1Api(); + Commons.validateImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + Commons.loadSpringCloudKubernetesImage(CONFIGURATION_WATCHER_IMAGE_NAME, K3S); + util.setUp(NAMESPACE); manifestsSecret(Phase.CREATE, util, NAMESPACE, IMAGE_NAME); + util.configWatcher(Phase.CREATE); } @AfterAll static void afterAll() { manifestsSecret(Phase.DELETE, util, NAMESPACE, IMAGE_NAME); + util.configWatcher(Phase.DELETE); } /** *
-	 *     - we have bootstrap enabled
-	 *     - we will 'locate' property sources from secrets.
-	 *     - there are no explicit secrets to search for, but what we will also read,
-	 *     	 is 'spring.cloud.kubernetes.secret.paths', which we have set to
-	 *     	 '/tmp/application.properties'
-	 *       in this test. That is populated by the volumeMounts (see mount/deployment-with-secret.yaml)
-	 *     - we first assert that we are actually reading the path based source
+	 *     - we have "spring.config.import: kubernetes:,configtree:/tmp/", which means we will 'locate' property sources
+	 *       from secrets.
+	 *     - the property above means that at the moment we will be searching for secrets that only
+	 *       match the application name, in this specific test there is no such secrets.
+	 *     - what we will also read, is /tmp directory according to configtree rules.
+	 *       As such, a property "props.key" will be in environment.
 	 *
-	 *     - we then change the secret content, wait for k8s to pick it up and replace them
-	 *     - our polling will then detect that change, and trigger a reload.
+	 *     - we then change the config map content, wait for configuration watcher to pick up the change
+	 *       and schedule a refresh event, based on http.
 	 * 
*/ @Test @@ -99,13 +97,24 @@ void test() throws Exception { // replace data in secret and wait for k8s to pick it up // our polling will detect that and restart the app V1Secret secret = (V1Secret) util.yaml("mount/secret.yaml"); - secret.setData(Map.of("from.properties.secret.key", "as-mount-changed".getBytes(StandardCharsets.UTF_8))); - coreV1Api.replaceNamespacedSecret("secret-reload", NAMESPACE, secret).execute(); + secret.setData(Map.of("application.properties", + "from.properties.secret.key=as-mount-changed".getBytes(StandardCharsets.UTF_8))); + + // add label so that configuration-watcher picks this up + Map existingLabels = new HashMap<>( + Optional.ofNullable(secret.getMetadata().getLabels()).orElse(new HashMap<>())); + existingLabels.put("spring.cloud.kubernetes.secret", "true"); + secret.getMetadata().setLabels(existingLabels); + + // add app annotation + Map existingAnnotations = new HashMap<>( + Optional.ofNullable(secret.getMetadata().getAnnotations()).orElse(new HashMap<>())); + existingAnnotations.put("spring.cloud.kubernetes.secret.apps", IMAGE_NAME); + secret.getMetadata().setAnnotations(existingAnnotations); - Commons.waitForLogStatement("Detected change in config maps/secrets, reload will be triggered", K3S, - IMAGE_NAME); + new CoreV1Api().replaceNamespacedSecret("secret-reload", NAMESPACE, secret).execute(); - await().atMost(Duration.ofSeconds(120)) + await().atMost(Duration.ofSeconds(180)) .pollInterval(Duration.ofSeconds(1)) .until(() -> webClient.method(HttpMethod.GET) .retrieve() diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/configmap-mount.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/configmap-mount.yaml new file mode 100644 index 0000000000..e0cf495c6c --- /dev/null +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/configmap-mount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: poll-reload-as-mount + namespace: default +data: + from.properties: "as-mount-initial" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/configmap.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/configmap.yaml index d6b8885fb3..141dbf02cf 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/configmap.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/configmap.yaml @@ -4,5 +4,4 @@ metadata: name: configmap-reload # different from the application name namespace: default data: - application.properties: | - from.properties.configmap.key=as-mount-initial + from.properties.configmap.key: "as-mount-initial" diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/secret.yaml b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/secret.yaml index 7f0084b352..ba33adaac5 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/secret.yaml +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-reload/src/test/resources/mount/secret.yaml @@ -5,4 +5,5 @@ metadata: namespace: default data: # from.properties.secret.key=initial - from.properties.secret.key: aW5pdGlhbA== + application.properties: + ZnJvbS5wcm9wZXJ0aWVzLnNlY3JldC5rZXk6IGluaXRpYWw= diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java index 9de5e03da2..d28563b8af 100644 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/fabric8_client/Util.java @@ -330,6 +330,22 @@ public void wiremock(String namespace, Phase phase, boolean withNodePort) { } + public void configWatcher(Phase phase) { + + InputStream deploymentStream = inputStream("config-watcher/deployment.yaml"); + InputStream serviceStream = inputStream("config-watcher/service.yaml"); + + Deployment deployment = client.apps().deployments().load(deploymentStream).item(); + Service service = client.services().load(serviceStream).item(); + + if (phase.equals(Phase.CREATE)) { + createAndWait("default", deployment.getMetadata().getName(), deployment, service, true); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait("default", deployment, service); + } + } + private void waitForSecret(String namespace, Secret secret, Phase phase) { String secretName = secretName(secret); await().pollInterval(Duration.ofSeconds(1)).atMost(600, TimeUnit.SECONDS).until(() -> { diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java index 47b59ba3bd..4b4bdea229 100644 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/native_client/Util.java @@ -445,6 +445,19 @@ public void wiremock(String namespace, Phase phase, boolean withNodePort) { } + public void configWatcher(Phase phase) { + + V1Deployment deployment = (V1Deployment) yaml("config-watcher/deployment.yaml"); + V1Service service = (V1Service) yaml("config-watcher/service.yaml"); + + if (phase.equals(Phase.CREATE)) { + createAndWait("default", deployment.getMetadata().getName(), deployment, service, true); + } + else if (phase.equals(Phase.DELETE)) { + deleteAndWait("default", deployment, service); + } + } + private String deploymentName(V1Deployment deployment) { return deployment.getMetadata().getName(); } diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/deployment.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/deployment.yaml new file mode 100644 index 0000000000..5363b4966c --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-cloud-kubernetes-configuration-watcher-deployment +spec: + selector: + matchLabels: + app: spring-cloud-kubernetes-configuration-watcher + template: + metadata: + labels: + app: spring-cloud-kubernetes-configuration-watcher + spec: + serviceAccountName: spring-cloud-kubernetes-serviceaccount + containers: + - name: spring-cloud-kubernetes-configuration-watcher + image: docker.io/springcloud/spring-cloud-kubernetes-configuration-watcher + imagePullPolicy: IfNotPresent + readinessProbe: + httpGet: + port: 8888 + path: /actuator/health/readiness + livenessProbe: + httpGet: + port: 8888 + path: /actuator/health/liveness + ports: + - containerPort: 8888 + env: + - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CONFIGURATION_WATCHER + value: DEBUG + - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_CLIENT_CONFIG_RELOAD + value: DEBUG + - name: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_CLOUD_KUBERNETES_COMMONS_CONFIG_RELOAD + value: DEBUG + - name: SPRING_CLOUD_KUBERNETES_CONFIGURATION_WATCHER_REFRESHDELAY + value: "120000" diff --git a/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/service.yaml b/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/service.yaml new file mode 100644 index 0000000000..c8496317b1 --- /dev/null +++ b/spring-cloud-kubernetes-test-support/src/main/resources/config-watcher/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: spring-cloud-kubernetes-configuration-watcher + name: spring-cloud-kubernetes-configuration-watcher +spec: + ports: + - name: http + port: 8888 + targetPort: 8888 + selector: + app: spring-cloud-kubernetes-configuration-watcher + type: ClusterIP