diff --git a/example/src/main/java/io/app/MyBean.java b/example/src/main/java/io/app/MyBean.java
deleted file mode 100644
index 76569e3d..00000000
--- a/example/src/main/java/io/app/MyBean.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.app;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-/**
- *
- */
-@Component
-@ConfigurationProperties(prefix = "bean")
-public class MyBean {
-
- private String message;
-
- @Scheduled(fixedDelay = 5000)
- public void hello() {
- System.out.println("The message is: " + message);
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
-}
diff --git a/example/src/main/resources/application.properties b/example/src/main/resources/application.properties
deleted file mode 100644
index 358fdac4..00000000
--- a/example/src/main/resources/application.properties
+++ /dev/null
@@ -1,9 +0,0 @@
-spring.application.name=example
-
-
-#spring.cloud.kubernetes.reload.strategy=refresh
-#spring.cloud.kubernetes.reload.mode=polling
-#spring.cloud.kubernetes.reload.period=2000
-#spring.cloud.kubernetes.reload.monitoring-config-maps=false
-#spring.cloud.kubernetes.reload.monitoring-secrets=true
-#spring.cloud.kubernetes.reload.enabled=true
diff --git a/pom.xml b/pom.xml
index 14e1fdf3..70b5d9a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,7 @@
1.4.14
0.0.4
1.16.8
+ 5.2.4.Final
2.5
1.0-groovy-2.3
1.4.1.RELEASE
@@ -90,6 +91,7 @@
3.5
2.19.1
+ 3.1.69
1.2
0.3.4
@@ -106,7 +108,7 @@
spring-cloud-starter-kubernetes-netflix
spring-cloud-starter-kubernetes-zipkin
spring-cloud-starter-kubernetes-all
- example
+ spring-cloud-kubernetes-examples
diff --git a/readme.md b/readme.md
index 58f20cda..88d340fb 100644
--- a/readme.md
+++ b/readme.md
@@ -11,6 +11,7 @@
- [PropertySource](#kubernetes-propertysource)
- [ConfigMap PropertySource](#configmap-propertysource)
- [Secrets PropertySource](#secrets-propertysource)
+ - [PropertySource Reload](#propertysource-reload)
- [Pod Health Indicator](#pod-health-indicator)
- [Transparency](#transparency) *(its transparent wether the code runs in or outside of Kubernetes)*
- [Kubernetes Profile Autoconfiguration](#kubernetes-profile-autoconfiguration)
@@ -199,13 +200,13 @@ You can select the Secrets to consume in a number of ways:
#### PropertySource Reload
Some applications may need to detect changes on external property sources and update their internal status to reflect the new configuration.
-The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when its related ConfigMap or Secret change.
+The reload feature of Spring Cloud Kubernetes is able to trigger an application reload when a related ConfigMap or Secret change.
This feature is disabled by default and can be enabled using the configuration property `spring.cloud.kubernetes.reload.enabled=true`
(eg. in the *application.properties* file).
The following levels of reload are supported (property `spring.cloud.kubernetes.reload.strategy`):
-- **refresh (default)**: only spring beans annotated with `@ConfigurationProperties` or `@RefreshScope` are reloaded.
+- **refresh (default)**: only configuration beans annotated with `@ConfigurationProperties` or `@RefreshScope` are reloaded.
This reload level leverages the refresh feature of Spring Cloud Context.
- **restart_context**: the whole Spring _ApplicationContext_ is gracefully restarted. Beans are recreated with the new configuration.
- **shutdown**: the Spring _ApplicationContext_ is shut down to activate a restart of the container.
@@ -214,8 +215,78 @@ This reload level leverages the refresh feature of Spring Cloud Context.
Example:
-Assuming that the reload feature is enabled with default settings, the following bean will be refreshed
+Assuming that the reload feature is enabled with default settings (*refresh* mode), the following bean will be refreshed when the config map changes:
+```java
+@Configuration
+@ConfigurationProperties(prefix = "bean")
+public class MyConfig {
+
+ private String message = "a message that can be changed live";
+
+ // getter and setters
+
+}
+```
+
+A way to see that changes effectively happen is creating another bean that prints the message periodically.
+
+```java
+@Component
+public class MyBean {
+
+ @Autowired
+ private MyConfig config;
+
+ @Scheduled(fixedDelay = 5000)
+ public void hello() {
+ System.out.println("The message is: " + config.getMessage());
+ }
+}
+```
+
+The message printed by the application can be changed using a config map like the following one:
+
+```yml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: reload-example
+data:
+ application.properties: |-
+ bean.message=Hello World!
+```
+
+Any change to the property named `bean.message` in the Config Map associated to the pod will be reflected in the output of the program
+(more details [here](#configmap-propertysource) about how to associate a Config Map to a pod).
+
+The full example is available in [spring-cloud-kubernetes-reload-example](spring-cloud-kubernetes-examples/spring-cloud-kubernetes-reload-example).
+
+The reload feature supports two operating modes:
+- **event (default)**: watches for changes in config maps or secrets using the Kubernetes API (web socket).
+Any event will produce a re-check on the configuration and a reload in case of changes.
+The `view` role on the service account is required in order to listen for config map changes. A higher level role (eg. `edit`) is required for secrets
+(secrets are not monitored by default).
+- **polling**: re-creates the configuration periodically from config maps and secrets to see if it has changed.
+The polling period can be configured using the property `spring.cloud.kubernetes.reload.period` and defaults to *15 seconds*.
+It requires the same role as the monitored property source.
+This means, for example, that using polling on file mounted secret sources does not require particular privileges.
+
+Properties:
+
+| Name | Type | Default | Description
+| --- | --- | --- | ---
+| spring.cloud.kubernetes.reload.enabled | Boolean | false | Enables monitoring of property sources and configuration reload
+| spring.cloud.kubernetes.reload.monitoring-config-maps | Boolean | true | Allow monitoring changes in config maps
+| spring.cloud.kubernetes.reload.monitoring-secrets | Boolean | false | Allow monitoring changes in secrets
+| spring.cloud.kubernetes.reload.strategy | Enum | refresh | The strategy to use when firing a reload (*refresh*, *restart_context*, *shutdown*)
+| spring.cloud.kubernetes.reload.mode | Enum | event | Specifies how to listen for changes in property sources (*event*, *polling*)
+| spring.cloud.kubernetes.reload.period | Long | 15000 | The period in milliseconds for verifying changes when using the *polling* strategy
+
+Notes:
+- Properties under *spring.cloud.kubernetes.reload.** should not be used in config maps or secrets: changing such properties at runtime may lead to unexpected results;
+- Deleting a property or the whole config map does not restore the original state of the beans when using the *refresh* level.
+
### Pod Health Indicator
diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/config-map.yml b/spring-cloud-kubernetes-examples/kubernetes-reload-example/config-map.yml
new file mode 100644
index 00000000..29be9bbe
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/config-map.yml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: reload-example
+data:
+ application.properties: |-
+ bean.message=Hello World!
+ another.property=value
\ No newline at end of file
diff --git a/example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml
similarity index 51%
rename from example/pom.xml
rename to spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml
index b782b635..71d3314d 100644
--- a/example/pom.xml
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml
@@ -3,14 +3,28 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- spring-cloud-kubernetes-project
+ spring-cloud-kubernetes-examples
io.fabric8
0.1-SNAPSHOT
4.0.0
- example
+ kubernetes-reload-example
+ Fabric8 :: Spring Cloud Kubernetes :: Examples :: Reload
+ Example demostrating how to use the configuration reload feature.
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ pom
+ import
+ ${spring-boot.version}
+
+
+
@@ -19,20 +33,29 @@
${project.version}
-
-
-
-
-
org.springframework.boot
spring-boot-starter
- 1.4.1.RELEASE
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-undertow
+
+
org.hibernate
hibernate-validator
- 5.2.4.Final
+ ${hibernate-validator.version}
@@ -42,7 +65,7 @@
io.fabric8
fabric8-maven-plugin
- 3.1.69
+ ${fabric8.maven.plugin.version}
diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/readme.md b/spring-cloud-kubernetes-examples/kubernetes-reload-example/readme.md
new file mode 100644
index 00000000..6c65369b
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/readme.md
@@ -0,0 +1,54 @@
+## Kubernetes Reload Example
+
+This example demonstrate how to use the reload feature to change the configuration of a spring-boot application at runtime.
+
+The application consists of a timed bean that periodically prints a message to the console.
+The message can be changed using a config map.
+
+### Running the example
+
+When using Openshift, you must assign the `view` role to the *default* service account in the current project:
+
+```
+oc policy add-role-to-user view --serviceaccount=default
+```
+
+You can deploy the application using the fabric8 maven plugin:
+
+```
+mvn clean install fabric8:deploy
+```
+
+### Changing the configuration
+
+Create a yaml file with the following contents:
+
+```yml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: reload-example
+data:
+ application.properties: |-
+ bean.message=Hello World!
+ another.property=value
+```
+
+A sample config map is provided with this example in the *config-map.yml* file.
+
+To deploy the config map, just run the following command:
+
+```
+oc create -f config-map.yml
+```
+
+As soon as the config map is deployed, the output of the application changes accordingly.
+The config map can be now edited with the following command:
+
+```
+oc edit configmap reload-example
+```
+
+Changes are applied immediately when using the *event* reload mode.
+
+The name of the config map (*"reload-example"*) matches the name of the application as declared in the *application.properties* file.
diff --git a/example/src/main/java/io/app/App.java b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/App.java
similarity index 66%
rename from example/src/main/java/io/app/App.java
rename to spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/App.java
index 306d88aa..480ab822 100644
--- a/example/src/main/java/io/app/App.java
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/App.java
@@ -1,12 +1,14 @@
-package io.app;
+package io.fabric8.spring.cloud.kubernetes.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
/**
*
*/
@SpringBootApplication
+@EnableScheduling
public class App {
public static void main(String[] args) {
diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyBean.java b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyBean.java
new file mode 100644
index 00000000..b735f7df
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyBean.java
@@ -0,0 +1,19 @@
+package io.fabric8.spring.cloud.kubernetes.examples;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MyBean {
+
+ @Autowired
+ private MyConfig config;
+
+ @Scheduled(fixedDelay = 5000)
+ public void hello() {
+ System.out.println("The message is: " + config.getMessage());
+ }
+
+
+}
diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyConfig.java b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyConfig.java
new file mode 100644
index 00000000..19fe9e82
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/java/io/fabric8/spring/cloud/kubernetes/examples/MyConfig.java
@@ -0,0 +1,20 @@
+package io.fabric8.spring.cloud.kubernetes.examples;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "bean")
+public class MyConfig {
+
+ private String message = "a message that can be changed live";
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+}
diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/resources/application.properties b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/resources/application.properties
new file mode 100644
index 00000000..ca0bfe4a
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+spring.application.name=reload-example
+
+spring.cloud.kubernetes.reload.enabled=true
+
+#spring.cloud.kubernetes.reload.strategy=restart_context
+#spring.cloud.kubernetes.reload.mode=polling
+#spring.cloud.kubernetes.reload.period=5000
+#spring.cloud.kubernetes.reload.monitoring-config-maps=false
+#spring.cloud.kubernetes.reload.monitoring-secrets=true
diff --git a/spring-cloud-kubernetes-examples/pom.xml b/spring-cloud-kubernetes-examples/pom.xml
new file mode 100644
index 00000000..5c2d0304
--- /dev/null
+++ b/spring-cloud-kubernetes-examples/pom.xml
@@ -0,0 +1,23 @@
+
+
+
+ spring-cloud-kubernetes-project
+ io.fabric8
+ 0.1-SNAPSHOT
+
+ 4.0.0
+
+ spring-cloud-kubernetes-examples
+ pom
+
+ Fabric8 :: Spring Cloud Kubernetes :: Examples
+ Examples showing how to use features of Spring Cloud Kubernetes.
+
+
+ kubernetes-reload-example
+
+
+
+
\ No newline at end of file