From c019cfa451279dd3e16bba347c71ca65c348edf0 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Thu, 16 Jun 2022 03:41:19 +0000 Subject: [PATCH] Bumping versions --- README.adoc | 121 ++++++++++++++++-- docs/src/main/asciidoc/_configprops.adoc | 1 + .../watcher/ActuatorRefreshIT.java | 3 +- .../integration/tests/commons/K8SUtils.java | 4 +- 4 files changed, 116 insertions(+), 13 deletions(-) diff --git a/README.adoc b/README.adoc index 26d66826..26174ccf 100644 --- a/README.adoc +++ b/README.adoc @@ -245,18 +245,30 @@ an `application-profile.properties` or `application-profile.yaml` file that cont application or Spring Boot starters. You can override these properties by specifying system properties or environment variables. +To enable this functionality you need to set `spring.config.import=kubernetes:` in your application's configuration properties. +Currently you can not specify a ConfigMap or Secret to load using `spring.config.import`, by default Spring Cloud Kubernetes +will load a ConfigMap and/or Secret based on the `spring.application.name` property. If `spring.application.name` is not set it will +load a ConfigMap and/or Secret with the name `application`. + +If you would like to load Kubernetes `PropertySource`s during the bootstrap phase like it worked prior to the 3.0.x release +you can either add `spring-cloud-starter-bootstrap` to your application's classpath or set `spring.cloud.bootstrap.enabled=true` +as an environment variable. + [[configmap-propertysource]] === Using a `ConfigMap` `PropertySource` Kubernetes provides a resource named https://kubernetes.io/docs/user-guide/configmap/[`ConfigMap`] to externalize the parameters to pass to your application in the form of key-value pairs or embedded `application.properties` or `application.yaml` files. The link:https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-fabric8-config[Spring Cloud Kubernetes Config] project makes Kubernetes `ConfigMap` instances available -during application bootstrapping and triggers hot reloading of beans or Spring context when changes are detected on +during application startup and triggers hot reloading of beans or Spring context when changes are detected on observed `ConfigMap` instances. -The default behavior is to create a `Fabric8ConfigMapPropertySource` based on a Kubernetes `ConfigMap` that has a `metadata.name` value of either the name of +Everything that follows is explained mainly referring to examples using ConfigMaps, but the same stands for +Secrets, i.e.: every feature is supported for both. + +The default behavior is to create a `Fabric8ConfigMapPropertySource` (or a `KubernetesClientConfigMapPropertySource`) based on a Kubernetes `ConfigMap` that has a `metadata.name` value of either the name of your Spring application (as defined by its `spring.application.name` property) or a custom name defined within the -`bootstrap.properties` file under the following key: `spring.cloud.kubernetes.config.name`. +`application.properties` file under the following key: `spring.cloud.kubernetes.config.name`. However, more advanced configuration is possible where you can use multiple `ConfigMap` instances. The `spring.cloud.kubernetes.config.sources` list makes this possible. @@ -366,6 +378,31 @@ data: ---- ==== +You can also define the search to happen based on labels, for example: + + +==== +[source,yaml] +---- +spring: + application: + name: labeled-configmap-with-prefix + cloud: + kubernetes: + config: + enableApi: true + useNameAsPrefix: true + namespace: spring-k8s + sources: + - labels: + letter: a +---- +==== + +This will search for every configmap in namespace `spring-k8s` that has labels `{letter : a}`. The important +thing to notice here is that unlike reading a configmap by name, this can result in _multiple_ config maps read. +As usual, the same feature is supported for secrets. + You can also configure Spring Boot applications differently depending on active profiles that are merged together when the `ConfigMap` is read. You can provide different property values for different profiles by using an `application.properties` or `application.yaml` property, specifying profile-specific values, each in their own document @@ -479,8 +516,8 @@ data: ==== -To tell Spring Boot which `profile` should be enabled at bootstrap, you can pass `SPRING_PROFILES_ACTIVE` environment variable. - To do so, you can launch your Spring Boot application with an environment variable that you can define it in the PodSpec at the container specification. +To tell Spring Boot which `profile` should be enabled see the https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles[Spring Boot documentation]. +One option for activating a specific profile when deploying to Kubernetes is to launch your Spring Boot application with an environment variable that you can define in the PodSpec at the container specification. Deployment resource file, as follows: ==== @@ -640,6 +677,71 @@ will result in three properties being generated: - `config-map-three.greetings.message` equal to `Say Hello from three`. +The same way you configure a prefix for configmaps, you can do it for secrets also; both for secrets that are based on name +and the ones based on labels. For example: + +==== +[source.yaml] +---- +spring: + application: + name: prefix-based-secrets + cloud: + kubernetes: + secrets: + enableApi: true + useNameAsPrefix: true + namespace: spring-k8s + sources: + - labels: + letter: a + useNameAsPrefix: false + - labels: + letter: b + explicitPrefix: two + - labels: + letter: c + - labels: + letter: d + useNameAsPrefix: true + - name: my-secret +---- +==== + +The same processing rules apply when generating property source as for config maps. The only difference is that +potentially, looking up secrets by labels can mean that we find more than one source. In such a case, prefix (if specified via `useNameAsPrefix`) +will be the names of all secrets found for those particular labels. + +One more thing to bear in mind is that we support `prefix` per _source_, not per secret. The easiest way to explain this is via an example: + +==== +[source.yaml] +---- +spring: + application: + name: prefix-based-secrets + cloud: + kubernetes: + secrets: + enableApi: true + useNameAsPrefix: true + namespace: spring-k8s + sources: + - labels: + color: blue + useNameAsPrefix: true +---- +==== + +Suppose that a query matching such a label will provide two secrets as a result: `secret-a` and `secret-b`. +Both of these secrets have the same property name: `color=sea-blue` and `color=ocean-blue`. It is undefined which +`color` will end-up as part of property sources, but the prefix for it will be `secret-a.secret-b` +(concatenated sorted naturally, names of the secrets). + +If you need more fine-grained results, adding more labels to identify the secret uniquely would be an option. + + + By default, besides reading the config map that is specified in the `sources` configuration, Spring will also try to read all properties from "profile aware" sources. The easiest way to explain this is via an example. Let's suppose your application enables a profile called "dev" and you have a configuration like the one below: @@ -1102,10 +1204,11 @@ that setting via `spring.main.cloud-platform`. For example, if you need to test some features, but do not want to deploy to a cluster, it is enough to set the: `spring.main.cloud-platform=KUBERNETES`. This will make `spring-cloud-kubernetes` act as-if it is deployed in a real cluster. -Be aware that when `spring-cloud-kubernetes-config` is on the classpath, `spring.main.cloud-platform` should be set in `bootstrap.{properties|yml}` -(or the profile specific one), otherwise it should be in `application.{properties|yml}` (or the profile specific one). -Also note that these properties: `spring.cloud.kubernetes.config.enabled` and `spring.cloud.kubernetes.secrets.enabled` -only take effect when set in `bootstrap.{properties|yml}`. + +NOTE: If you have `spring-cloud-bootstrap-starter` on your classpath or are setting `spring.cloud.bootstrap.enabled=true` then +you will have to set `spring.main.cloud-platform` should be set in `bootstrap.{properties|yml}` +(or the profile specific one). Also note that these properties: `spring.cloud.kubernetes.config.enabled` and `spring.cloud.kubernetes.secrets.enabled` +will only take effect when set in `bootstrap.{properties|yml}` when you have `spring-cloud-bootstrap-starter` on your classpath or are setting `spring.cloud.bootstrap.enabled=true`. === Breaking Changes In 3.0.x diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 5043f759..7017f51a 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -51,6 +51,7 @@ |spring.cloud.kubernetes.config.enabled | `true` | Enable the ConfigMap property source locator. |spring.cloud.kubernetes.config.fail-fast | `false` | |spring.cloud.kubernetes.config.include-profile-specific-sources | `true` | +|spring.cloud.kubernetes.config.labels | | |spring.cloud.kubernetes.config.name | | |spring.cloud.kubernetes.config.namespace | | |spring.cloud.kubernetes.config.paths | | diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java index 63cddbc9..5e9af021 100644 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/ActuatorRefreshIT.java @@ -152,8 +152,7 @@ class ActuatorRefreshIT { private V1Deployment getConfigWatcherDeployment() throws Exception { V1Deployment deployment = (V1Deployment) K8SUtils.readYamlFromClasspath( "config-watcher/spring-cloud-kubernetes-configuration-watcher-http-deployment.yaml"); - String image = K8SUtils.getImageFromDeployment(deployment) + ":" - + getPomVersion(); + String image = K8SUtils.getImageFromDeployment(deployment) + ":" + getPomVersion(); deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image); return deployment; } diff --git a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java index 596a20f0..088a14b7 100644 --- a/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java +++ b/spring-cloud-kubernetes-test-support/src/main/java/org/springframework/cloud/kubernetes/integration/tests/commons/K8SUtils.java @@ -353,8 +353,8 @@ public class K8SUtils { } /** - * Gets the image from a Kubernetes Client deployment yaml. Assumes there is only one container - * defined in the deployment. + * Gets the image from a Kubernetes Client deployment yaml. Assumes there is only one + * container defined in the deployment. * @param deployment deployment yaml * @return An array where the first item is the mage name and the second item is the * tag