From e667b9db1feb160748465bc8d8d450014de8afc2 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 28 Aug 2020 19:58:09 +0000 Subject: [PATCH 01/13] Update SNAPSHOT to 1.1.6.RELEASE --- README.adoc | 29 +++++++++++++++++++ docs/pom.xml | 2 +- docs/src/main/asciidoc/_configprops.adoc | 4 +++ pom.xml | 10 +++---- spring-cloud-kubernetes-config/pom.xml | 2 +- spring-cloud-kubernetes-core/pom.xml | 2 +- .../KubernetesAutoConfigurationTests.java | 7 +++-- spring-cloud-kubernetes-dependencies/pom.xml | 4 +-- spring-cloud-kubernetes-discovery/pom.xml | 2 +- .../greeting-service/pom.xml | 2 +- .../name-service/pom.xml | 2 +- .../pom.xml | 2 +- .../kubernetes-hello-world-example/pom.xml | 2 +- .../pom.xml | 2 +- .../kubernetes-reload-example/pom.xml | 2 +- .../kubernetes-zipkin-example/pom.xml | 2 +- spring-cloud-kubernetes-examples/pom.xml | 2 +- .../discovery/discovery-client/pom.xml | 2 +- .../discovery/discovery-service-a/pom.xml | 2 +- .../discovery/discovery-service-b/pom.xml | 2 +- .../discovery/pom.xml | 2 +- .../discovery/tests/pom.xml | 2 +- .../istio/pom.xml | 2 +- .../load-balancer/pom.xml | 2 +- .../pom.xml | 2 +- .../simple-configmap/pom.xml | 2 +- .../simple-core/pom.xml | 2 +- spring-cloud-kubernetes-istio/pom.xml | 2 +- spring-cloud-kubernetes-leader/pom.xml | 2 +- spring-cloud-kubernetes-loadbalancer/pom.xml | 2 +- spring-cloud-kubernetes-ribbon/pom.xml | 2 +- spring-cloud-starter-kubernetes-all/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-starter-kubernetes/pom.xml | 2 +- 36 files changed, 75 insertions(+), 41 deletions(-) diff --git a/README.adoc b/README.adoc index 96b1230c..043d539a 100644 --- a/README.adoc +++ b/README.adoc @@ -874,6 +874,35 @@ The Kubernetes health indicator (which is part of the core module) exposes the f +== LoadBalancer for Kubernetes +This project includes Spring Cloud Load Balancer for load balancing based on Kubernetes Endpoints and provides implementation of load balancer based on Kubernetes Service. +To include it to your project add the following dependency. +==== +[source,xml] +---- + + org.springframework.cloud + spring-cloud-starter-kubernetes-loadbalancer + +---- +==== + +To enable load balancing based on Kubernetes Service name use the following property. Then load balancer would try to call application using address, for example `service-a.default.svc.cluster.local` +==== +[source] +---- +spring.cloud.kubernetes.loadbalancer.mode=SERVICE +---- +==== + +To enabled load balancing across all namespaces use the following property. Property from `spring-cloud-kubernetes-discovery` module is respected. +==== +[source] +---- +spring.cloud.kubernetes.discovery.all-namespaces=true +---- +==== + == Security Configurations Inside Kubernetes diff --git a/docs/pom.xml b/docs/pom.xml index 10a83e3c..6aa2d40c 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE pom Spring Cloud Kubernetes Docs diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index f743abbb..f8447b3f 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -64,6 +64,10 @@ |spring.cloud.kubernetes.discovery.service-labels | | If set, then only the services matching these labels will be fetched from the Kubernetes API server. |spring.cloud.kubernetes.discovery.service-name | unknown | The service name of the local instance. |spring.cloud.kubernetes.enabled | true | Whether to enable Kubernetes integration. +|spring.cloud.kubernetes.loadbalancer.cluster-domain | cluster.local | cluster domain. +|spring.cloud.kubernetes.loadbalancer.enabled | true | Load balancer enabled,default true. +|spring.cloud.kubernetes.loadbalancer.mode | | {@link KubernetesLoadBalancerMode} setting load balancer server list with ip of pod or service name. default value is POD. +|spring.cloud.kubernetes.loadbalancer.port-name | http | service port name. |spring.cloud.kubernetes.reload.enabled | false | Enables the Kubernetes configuration reload on change. |spring.cloud.kubernetes.reload.max-wait-for-restart | 2s | If Restart or Shutdown strategies are used, Spring Cloud Kubernetes waits a random amount of time before restarting. This is done in order to avoid having all instances of the same application restart at the same time. This property configures the maximum of amount of wait time from the moment the signal is received that a restart is needed until the moment the restart is actually triggered |spring.cloud.kubernetes.reload.mode | | Sets the detection mode for Kubernetes configuration reload. diff --git a/pom.xml b/pom.xml index 3dee885e..9edcf376 100644 --- a/pom.xml +++ b/pom.xml @@ -24,13 +24,13 @@ org.springframework.cloud spring-cloud-build - 2.3.2.BUILD-SNAPSHOT + 2.3.1.RELEASE org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE pom Spring Cloud Kubernetes @@ -63,9 +63,9 @@ - 2.2.5.BUILD-SNAPSHOT - 2.2.5.BUILD-SNAPSHOT - 2.2.5.BUILD-SNAPSHOT + 2.2.5.RELEASE + 2.2.5.RELEASE + 2.2.5.RELEASE 3.5 diff --git a/spring-cloud-kubernetes-config/pom.xml b/spring-cloud-kubernetes-config/pom.xml index 5c4e213b..57627e7e 100644 --- a/spring-cloud-kubernetes-config/pom.xml +++ b/spring-cloud-kubernetes-config/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-core/pom.xml b/spring-cloud-kubernetes-core/pom.xml index d6ecc55c..057016ee 100644 --- a/spring-cloud-kubernetes-core/pom.xml +++ b/spring-cloud-kubernetes-core/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java index 2810f9e4..6edd151a 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java @@ -33,9 +33,10 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { - "spring.cloud.kubernetes.client.password=mypassword", - "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = App.class, + properties = { "spring.cloud.kubernetes.client.password=mypassword", + "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) public class KubernetesAutoConfigurationTests { @ClassRule diff --git a/spring-cloud-kubernetes-dependencies/pom.xml b/spring-cloud-kubernetes-dependencies/pom.xml index 165c41e4..736d7358 100644 --- a/spring-cloud-kubernetes-dependencies/pom.xml +++ b/spring-cloud-kubernetes-dependencies/pom.xml @@ -23,11 +23,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.3.2.BUILD-SNAPSHOT + 2.3.1.RELEASE spring-cloud-kubernetes-dependencies - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE pom Spring Cloud Kubernetes :: Dependencies Spring Cloud Kubernetes Dependencies diff --git a/spring-cloud-kubernetes-discovery/pom.xml b/spring-cloud-kubernetes-discovery/pom.xml index 901bdeea..961328d8 100644 --- a/spring-cloud-kubernetes-discovery/pom.xml +++ b/spring-cloud-kubernetes-discovery/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml index 94fbdf8a..38e0124a 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE greeting-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml index 58521c5e..d2c9e430 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE name-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml index 6b9cefbb..2a9a1315 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE org.springframework.cloud diff --git a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml index e420225b..27d7db07 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml index 56ab1dea..8bc97dd7 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes-examples - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE kubernetes-leader-election-example diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml index 2edfb308..305d5ce8 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml index 7ffae6e5..c749bbc5 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-examples/pom.xml b/spring-cloud-kubernetes-examples/pom.xml index efca885a..897cb38a 100644 --- a/spring-cloud-kubernetes-examples/pom.xml +++ b/spring-cloud-kubernetes-examples/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE spring-cloud-kubernetes-examples diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml index 48dae2a9..8a33f2b6 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE discovery-client diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml index f910c381..44b3d770 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE discovery-service-a diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml index 57024485..2df12946 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE discovery-service-b diff --git a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml index c374d2c9..3f2a1e25 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE Spring Cloud Kubernetes :: Integration Tests :: Discovery Parent diff --git a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml index ec9d30e7..90ed03fc 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE tests diff --git a/spring-cloud-kubernetes-integration-tests/istio/pom.xml b/spring-cloud-kubernetes-integration-tests/istio/pom.xml index 0f04b862..d33794a3 100644 --- a/spring-cloud-kubernetes-integration-tests/istio/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/istio/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE Spring Cloud Kubernetes :: Integration Tests :: Istio diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml index e6d25022..46e74e60 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-integration-tests org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml index 09e0e171..43429275 100644 --- a/spring-cloud-kubernetes-integration-tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE spring-cloud-kubernetes-integration-tests diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml index 368210ab..8e0febdc 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE Spring Cloud Kubernetes :: Integration Tests :: Simple Configmap diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml index eac490e9..d32dd91e 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE Spring Cloud Kubernetes :: Integration Tests :: Simple Core diff --git a/spring-cloud-kubernetes-istio/pom.xml b/spring-cloud-kubernetes-istio/pom.xml index f2275ac6..203dc81a 100644 --- a/spring-cloud-kubernetes-istio/pom.xml +++ b/spring-cloud-kubernetes-istio/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-leader/pom.xml b/spring-cloud-kubernetes-leader/pom.xml index 5982ea23..f494b42e 100644 --- a/spring-cloud-kubernetes-leader/pom.xml +++ b/spring-cloud-kubernetes-leader/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE spring-cloud-kubernetes-leader diff --git a/spring-cloud-kubernetes-loadbalancer/pom.xml b/spring-cloud-kubernetes-loadbalancer/pom.xml index 3b4fcb3d..00055049 100644 --- a/spring-cloud-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-kubernetes-ribbon/pom.xml b/spring-cloud-kubernetes-ribbon/pom.xml index 890b9d40..5a3cf01f 100644 --- a/spring-cloud-kubernetes-ribbon/pom.xml +++ b/spring-cloud-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-starter-kubernetes-all/pom.xml b/spring-cloud-starter-kubernetes-all/pom.xml index fd70d73b..816394cd 100644 --- a/spring-cloud-starter-kubernetes-all/pom.xml +++ b/spring-cloud-starter-kubernetes-all/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-starter-kubernetes-config/pom.xml b/spring-cloud-starter-kubernetes-config/pom.xml index 3ce88092..5518f342 100644 --- a/spring-cloud-starter-kubernetes-config/pom.xml +++ b/spring-cloud-starter-kubernetes-config/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml index d252a071..64415349 100644 --- a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-starter-kubernetes-ribbon/pom.xml b/spring-cloud-starter-kubernetes-ribbon/pom.xml index 1a37c345..570a856b 100644 --- a/spring-cloud-starter-kubernetes-ribbon/pom.xml +++ b/spring-cloud-starter-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 diff --git a/spring-cloud-starter-kubernetes/pom.xml b/spring-cloud-starter-kubernetes/pom.xml index 9020013f..cfa083b7 100644 --- a/spring-cloud-starter-kubernetes/pom.xml +++ b/spring-cloud-starter-kubernetes/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.6.RELEASE 4.0.0 From 5a9c3418e9e0319edfe5f2d6a57cbd7cb687bbf0 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 28 Aug 2020 20:00:54 +0000 Subject: [PATCH 02/13] Going back to snapshots --- README.adoc | 29 ------------------- docs/pom.xml | 2 +- docs/src/main/asciidoc/_configprops.adoc | 4 --- pom.xml | 10 +++---- spring-cloud-kubernetes-config/pom.xml | 2 +- spring-cloud-kubernetes-core/pom.xml | 2 +- .../KubernetesAutoConfigurationTests.java | 7 ++--- spring-cloud-kubernetes-dependencies/pom.xml | 4 +-- spring-cloud-kubernetes-discovery/pom.xml | 2 +- .../greeting-service/pom.xml | 2 +- .../name-service/pom.xml | 2 +- .../pom.xml | 2 +- .../kubernetes-hello-world-example/pom.xml | 2 +- .../pom.xml | 2 +- .../kubernetes-reload-example/pom.xml | 2 +- .../kubernetes-zipkin-example/pom.xml | 2 +- spring-cloud-kubernetes-examples/pom.xml | 2 +- .../discovery/discovery-client/pom.xml | 2 +- .../discovery/discovery-service-a/pom.xml | 2 +- .../discovery/discovery-service-b/pom.xml | 2 +- .../discovery/pom.xml | 2 +- .../discovery/tests/pom.xml | 2 +- .../istio/pom.xml | 2 +- .../load-balancer/pom.xml | 2 +- .../pom.xml | 2 +- .../simple-configmap/pom.xml | 2 +- .../simple-core/pom.xml | 2 +- spring-cloud-kubernetes-istio/pom.xml | 2 +- spring-cloud-kubernetes-leader/pom.xml | 2 +- spring-cloud-kubernetes-loadbalancer/pom.xml | 2 +- spring-cloud-kubernetes-ribbon/pom.xml | 2 +- spring-cloud-starter-kubernetes-all/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- spring-cloud-starter-kubernetes/pom.xml | 2 +- 36 files changed, 41 insertions(+), 75 deletions(-) diff --git a/README.adoc b/README.adoc index 043d539a..96b1230c 100644 --- a/README.adoc +++ b/README.adoc @@ -874,35 +874,6 @@ The Kubernetes health indicator (which is part of the core module) exposes the f -== LoadBalancer for Kubernetes -This project includes Spring Cloud Load Balancer for load balancing based on Kubernetes Endpoints and provides implementation of load balancer based on Kubernetes Service. -To include it to your project add the following dependency. -==== -[source,xml] ----- - - org.springframework.cloud - spring-cloud-starter-kubernetes-loadbalancer - ----- -==== - -To enable load balancing based on Kubernetes Service name use the following property. Then load balancer would try to call application using address, for example `service-a.default.svc.cluster.local` -==== -[source] ----- -spring.cloud.kubernetes.loadbalancer.mode=SERVICE ----- -==== - -To enabled load balancing across all namespaces use the following property. Property from `spring-cloud-kubernetes-discovery` module is respected. -==== -[source] ----- -spring.cloud.kubernetes.discovery.all-namespaces=true ----- -==== - == Security Configurations Inside Kubernetes diff --git a/docs/pom.xml b/docs/pom.xml index 6aa2d40c..10a83e3c 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT pom Spring Cloud Kubernetes Docs diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index f8447b3f..f743abbb 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -64,10 +64,6 @@ |spring.cloud.kubernetes.discovery.service-labels | | If set, then only the services matching these labels will be fetched from the Kubernetes API server. |spring.cloud.kubernetes.discovery.service-name | unknown | The service name of the local instance. |spring.cloud.kubernetes.enabled | true | Whether to enable Kubernetes integration. -|spring.cloud.kubernetes.loadbalancer.cluster-domain | cluster.local | cluster domain. -|spring.cloud.kubernetes.loadbalancer.enabled | true | Load balancer enabled,default true. -|spring.cloud.kubernetes.loadbalancer.mode | | {@link KubernetesLoadBalancerMode} setting load balancer server list with ip of pod or service name. default value is POD. -|spring.cloud.kubernetes.loadbalancer.port-name | http | service port name. |spring.cloud.kubernetes.reload.enabled | false | Enables the Kubernetes configuration reload on change. |spring.cloud.kubernetes.reload.max-wait-for-restart | 2s | If Restart or Shutdown strategies are used, Spring Cloud Kubernetes waits a random amount of time before restarting. This is done in order to avoid having all instances of the same application restart at the same time. This property configures the maximum of amount of wait time from the moment the signal is received that a restart is needed until the moment the restart is actually triggered |spring.cloud.kubernetes.reload.mode | | Sets the detection mode for Kubernetes configuration reload. diff --git a/pom.xml b/pom.xml index 9edcf376..3dee885e 100644 --- a/pom.xml +++ b/pom.xml @@ -24,13 +24,13 @@ org.springframework.cloud spring-cloud-build - 2.3.1.RELEASE + 2.3.2.BUILD-SNAPSHOT org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT pom Spring Cloud Kubernetes @@ -63,9 +63,9 @@ - 2.2.5.RELEASE - 2.2.5.RELEASE - 2.2.5.RELEASE + 2.2.5.BUILD-SNAPSHOT + 2.2.5.BUILD-SNAPSHOT + 2.2.5.BUILD-SNAPSHOT 3.5 diff --git a/spring-cloud-kubernetes-config/pom.xml b/spring-cloud-kubernetes-config/pom.xml index 57627e7e..5c4e213b 100644 --- a/spring-cloud-kubernetes-config/pom.xml +++ b/spring-cloud-kubernetes-config/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-core/pom.xml b/spring-cloud-kubernetes-core/pom.xml index 057016ee..d6ecc55c 100644 --- a/spring-cloud-kubernetes-core/pom.xml +++ b/spring-cloud-kubernetes-core/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java index 6edd151a..2810f9e4 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java @@ -33,10 +33,9 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, - properties = { "spring.cloud.kubernetes.client.password=mypassword", - "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { + "spring.cloud.kubernetes.client.password=mypassword", + "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) public class KubernetesAutoConfigurationTests { @ClassRule diff --git a/spring-cloud-kubernetes-dependencies/pom.xml b/spring-cloud-kubernetes-dependencies/pom.xml index 736d7358..165c41e4 100644 --- a/spring-cloud-kubernetes-dependencies/pom.xml +++ b/spring-cloud-kubernetes-dependencies/pom.xml @@ -23,11 +23,11 @@ spring-cloud-dependencies-parent org.springframework.cloud - 2.3.1.RELEASE + 2.3.2.BUILD-SNAPSHOT spring-cloud-kubernetes-dependencies - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT pom Spring Cloud Kubernetes :: Dependencies Spring Cloud Kubernetes Dependencies diff --git a/spring-cloud-kubernetes-discovery/pom.xml b/spring-cloud-kubernetes-discovery/pom.xml index 961328d8..901bdeea 100644 --- a/spring-cloud-kubernetes-discovery/pom.xml +++ b/spring-cloud-kubernetes-discovery/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml index 38e0124a..94fbdf8a 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT greeting-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml index d2c9e430..58521c5e 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT name-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml index 2a9a1315..6b9cefbb 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT org.springframework.cloud diff --git a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml index 27d7db07..e420225b 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml index 8bc97dd7..56ab1dea 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes-examples - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT kubernetes-leader-election-example diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml index 305d5ce8..2edfb308 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml index c749bbc5..7ffae6e5 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/pom.xml b/spring-cloud-kubernetes-examples/pom.xml index 897cb38a..efca885a 100644 --- a/spring-cloud-kubernetes-examples/pom.xml +++ b/spring-cloud-kubernetes-examples/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT spring-cloud-kubernetes-examples diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml index 8a33f2b6..48dae2a9 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT discovery-client diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml index 44b3d770..f910c381 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT discovery-service-a diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml index 2df12946..57024485 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT discovery-service-b diff --git a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml index 3f2a1e25..c374d2c9 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Discovery Parent diff --git a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml index 90ed03fc..ec9d30e7 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT tests diff --git a/spring-cloud-kubernetes-integration-tests/istio/pom.xml b/spring-cloud-kubernetes-integration-tests/istio/pom.xml index d33794a3..0f04b862 100644 --- a/spring-cloud-kubernetes-integration-tests/istio/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/istio/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Istio diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml index 46e74e60..e6d25022 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-integration-tests org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml index 43429275..09e0e171 100644 --- a/spring-cloud-kubernetes-integration-tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT spring-cloud-kubernetes-integration-tests diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml index 8e0febdc..368210ab 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Simple Configmap diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml index d32dd91e..eac490e9 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Simple Core diff --git a/spring-cloud-kubernetes-istio/pom.xml b/spring-cloud-kubernetes-istio/pom.xml index 203dc81a..f2275ac6 100644 --- a/spring-cloud-kubernetes-istio/pom.xml +++ b/spring-cloud-kubernetes-istio/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-leader/pom.xml b/spring-cloud-kubernetes-leader/pom.xml index f494b42e..5982ea23 100644 --- a/spring-cloud-kubernetes-leader/pom.xml +++ b/spring-cloud-kubernetes-leader/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT spring-cloud-kubernetes-leader diff --git a/spring-cloud-kubernetes-loadbalancer/pom.xml b/spring-cloud-kubernetes-loadbalancer/pom.xml index 00055049..3b4fcb3d 100644 --- a/spring-cloud-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-ribbon/pom.xml b/spring-cloud-kubernetes-ribbon/pom.xml index 5a3cf01f..890b9d40 100644 --- a/spring-cloud-kubernetes-ribbon/pom.xml +++ b/spring-cloud-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-all/pom.xml b/spring-cloud-starter-kubernetes-all/pom.xml index 816394cd..fd70d73b 100644 --- a/spring-cloud-starter-kubernetes-all/pom.xml +++ b/spring-cloud-starter-kubernetes-all/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-config/pom.xml b/spring-cloud-starter-kubernetes-config/pom.xml index 5518f342..3ce88092 100644 --- a/spring-cloud-starter-kubernetes-config/pom.xml +++ b/spring-cloud-starter-kubernetes-config/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml index 64415349..d252a071 100644 --- a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-ribbon/pom.xml b/spring-cloud-starter-kubernetes-ribbon/pom.xml index 570a856b..1a37c345 100644 --- a/spring-cloud-starter-kubernetes-ribbon/pom.xml +++ b/spring-cloud-starter-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes/pom.xml b/spring-cloud-starter-kubernetes/pom.xml index cfa083b7..9020013f 100644 --- a/spring-cloud-starter-kubernetes/pom.xml +++ b/spring-cloud-starter-kubernetes/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.RELEASE + 1.1.6.BUILD-SNAPSHOT 4.0.0 From 07a8748954afd463101f8d786c36053837730397 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 28 Aug 2020 20:00:54 +0000 Subject: [PATCH 03/13] Bumping versions to 1.1.7.BUILD-SNAPSHOT after release --- docs/pom.xml | 2 +- pom.xml | 10 +++++----- spring-cloud-kubernetes-config/pom.xml | 2 +- spring-cloud-kubernetes-core/pom.xml | 2 +- spring-cloud-kubernetes-dependencies/pom.xml | 2 +- spring-cloud-kubernetes-discovery/pom.xml | 2 +- .../greeting-service/pom.xml | 2 +- .../name-service/pom.xml | 2 +- .../kubernetes-circuitbreaker-ribbon-example/pom.xml | 2 +- .../kubernetes-hello-world-example/pom.xml | 2 +- .../kubernetes-leader-election-example/pom.xml | 2 +- .../kubernetes-reload-example/pom.xml | 2 +- .../kubernetes-zipkin-example/pom.xml | 2 +- spring-cloud-kubernetes-examples/pom.xml | 2 +- .../discovery/discovery-client/pom.xml | 2 +- .../discovery/discovery-service-a/pom.xml | 2 +- .../discovery/discovery-service-b/pom.xml | 2 +- .../discovery/pom.xml | 2 +- .../discovery/tests/pom.xml | 2 +- .../istio/pom.xml | 2 +- .../load-balancer/pom.xml | 2 +- spring-cloud-kubernetes-integration-tests/pom.xml | 2 +- .../simple-configmap/pom.xml | 2 +- .../simple-core/pom.xml | 2 +- spring-cloud-kubernetes-istio/pom.xml | 2 +- spring-cloud-kubernetes-leader/pom.xml | 2 +- spring-cloud-kubernetes-loadbalancer/pom.xml | 2 +- spring-cloud-kubernetes-ribbon/pom.xml | 2 +- spring-cloud-starter-kubernetes-all/pom.xml | 2 +- spring-cloud-starter-kubernetes-config/pom.xml | 2 +- spring-cloud-starter-kubernetes-loadbalancer/pom.xml | 2 +- spring-cloud-starter-kubernetes-ribbon/pom.xml | 2 +- spring-cloud-starter-kubernetes/pom.xml | 2 +- 33 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/pom.xml b/docs/pom.xml index 10a83e3c..5ad957a2 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -8,7 +8,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT pom Spring Cloud Kubernetes Docs diff --git a/pom.xml b/pom.xml index 3dee885e..624c04ce 100644 --- a/pom.xml +++ b/pom.xml @@ -24,13 +24,13 @@ org.springframework.cloud spring-cloud-build - 2.3.2.BUILD-SNAPSHOT + 2.3.1.RELEASE org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT pom Spring Cloud Kubernetes @@ -63,9 +63,9 @@ - 2.2.5.BUILD-SNAPSHOT - 2.2.5.BUILD-SNAPSHOT - 2.2.5.BUILD-SNAPSHOT + 2.2.6.BUILD-SNAPSHOT + 2.2.6.BUILD-SNAPSHOT + 2.2.6.BUILD-SNAPSHOT 3.5 diff --git a/spring-cloud-kubernetes-config/pom.xml b/spring-cloud-kubernetes-config/pom.xml index 5c4e213b..013765f3 100644 --- a/spring-cloud-kubernetes-config/pom.xml +++ b/spring-cloud-kubernetes-config/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-core/pom.xml b/spring-cloud-kubernetes-core/pom.xml index d6ecc55c..136c8c83 100644 --- a/spring-cloud-kubernetes-core/pom.xml +++ b/spring-cloud-kubernetes-core/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-dependencies/pom.xml b/spring-cloud-kubernetes-dependencies/pom.xml index 165c41e4..d58a4f5c 100644 --- a/spring-cloud-kubernetes-dependencies/pom.xml +++ b/spring-cloud-kubernetes-dependencies/pom.xml @@ -27,7 +27,7 @@ spring-cloud-kubernetes-dependencies - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT pom Spring Cloud Kubernetes :: Dependencies Spring Cloud Kubernetes Dependencies diff --git a/spring-cloud-kubernetes-discovery/pom.xml b/spring-cloud-kubernetes-discovery/pom.xml index 901bdeea..b91b21ed 100644 --- a/spring-cloud-kubernetes-discovery/pom.xml +++ b/spring-cloud-kubernetes-discovery/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml index 94fbdf8a..1d5ebf19 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/greeting-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT greeting-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml index 58521c5e..ef4a06cc 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/name-service/pom.xml @@ -23,7 +23,7 @@ org.springframework.cloud kubernetes-circuitbreaker-ribbon-example - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT name-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml index 6b9cefbb..fba12def 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-circuitbreaker-ribbon-example/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT org.springframework.cloud diff --git a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml index e420225b..7dd12e51 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-hello-world-example/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml index 56ab1dea..e0551f1e 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes-examples - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT kubernetes-leader-election-example diff --git a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml index 2edfb308..b3434bc7 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-reload-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml index 7ffae6e5..0653e9be 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-zipkin-example/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/pom.xml b/spring-cloud-kubernetes-examples/pom.xml index efca885a..9fb28ad2 100644 --- a/spring-cloud-kubernetes-examples/pom.xml +++ b/spring-cloud-kubernetes-examples/pom.xml @@ -23,7 +23,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT spring-cloud-kubernetes-examples diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml index 48dae2a9..7729f5ef 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-client/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT discovery-client diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml index f910c381..b9fdef19 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-a/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT discovery-service-a diff --git a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml index 57024485..34830870 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/discovery-service-b/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT discovery-service-b diff --git a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml index c374d2c9..6caf6fdc 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Discovery Parent diff --git a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml index ec9d30e7..d8c6d7a0 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/discovery/tests/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud discovery-parent - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT tests diff --git a/spring-cloud-kubernetes-integration-tests/istio/pom.xml b/spring-cloud-kubernetes-integration-tests/istio/pom.xml index 0f04b862..27cf85d9 100644 --- a/spring-cloud-kubernetes-integration-tests/istio/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/istio/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Istio diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml index e6d25022..7732ce8c 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-integration-tests org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-integration-tests/pom.xml b/spring-cloud-kubernetes-integration-tests/pom.xml index 09e0e171..e6e005ee 100644 --- a/spring-cloud-kubernetes-integration-tests/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/pom.xml @@ -6,7 +6,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT spring-cloud-kubernetes-integration-tests diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml index 368210ab..37dc7684 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Simple Configmap diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml index eac490e9..0fe9593e 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml +++ b/spring-cloud-kubernetes-integration-tests/simple-core/pom.xml @@ -7,7 +7,7 @@ org.springframework.cloud spring-cloud-kubernetes-integration-tests - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT Spring Cloud Kubernetes :: Integration Tests :: Simple Core diff --git a/spring-cloud-kubernetes-istio/pom.xml b/spring-cloud-kubernetes-istio/pom.xml index f2275ac6..cbc1d5b3 100644 --- a/spring-cloud-kubernetes-istio/pom.xml +++ b/spring-cloud-kubernetes-istio/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-leader/pom.xml b/spring-cloud-kubernetes-leader/pom.xml index 5982ea23..7ce0b9ef 100644 --- a/spring-cloud-kubernetes-leader/pom.xml +++ b/spring-cloud-kubernetes-leader/pom.xml @@ -22,7 +22,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT spring-cloud-kubernetes-leader diff --git a/spring-cloud-kubernetes-loadbalancer/pom.xml b/spring-cloud-kubernetes-loadbalancer/pom.xml index 3b4fcb3d..d7ac6514 100644 --- a/spring-cloud-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ org.springframework.cloud spring-cloud-kubernetes - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-ribbon/pom.xml b/spring-cloud-kubernetes-ribbon/pom.xml index 890b9d40..0a4aef85 100644 --- a/spring-cloud-kubernetes-ribbon/pom.xml +++ b/spring-cloud-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-all/pom.xml b/spring-cloud-starter-kubernetes-all/pom.xml index fd70d73b..e28d5f86 100644 --- a/spring-cloud-starter-kubernetes-all/pom.xml +++ b/spring-cloud-starter-kubernetes-all/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-config/pom.xml b/spring-cloud-starter-kubernetes-config/pom.xml index 3ce88092..04bd6167 100644 --- a/spring-cloud-starter-kubernetes-config/pom.xml +++ b/spring-cloud-starter-kubernetes-config/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml index d252a071..7105fbde 100644 --- a/spring-cloud-starter-kubernetes-loadbalancer/pom.xml +++ b/spring-cloud-starter-kubernetes-loadbalancer/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes-ribbon/pom.xml b/spring-cloud-starter-kubernetes-ribbon/pom.xml index 1a37c345..a0b67a1a 100644 --- a/spring-cloud-starter-kubernetes-ribbon/pom.xml +++ b/spring-cloud-starter-kubernetes-ribbon/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 diff --git a/spring-cloud-starter-kubernetes/pom.xml b/spring-cloud-starter-kubernetes/pom.xml index 9020013f..90011ce3 100644 --- a/spring-cloud-starter-kubernetes/pom.xml +++ b/spring-cloud-starter-kubernetes/pom.xml @@ -22,7 +22,7 @@ spring-cloud-kubernetes org.springframework.cloud - 1.1.6.BUILD-SNAPSHOT + 1.1.7.BUILD-SNAPSHOT 4.0.0 From 5164a851ffb636e6833ac09f5ddcc4a3e8eb1293 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Fri, 11 Sep 2020 16:56:53 +0200 Subject: [PATCH 04/13] Add example for SC LoadBalancer. --- .../KubernetesAutoConfigurationTests.java | 7 +- .../kubernetes-loadbalancer-example/README.md | 94 ++++++ .../.mvn/wrapper/MavenWrapperDownloader.java | 117 +++++++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 50710 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + .../greeting-service/mvnw | 310 ++++++++++++++++++ .../greeting-service/mvnw.cmd | 182 ++++++++++ .../greeting-service/pom.xml | 93 ++++++ .../src/main/fabric8/route.yml | 10 + .../examples/GreetingController.java | 55 ++++ .../examples/GreetingServiceApplication.java | 46 +++ .../kubernetes/examples/NameService.java | 42 +++ .../src/main/resources/application.yml | 10 + .../.mvn/wrapper/MavenWrapperDownloader.java | 117 +++++++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 50710 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + .../name-service/mvnw | 310 ++++++++++++++++++ .../name-service/mvnw.cmd | 182 ++++++++++ .../name-service/pom.xml | 67 ++++ .../name-service/src/main/fabric8/route.yml | 10 + .../kubernetes/examples/NameController.java | 68 ++++ .../examples/NameServiceApplication.java | 34 ++ .../src/main/resources/application.yml | 6 + .../kubernetes-loadbalancer-example/pom.xml | 117 +++++++ spring-cloud-kubernetes-examples/pom.xml | 1 + 25 files changed, 1879 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties create mode 100755 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/fabric8/route.yml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/resources/application.yml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties create mode 100755 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/fabric8/route.yml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameServiceApplication.java create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/resources/application.yml create mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java index 2810f9e4..6edd151a 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java @@ -33,9 +33,10 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { - "spring.cloud.kubernetes.client.password=mypassword", - "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = App.class, + properties = { "spring.cloud.kubernetes.client.password=mypassword", + "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) public class KubernetesAutoConfigurationTests { @ClassRule diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md new file mode 100644 index 00000000..2d1d1b39 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md @@ -0,0 +1,94 @@ +## Kubernetes Spring Cloud LoadBalancer Example + +This example demonstrates how to use [Spring Cloud LoadBalancer](https://github.com/spring-cloud-incubator/spring-cloud-loadbalancer). In our example the REST `greeting service` calls the `name service`. +As the Spring Cloud LoadBalancer for Kubernetes is configured within this example, it will fetch from the Kubernetes API Server the list of the endpoints available for the name service and load-balance the request between the IP addresses available. + +### Running the example + +This project example runs on ALL the Kubernetes or OpenShift environments, but for development purposes you can use [Minikube - Kubernetes](https://kubernetes.io/docs/getting-started-guides/minikube/) tool +to install the platform locally within a virtual machine managed by VirtualBox, Xhyve or KVM, with no fuss. + +IMPORTANT: In order for this setup to work, you need to grant permissions to retrieve "pods", "services" and "enpoints" to the serviceaccont that will be used with the greeting-service. + +### Build/Deploy using Minikube + +First, create a new virtual machine provisioned with Kubernetes on your laptop using the command `minikube start`. + +Next, you can compile your project and generate the Kubernetes resources (yaml files containing the definition of the pod, deployment, build, service and route to be created) +like also to deploy the application on Kubernetes in one maven line by running the following command one by one in both `greeting-service` and `name-service` + +``` +./mvnw clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes +``` + +### Call the Greeting service + +When maven has finished to compile the code but also to call the platform in order to deploy the yaml files generated and tell to the platform to start the process +to build/deploy the docker image and create the containers where the Spring Boot application will run 'greeting-service" and "name-service", you will be able to +check if the pods have been created using this command : + +``` +kc get pods +``` + +If the status of the Spring Boot pod application is `running` and ready state `1`, then you can +get the external address IP/Hostname to be used to call the service from your laptop + +``` +minikube service --url greeting-service +``` + +and then call the service using the curl client + +``` +curl https://IP_OR_HOSTNAME/greeting +``` + +to get a response as such + +``` +Hello from name-service-1-0dzb4!d +``` + +### Verify the load balancing + +First, scale the number of pods of the `name service` to 2 + +``` +kc scale --replicas=2 deployment name-service +``` + +Wait a few minutes before to issue the curl request to call the Greeting Service to let the platform to create the new pod. + +``` +kc get pods --selector=project=name-service +NAME READY STATUS RESTARTS AGE +name-service-1652024859-fsnfw 1/1 Running 0 33s +name-service-1652024859-wrzjs 1/1 Running 0 6m +``` + +If you issue the curl request to access the greeting service, you should see that the message response +contains a different id end of the message which corresponds to the name of the pod. + +``` +Hello from name-service-1-0ss0r! +``` + +As Spring Cloud LoadBalancer will question the Kubernetes API to get, base on the `name-service` name, the list of IP Addresses assigned to the service as endpoints, +you should see that you will get a response from one of the 2 pods running + +``` +kc get endpoints/name-service +NAME ENDPOINTS AGE +name-service 172.17.0.5:8080,172.17.0.6:8080 40m +``` + +Here is an example about what you will get + +``` +curl https://IP_OR_HOSTNAME/greeting +Hello from name-service-1652024859-hf3xv! +curl https://IP_OR_HOSTNAME/greeting +Hello from name-service-1652024859-426kv! +... +``` diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..c32394f1 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-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 + * + * http://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. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.5"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..0d5e649888a4843c1520054d9672f80c62ebbb48 GIT binary patch literal 50710 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�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 JS$+5G{{hr`vzY(@ literal 0 HcmV?d00001 diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..fa87ad7d --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw new file mode 100755 index 00000000..d2f0ea38 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd new file mode 100644 index 00000000..b26ab24f --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml new file mode 100644 index 00000000..edf939ae --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml @@ -0,0 +1,93 @@ + + + + kubernetes-loadbalancer-example + org.springframework.cloud + 1.1.7.BUILD-SNAPSHOT + + 4.0.0 + + olgamaciaszek + greeting-service + Spring Cloud LoadBalancer :: Greeting Service + Spring Cloud LoadBalancer :: Greeting Service + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + io.fabric8 + fabric8-maven-plugin + + + fmp + + resource + + + + + + + + + + + org.springframework.boot + spring-boot-dependencies + pom + import + ${spring-boot.version} + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-kubernetes-loadbalancer + ${project.version} + + + org.springframework.cloud + spring-cloud-starter-kubernetes + ${project.version} + + + com.squareup.okhttp3 + okhttp + + + + diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/fabric8/route.yml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/fabric8/route.yml new file mode 100644 index 00000000..d6881f9f --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/fabric8/route.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Route +metadata: + name: greeting-service +spec: + port: + targetPort: 8080 + to: + kind: Service + name: greeting-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java new file mode 100644 index 00000000..7084b4cf --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java @@ -0,0 +1,55 @@ +/* + * Copyright 2020-2020 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.examples; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * Greeting service controller. + * + * @author Gytis Trikleris + */ +@RestController +public class GreetingController { + + private final NameService nameService; + + public GreetingController(NameService nameService) { + this.nameService = nameService; + } + + /** + * Endpoint to get a greeting. This endpoint uses a name server to get a name for the + * greeting. + * + * Request to the name service is guarded with a circuit breaker. Therefore if a name + * service is not available or is too slow to response fallback name is used. + * + * Delay parameter can me used to make name service response slower. + * @param delay Milliseconds for how long the response from name service should be + * delayed. + * @return Greeting string. + */ + @RequestMapping("/greeting") + public String getGreeting( + @RequestParam(value = "delay", defaultValue = "0") int delay) { + return String.format("Hello from %s!", this.nameService.getName(delay)); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java new file mode 100644 index 00000000..6cd86579 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java @@ -0,0 +1,46 @@ +/* + * Copyright 2020-2020 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.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +/** + * Entry point to the application. + * + * @author Gytis Trikleris + * @author Olga Maciaszek-Sharma + */ +@SpringBootApplication +@EnableDiscoveryClient +public class GreetingServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(GreetingServiceApplication.class, args); + } + + @LoadBalanced + @Bean + RestTemplate restTemplate() { + return new RestTemplate(); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java new file mode 100644 index 00000000..8f23a128 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java @@ -0,0 +1,42 @@ +/* + * Copyright 2020-2020 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.examples; + +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +/** + * Service invoking name-service via REST and guarded by Hystrix. + * + * @author Gytis Trikleris + * @author Olga Maciaszek-Sharma + */ +@Service +public class NameService { + + private final RestTemplate restTemplate; + + public NameService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public String getName(int delay) { + return this.restTemplate.getForObject( + String.format("http://name-service/name?delay=%d", delay), String.class); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/resources/application.yml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/resources/application.yml new file mode 100644 index 00000000..5aaed995 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/resources/application.yml @@ -0,0 +1,10 @@ +spring: + application: + name: greeting-service + cloud: + loadbalancer: + ribbon: + enabled: false + +server: + port: 8080 diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 00000000..c32394f1 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-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 + * + * http://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. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.5"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..0d5e649888a4843c1520054d9672f80c62ebbb48 GIT binary patch literal 50710 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�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 JS$+5G{{hr`vzY(@ literal 0 HcmV?d00001 diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..fa87ad7d --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw new file mode 100755 index 00000000..d2f0ea38 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd new file mode 100644 index 00000000..b26ab24f --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml new file mode 100644 index 00000000..94712f54 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml @@ -0,0 +1,67 @@ + + + + kubernetes-loadbalancer-example + org.springframework.cloud + 1.1.7.BUILD-SNAPSHOT + + 4.0.0 + + name-service + + Spring Cloud LoadBalancer :: Name Service + Spring Cloud LoadBalancer :: Name Service + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + io.fabric8 + fabric8-maven-plugin + + + fmp + + resource + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + + diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/fabric8/route.yml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/fabric8/route.yml new file mode 100644 index 00000000..adb5a71a --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/fabric8/route.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Route +metadata: + name: name-service +spec: + port: + targetPort: 8080 + to: + kind: Service + name: name-service diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java new file mode 100644 index 00000000..34995a80 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java @@ -0,0 +1,68 @@ +/* + * Copyright 2020-2020 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.examples; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * Name service controller. + * + * @author Gytis Trikleris + */ +@RestController +public class NameController { + + private static final Logger LOG = LoggerFactory.getLogger(NameController.class); + + private final String hostName = System.getenv("HOSTNAME"); + + @RequestMapping("/") + public String ribbonPing() { + LOG.info("Ribbon ping"); + return this.hostName; + } + + /** + * Endpoint to get a name with a capability to delay a response for some number of + * milliseconds. + * @param delayValue Milliseconds for how long the response should be delayed. + * @return Host name. + */ + @RequestMapping("/name") + public String getName( + @RequestParam(value = "delay", defaultValue = "0") int delayValue) { + LOG.info(String.format("Returning a name '%s' with a delay '%d'", this.hostName, + delayValue)); + delay(delayValue); + return this.hostName; + } + + private void delay(int delayValue) { + try { + Thread.sleep(delayValue); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameServiceApplication.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameServiceApplication.java new file mode 100644 index 00000000..98aef1b1 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameServiceApplication.java @@ -0,0 +1,34 @@ +/* + * Copyright 2020-2020 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.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Entry point to the application. + * + * @author Gytis Trikleris + */ +@SpringBootApplication +public class NameServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(NameServiceApplication.class, args); + } + +} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/resources/application.yml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/resources/application.yml new file mode 100644 index 00000000..b08d6019 --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + application: + name: name-service + +server: + port: 8080 \ No newline at end of file diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml new file mode 100644 index 00000000..7eff42fd --- /dev/null +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml @@ -0,0 +1,117 @@ + + + + spring-cloud-kubernetes-examples + org.springframework.cloud + 1.1.7.BUILD-SNAPSHOT + + 4.0.0 + + olgamaciaszek + kubernetes-loadbalancer-example + Spring Cloud LoadBalancer Example + pom + + + name-service + greeting-service + + + + + kubernetes + + + + io.fabric8 + fabric8-maven-plugin + ${fabric8.maven.plugin.version} + + + fmp + + resource + build + + + + + + + + NodePort + + + + + + + + + + release + + + + io.fabric8 + fabric8-maven-plugin + ${fabric8.maven.plugin.version} + + + fmp + + resource + helm + + + + + + + + + + integration + + + + io.fabric8 + fabric8-maven-plugin + ${fabric8.maven.plugin.version} + + + fmp + + resource + build + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + run-integration-tests + integration-test + + integration-test + verify + + + + + false + false + + + + + + + + diff --git a/spring-cloud-kubernetes-examples/pom.xml b/spring-cloud-kubernetes-examples/pom.xml index 9fb28ad2..493fd330 100644 --- a/spring-cloud-kubernetes-examples/pom.xml +++ b/spring-cloud-kubernetes-examples/pom.xml @@ -37,6 +37,7 @@ kubernetes-reload-example kubernetes-hello-world-example kubernetes-leader-election-example + kubernetes-loadbalancer-example From 870cae608081d33512895777c1e883f4fa0501da Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Fri, 11 Sep 2020 17:20:41 +0200 Subject: [PATCH 05/13] Switch example to WebFlux. --- .../greeting-service/pom.xml | 2 +- .../examples/GreetingController.java | 15 +++++++++----- .../examples/GreetingServiceApplication.java | 6 +++--- .../kubernetes/examples/NameService.java | 18 ++++++++++------- .../name-service/pom.xml | 2 +- .../kubernetes/examples/NameController.java | 20 ++++++++++--------- 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml index edf939ae..63daeb20 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml @@ -68,7 +68,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter-webflux org.springframework.boot diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java index 7084b4cf..066ac12c 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java @@ -16,7 +16,10 @@ package org.springframework.cloud.kubernetes.examples; -import org.springframework.web.bind.annotation.RequestMapping; + +import reactor.core.publisher.Mono; + +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -24,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController; * Greeting service controller. * * @author Gytis Trikleris + * @author Olga Maciaszek-Sharma */ @RestController public class GreetingController { @@ -46,10 +50,11 @@ public class GreetingController { * delayed. * @return Greeting string. */ - @RequestMapping("/greeting") - public String getGreeting( - @RequestParam(value = "delay", defaultValue = "0") int delay) { - return String.format("Hello from %s!", this.nameService.getName(delay)); + @GetMapping("/greeting") + public Mono getGreeting( + @RequestParam(value = "delay", defaultValue = "0") int delay) { + return Mono + .just(String.format("Hello from %s!", nameService.getName(delay))); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java index 6cd86579..fb649080 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingServiceApplication.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; /** * Entry point to the application. @@ -39,8 +39,8 @@ public class GreetingServiceApplication { @LoadBalanced @Bean - RestTemplate restTemplate() { - return new RestTemplate(); + WebClient.Builder loadBalancedWebClientBuilder() { + return WebClient.builder(); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java index 8f23a128..d8e423f4 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java @@ -16,8 +16,11 @@ package org.springframework.cloud.kubernetes.examples; +import reactor.core.publisher.Mono; + import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.WebClient; /** * Service invoking name-service via REST and guarded by Hystrix. @@ -28,15 +31,16 @@ import org.springframework.web.client.RestTemplate; @Service public class NameService { - private final RestTemplate restTemplate; + private final WebClient webClient; - public NameService(RestTemplate restTemplate) { - this.restTemplate = restTemplate; + public NameService(WebClient.Builder webClientBuilder) { + webClient = webClientBuilder.build(); } - public String getName(int delay) { - return this.restTemplate.getForObject( - String.format("http://name-service/name?delay=%d", delay), String.class); + public Mono getName(int delay) { + return webClient.get() + .uri("http://name-service/name?delay=%d", delay) + .exchange(); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml index 94712f54..8f982f69 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml @@ -56,7 +56,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter-webflux org.springframework.boot diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java index 34995a80..9fa3dd63 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java @@ -18,8 +18,9 @@ package org.springframework.cloud.kubernetes.examples; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -27,6 +28,7 @@ import org.springframework.web.bind.annotation.RestController; * Name service controller. * * @author Gytis Trikleris + * @author Olga Maciaszek-Sharma */ @RestController public class NameController { @@ -35,10 +37,10 @@ public class NameController { private final String hostName = System.getenv("HOSTNAME"); - @RequestMapping("/") + @GetMapping("/") public String ribbonPing() { LOG.info("Ribbon ping"); - return this.hostName; + return hostName; } /** @@ -47,13 +49,13 @@ public class NameController { * @param delayValue Milliseconds for how long the response should be delayed. * @return Host name. */ - @RequestMapping("/name") - public String getName( - @RequestParam(value = "delay", defaultValue = "0") int delayValue) { - LOG.info(String.format("Returning a name '%s' with a delay '%d'", this.hostName, - delayValue)); + @GetMapping("/name") + public Mono getName( + @RequestParam(value = "delay", defaultValue = "0") int delayValue) { + LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName, + delayValue)); delay(delayValue); - return this.hostName; + return Mono.just(hostName); } private void delay(int delayValue) { From 7b2bb7a2f03cb9df91ad27be5987a354708ca7a3 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Fri, 11 Sep 2020 17:46:09 +0200 Subject: [PATCH 06/13] Remove debug code. --- .../greeting-service/pom.xml | 1 - .../kubernetes-loadbalancer-example/pom.xml | 12 +++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml index 63daeb20..a8e2cf79 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml @@ -9,7 +9,6 @@ 4.0.0 - olgamaciaszek greeting-service Spring Cloud LoadBalancer :: Greeting Service Spring Cloud LoadBalancer :: Greeting Service diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml index 7eff42fd..a2cc919f 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml @@ -8,17 +8,10 @@ 1.1.7.BUILD-SNAPSHOT 4.0.0 - - olgamaciaszek kubernetes-loadbalancer-example Spring Cloud LoadBalancer Example pom - - name-service - greeting-service - - kubernetes @@ -114,4 +107,9 @@ + + name-service + greeting-service + + From 35d36f7d41cc86c6e0fc0c863d902fdf75d937aa Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Fri, 11 Sep 2020 18:07:37 +0200 Subject: [PATCH 07/13] Fix call. --- .../cloud/kubernetes/examples/GreetingController.java | 7 +++---- .../cloud/kubernetes/examples/NameService.java | 7 +++---- .../cloud/kubernetes/examples/NameController.java | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java index 066ac12c..4ec2844f 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java @@ -16,7 +16,6 @@ package org.springframework.cloud.kubernetes.examples; - import reactor.core.publisher.Mono; import org.springframework.web.bind.annotation.GetMapping; @@ -52,9 +51,9 @@ public class GreetingController { */ @GetMapping("/greeting") public Mono getGreeting( - @RequestParam(value = "delay", defaultValue = "0") int delay) { - return Mono - .just(String.format("Hello from %s!", nameService.getName(delay))); + @RequestParam(value = "delay", defaultValue = "0") int delay) { + return nameService.getName(delay) + .map(name -> String.format("Hello from %s!", name)); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java index d8e423f4..7d479e32 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java @@ -19,7 +19,6 @@ package org.springframework.cloud.kubernetes.examples; import reactor.core.publisher.Mono; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; /** @@ -37,10 +36,10 @@ public class NameService { webClient = webClientBuilder.build(); } - public Mono getName(int delay) { + public Mono getName(int delay) { return webClient.get() - .uri("http://name-service/name?delay=%d", delay) - .exchange(); + .uri(String.format("http://name-service/name?delay=%d", delay)).retrieve() + .bodyToMono(String.class); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java index 9fa3dd63..cad79b6a 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java @@ -51,9 +51,9 @@ public class NameController { */ @GetMapping("/name") public Mono getName( - @RequestParam(value = "delay", defaultValue = "0") int delayValue) { + @RequestParam(value = "delay", defaultValue = "0") int delayValue) { LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName, - delayValue)); + delayValue)); delay(delayValue); return Mono.just(hostName); } From 83356797f86bf065dc4fc467091a11fb6dc1dbbb Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Fri, 11 Sep 2020 18:19:27 +0200 Subject: [PATCH 08/13] Fix README. Remove wrappers. --- .../kubernetes-loadbalancer-example/README.md | 4 +- .../.mvn/wrapper/MavenWrapperDownloader.java | 117 ------- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../greeting-service/mvnw | 310 ------------------ .../greeting-service/mvnw.cmd | 182 ---------- .../.mvn/wrapper/MavenWrapperDownloader.java | 117 ------- .../.mvn/wrapper/maven-wrapper.jar | Bin 50710 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 - .../name-service/mvnw | 310 ------------------ .../name-service/mvnw.cmd | 182 ---------- 11 files changed, 2 insertions(+), 1224 deletions(-) delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties delete mode 100755 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties delete mode 100755 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw delete mode 100644 spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md index 2d1d1b39..27c01a76 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/README.md @@ -15,10 +15,10 @@ IMPORTANT: In order for this setup to work, you need to grant permissions to ret First, create a new virtual machine provisioned with Kubernetes on your laptop using the command `minikube start`. Next, you can compile your project and generate the Kubernetes resources (yaml files containing the definition of the pod, deployment, build, service and route to be created) -like also to deploy the application on Kubernetes in one maven line by running the following command one by one in both `greeting-service` and `name-service` +like also to deploy the application on Kubernetes in one maven line by running: ``` -./mvnw clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes +mvn clean install fabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes ``` ### Call the Greeting service diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index c32394f1..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-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 - * - * http://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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.5"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 0d5e649888a4843c1520054d9672f80c62ebbb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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�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 JS$+5G{{hr`vzY(@ diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index fa87ad7d..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw deleted file mode 100755 index d2f0ea38..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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 -# -# http://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd deleted file mode 100644 index b26ab24f..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index c32394f1..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2007-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 - * - * http://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. - */ -import java.net.*; -import java.io.*; -import java.nio.channels.*; -import java.util.Properties; - -public class MavenWrapperDownloader { - - private static final String WRAPPER_VERSION = "0.5.5"; - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" - + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if(mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if(mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if(!outputFile.getParentFile().exists()) { - if(!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { - String username = System.getenv("MVNW_USERNAME"); - char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - }); - } - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 0d5e649888a4843c1520054d9672f80c62ebbb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50710 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�zysyX$qy=e$fT3I);zi(d{LG!_|v^=p4+LvsaO4ZCN~ zB-KmIW}S_KN_ATX;5;x^db&s|}S8E#kzLatD!GN+|kuC<-^@23Y! z*;N4OIffqekU*ZaeTLtsHRzwQKbwq>RI6t0q&$~4;x_R!j1^WDlIWM;4owb|LaUU;gB#MA@JqI#y;!{{X|Dopjjm?}-C%NvfAIc8KU4twNO{gMnKTHPgD_kgT>dPikq_{#R~- z5_LG$FSLUqOdW;v1Sld5H;iO?Kt~1>?KtDuV~QlMHwU1aUdmH2gDOt#2doNPh*b#| zj*nPhH-OXD^b|$QA2mZwnAQ5#*o;#inRD_HLwn9_qvcj5qS$^Yzr%^V?>svB2OgQa zwb)=f5m@1E6{{~15H$w6r>|_>&!pWVf>~#bcLb7PI#F2VX+|c^cxRYg&Rf-g+-+8Y z+9b3@@uoR2Bq#b(GR}?7e?R`l7gp&^LqAg<39sS{n)*aB#u2+xXKf+_@NCse$b#x> z|D853NTEM!txFmuZ8~B&9*E?|7&T6{ePv{9!U&CK=H^@W*dbvN(+dW(86zl_2SRqP zVz1T$USo{^tp6su9fqL}hRYP2kXl7zv=9Bn*2NMrfQhT&#$P@F8ojHpeo#G{UN)Iu zdyFTF6Xog5MPav;ZC%%W)qUR&gnUzG9AFiT?H=GzZZ6FKLWIy$S~hi#wUT9KwV+!!3ux(uIY&xNOy#_ zb@YdgY}y@5sivI8BEhQ<)Xve#*}|P)>n+>UHSP72oB%los3Hnc@M*l^04)-w?h#El zLnO=xj4vs{#Y3SZyJTN7gLy-Z6bZHV{H-j>HQ)Dia)VL&*G8}J&5qXvX9;%%O%?6& zymuDI1Z2O%G2gl0tF2evSCQCMwY8zQjaDzY-8}2#$9nyGauUh5mPja>5XSRj}YzFxKs12=Ie0gr;4-rl7ES2utCIaTjqFNg{V`5}Rdt~xE^I;Bwp4)|cs8=f)1YwHz zp?r7}s2~qsDV+gL1e}}NpUE#`^Aq8l%yL9DyQeXSADg5*qMprGAELiHg0Q39`O+i1 z!J@iV!`Y~C$wJ!5?|2X&h?5r(@)tBG$JL=!*uk=2k;T<@{|s1xYL079FvK(6NMedO zP8^EEZnp`(hVMZ;sTk(k5YXnG-b6v;nlw+^* zEwj5-yyMEI3=z&TduBb3HLKz9{|qCfLrTof>=V;1r2y;LT3N)to9fNmN^_w;gpvtr z#4Z->#;&${rrl6`uidUzwT0ab5cAd(eq1^_;`7#H*J0NAJlc@Q>a;+uk$1Fo%q1>V ztuCG3YmenEJhn45P;?%`k@Y>ot+ZzKw9qU`LM| z5^tVL}`9?D;Hzd>_%ptW6 z#N#GToeLGh=K(xh3^-Wj zJpQ)7Zzj6MZdx3^Jn@dh#&_`!w5*<+z^_z~Zc1EyN73#a8yMu*us=j$zX|$sa7Qja zJqh|s-0NjR=L@{4^RexB5aiQJk-m~K^0-AnoCz)nOyncC9+EzeaOQ;W`3Fy|tX21Z zYS`m6!*in{AkaUR|EZKLvNDL+D#(Pz#TTPwImog9dM47L2Ha*RhaXuWuVNEk zv^yjmQQilZpE!xi)2UL9FThU@%XPr@><}RDNOnAZVo7F@UzrdfIeQ}ztxG;_5D8{x zpghA^U4P0{+lr65_?%+D?R-Z|%F4h9&{UhTF&^rKK@f1|DYh1V+z?V5Y7DoHO;E04 zspYSv9AuJII$U~Vbe9+yNypV&&?1%5*S@Sm!g@KaK*D-8e_jd`d3{_7GkL8lN20!~ zSPC<%ss zq}c{_ZD89J{JbXK-yZNh=_2;Spj0~&Rmdy@G~6|)6IWLW0jN_~ZwBq!r;7F}yhPMw zyGvM6nVXhJVb3P#P^wo6Z79Mus9+P-E zn<4+(Z00{oIR8jvgroal`}p94zw;8~W8Hp$q0z8RcM-&i5e2?mkT#ZWnJAyHVRQWo zLDUQsCt>vcvL*RGaPI(0&ArSQKsR%QXGrRc8xlXN6w)_JuSZbSE)|-Hje-i9jWVVY zCRpOHe4+=#$V2c!5b$mFdJku;)298132#glg?KN(>C4atl4%gDXow)md;WfQq-vT& zL$Y%hKKUSwlx&yzsU(lOCd9m0fz9X#b2@`^U(GKka``>d5|X z8pLfJo%F4&{{5gKOU+#m`?vEqw|S9z)o@CrRm1=l=xeOA9+pvT)Ga=S5RtlC^5D82 z<8t)jPzUD(Zn9DJFKa~bJ#g{9U^~uf0N{n%dIUWUKy$@)rc>c{CTsKbZR)P;)*e<* zGu3#c0Xz+F#+~==PoHb=`>mX=FVtTs4wHOgdT~g27WD?py|^9Z2A2&5(gXICs0|0w zmvch%kRg|?05N(`)XO{-CG42L%3p)78)BYwkMaX%@s{urW?yoQC%DBEl!tb z+qIV({K_N1-m(n1;jmQ*ldFehGiLQOkR?{M6fYE{)aVjKNPxDp7}3Evlw_rsYy}oo z>I9tCT81hPGr>ar(HF(_{zaxdE81dX1-~r?=j0r+a^H`!Dd1h2GgBTRxH2+xF9pfV zr6vcp_)q7Jy;0zmGH&t|RPUuzQ}I)m5W?5B%SLTDyQc_%oO2lUg5E3L#Bv&FxyQKi z+fU*dE#u%YtnXn4ttri0=4<>be51WT)4n68^vuXmTH^6Z+fCF-eDF)m9m%XHJDTGF zIEy_YfPDHk!(NVDJJpEjIN#gfT&=Cox92;W20|ojSNW{vzaAn<;#~#@5vh#9gD(nk zwn)`Foh-(wGTz2RI2N(gbSCGv80UV8_#sF%3LA{cuN-W^Xh~#g&6j3boo%h#=n-r4 zzTONgkxjx=zE4PLMVm0JmzcL3+r`_YJ>=-LptK4UcoP?JWwCqf%qGnj2CAm1g;bpW zc=Snp-L_MK9X)Fsj)3uZR`gGIHyh=uw6L<#l7A@g^IoduM7G|<3opaWkZR123QBQe z00cg!%35wF(b@x%^mL~rWQlDI`05vX#~75`3=_F9oA05`X!XIX77X!|g`nXw{BmX! z6m;1XDruiW3Ww$3vFdvSZ9h$jNopc#&JX!Lm^j}U6XH_xz^q7YD$fFP(xubauVuWz z<6GkJyg;wwwaAO^O5pP-(*t@MEMCWM2zY2v@Mg*Wfeu@(C>6lg2d_U zXkydADuMO6yx@Eu(!0C8t@4I)Kim_!gvMDPqnrH|Q0~ zM1vX0ItXknO){#fNgWNwScueS#7wP-InL$k5%`gmg2$Q*%%nHTm8!0ibosAkct7cz zUtu!`{C5zJG1se79|^BUxb762i~QxxNp5PlPY5KIx6w9S7W)w|h#0}~EQ%BQ&si;v zvBI8D+-qFH1E9DiHj1v&*nLQqpQYUKnb5pz2KW0D7wlDM?#|A1$j6!?Mde@a>w}D# zX4D@r9Y`{4NsY{4OGn32Ts7Slqe4+C6%?Y$S@x^2$%U7xXyIx_fkbJjdmDr zG3TY$_(^f=PBth@PU$(P>s!2$RLv%3)7@|mtg4-wo7s7oU+B4BNs3}s989xGNB*`oRQ~ocNDijOq26fjIl>+`e#NPDIsyiIXm) zO6rQjqHyQsl_p6IiTj+=@|BQ}zDkR^rcmMq&oQ33;P>sMy?7ccB1k+i zzGvMKP%A`m~)r;gNhP zBG|G-*d?Gi=i|R|0=eVu^)%Ie#t7U-pL(u|zVIUP4w%;;dE;Lt+v}s4I;$NZ#VH87 zNoFz{FCfRDmeE@U#b;!-s*Yo9;c||hjW4zHvdCZf5XeRBz|$^`yL%W~*v&?7^i?%K z2?~03DjYqn7t|@mQ*5XZHB_~y7Ei{eO{!~X^Yxl{>v@o^<^rHFWNgQ>Kitlni=V*J z8&xA_4J@Yp91m4yN^uuvZ(19gFDzGzqNrJLaXH%8Dl7#rdER!XgTXFZgt!JY4@OiE}3b32Pzbj)nI7kKeR7Br|x zFR(8p8qdMMMM8=K+g?R_3k5jVrgJ83ZYTPrPbmW`?T@mhzag=Dq36?8PJvqDhJ*7M z0{U4XGtN6%(UWf%&O~EnuHG79nFT(v<+PHK2@Y4^C{=zs*iZ~EVbHOrTvBXqb4KD- z&pMMu663ByI}OEAJj3+~A1el$m5AEkh>#bjKl}^vf=j&adgZY0GLlE$6Bc?oqF_v18Ix%3(Zw?{!V=p{lIxU6SIk<4$I{0U}@ znuoM`TGm!vNuyX}Ok@KCxC{MNwpj+F1w`;;HRctuLQtmg;0uBl2u`*zW@F6+S(osl zTvrKIpkiQV8PFO)4gh%NaFh9FGYSLK43{Ek@zGdr;Y=uSsWxHK1&J)Fjs9jG8yJXV zx=Ohi7D%i|h>hT{lPMvC;>|N1bOO&N-EtcUVLFeZGCG1F>}4r9qu`q}hp)qjt$2we zacGRO$2cn_%FV~IS~VW=F>6StmI}!`2guXSr=Jcb~qj;b#nxT)|t4%GlNo} zo-yQLi!cprmaZK3oadq|cp*}4sy$IjFo8HziwdsYPr%mFS+Azxn1UU=tO=7jXCoKb zip6_)Q>vdzvhRoZ?t`%*?gyzdo{HT+W8$amGE=a^wb~60Jv&??XvYkLKNRqRMWJB1 zX+q3@<+IG(P1d_`+lvL^C}4-90*LuRnRiC;-4{O-FPODpxiGBN#SQ9H2+B;JqhDnfLY&c`Hbsh*Nbd_6nZ zl9=4Ovg803&N()m4bzp_yjrrARDUr~a$e!;?Bd?vw8ZsDm-ZHMwfhtN@I6AG9&-QH zp+LW1tt1Dra(n>zr90}1%cETiD2XOVUyjdP+I|8|b7kQMcaAl$<^rr5T|iD3jp7%K zq{bY)q)csIS*0Z=qmr2^5Lb=N47!L*t@wXzq;4}I>+)>*)t}$y!`^)Wbs92AHPo@ zdua*H4TdfzFK?I&g5+RhbwlA4(mh_lf?~mq!q!Gx`Zs#^rRq2uu&9jhOc7_XlSpv& zndOJPFccid+ddXM_uV{N{~Jh&K@0jn#U;~#GqEHPLjA!642j_ zfmuhn!AA{O@pb#89k4lnb8lW8od-;6nP}7Kwt2wq=&Mxsa(!U>WVx^N15Z?r|MniI zEn#jJy1{bGdF@aQzRA!^!Y5|kYq{aR+M)4&vG&Tr@J@Ny1>1a7_?Eoo^it)I`UdSe zujc6wdEwSLC^&+;1@lr3gDVXbe@*MctM`z2$bj|zo~`QQb(pwUu5OH7i8&DUqyK14 zF!!3!uRQGGg=kFdS<+HjzhDo(w-~SBrtDBd_w_+fdW0dpT|j)mdk||XX}?%o;4RAu zof1gVjZI&#T;yLg0DoK!m}u1rsXedYXgOLrw)E_>1k>a`D0NA^S)|f<_P(23i(7lg zf0lS~zhD zINR|YzR{)5#+1eU-cV3cOg5=L0GxVkQ%ElBEP?#FTWn7cc%XnFH$G0E#!RA2{rf-x z2R-4HdYE2m1>Mn@pTyp>liQrVC8voT4OpXdhy7DAIr^m|T0fgoo@T$Ep+T$iEs0zOXJ0fTVEpTA8jJ#DNdUtDDZWpgKH$btBLEEiU}KG?R? z4H{)_NnT}8qb=N2*IxC!m11tft~qS;L(sc}q?7ma& zZND)34!)yzz{@9ao%c+Gk#>O4ateAf-r9zca_-tkU3@Xn1E?aUqinmCi@GbT=sa3q zKPyB15v|h50)Z%l8}i1uh!&SB3F>UeI*IDe zp_`qKh7)LFd?kcTS|Vb>7g`miC!nC_+=A))I>^T#K>3UD)(1MlPR`J92n`_y98@Ux5!dAKe4XCRi{*wZl3|cn#H~> zln&utaatEGJ*&(vZl)7X1C61?Ha*xOW3{2vqdM!e31Q#sClAMPhq#`Ka@v1>cAR~DMS4iLzdBb4eS(%%!+{Y`g?TvfF(P`@$UlOa`mDQD=5akH5k zDiHth|Hhyk62Bh@VZQ0U8Rxd-g>eu#3hx8p zi|oL$BN#2DPTbRW#xZ;0KC`*U=lca>7a`k>jE;%$RNbq03rPR*RW5Kj?l8bFHW|k~ zI~G#{nlZ#{wCYz#cGCtYvQ2+3yQZzqg-Z+iDo;T79;nX==?r>!Rr7${dgL|~PC}!k zkwgbMsN=@knrF&0M(QvM3?tfLN6x;`gY+WZgxr%5K|lV0#RQM2cp;w0`KA3RAI=KX zq_)ze1xdAGw%slLZ~l*QC_-`;cPjL=6!UAT8fi#RkF@ zFxZst_L;sr5tbf50#s=#KGg)g7y5zt&z#Veu(J@neBV}k3go5ounsf%c6o`t6;USM zdL1NE{Ni12$lQQ;%q#jy9R-%#ACwQa4Vm_K%6hV6qt&1bJzFGHsYns96?D zu6bH|YY>l#n2}{~YPIh#5Yz?`l~yo#&^V_jcvsLcfgQmy4?&(GaL%s5Ae}hwXFL;; zXNK><%cyZM&kruofu8Rn!5agDfDxL|+~#HN%(=q~=~%daMa?>XN(ziX2O?SpqXxKp z)d23BQA0#Ic_H)cv&?K<@K@GXS5O^wfeIHm;`1nHhs*V4RoQa7J9@6R6o}Y_tSafq`yu?q+R3QVihW#6!;r0i*8g@y}^BuXI4( zYjeJup^poCg`0?-DuDya_3$Y|Yobf5os0HIm>YDtaTkcDqe3yU-Xw%oT8t74?KK>lC8lZvtn88Us;`n_Fi|I2tT|jV7h`d#n z^_Pq;imf6s`vT@tn`ISTC{Oy70Vf&~)vbh>&wT7Jo!$^f-jN?B4rmtWDwj*ipFxqK zC7x-<>ak}hi5?vS!gRK3bYx>*tv0;X54>@)2byTK2y1;*Y@N{!4b#hZIl@x!N_i~A zYIzm?!Ve}7xGJreRHfI_>+|dMz9Om~LIGg{&)NemNSH~v?})&p32_-lMvWZD=#XzN zm5_|sqLFBX!txXVQM6*v=hDU0^U!rWn}mI9%=?0u z0ZZDa#qHZVM;C^8Xe_EI9xPrVPq*4>}!b>O2eNTFpD@8%>`D`P1u(pN08RgFL|RY%Vx zvpY-hUiMA3Dw`ZRf;1S z#Cu`s5D}AdwIa~Q+0r&?vvpvwe?CviFiE#pT}-G!niAWZc#u%j80DQdC@sWu?D&~L z#Hv!bq3BEzEnobi>z`8?&CyQN`gN2`UgW2}Fs{tGRxTlC1d|rcWJ46*+e*bwsI8JH z%H*wnbPeCo&lr~wku@g7uIC7?72@jG zH^*vFO#Lgh6e}yPi4VKC8_y+I>L6i#q_>pb!UZdTb)?4)gx7eGtU{4GGez?~ymG|Y z#+N*o2=uK(jyriZ?N%1D)?~sWtc>Jcb zeT!t&0+8lyrT@3y;q(TVQo9IQ@}g#hz0XR*6S85oIz)(==#=`RJGEOBfWd zi7hK@k$=v$9Rx#y=!WeNMFq@mMM7LRzsrdY|2?W z%HgE2NY4PC*2^a{cEda5S12$2EA@ex?M9@bHSkRih{`eda>jg>nHHs4B<*euVyo=< zS8ea}=RvXk`l)*8a?b%d+84dHONPI%OkPpUP15KKYfZI0mbA}@C<45{+?-7DqFTLK zd|JAHbh|JHX*jC#3d{s+KE3QBe%A zQOXRbgI1;D;E(~gAT4JjS9JKQy%`GDq0&Vp&)tJc%c_(jIYGzi!ln6qij-O0iJ21C zt+4ZsJ$vz+6m`BZ5^7GgFhI;Ig@v}k#^NBWb|%5u;b0pbB4d2Irk&Kzra|GTDaT~- zucRc|44P1pqk!FytDFu!6ccd9nasV@vv`}-H%gg5ELCA#Ev zpYVkWMW#%inszrWSTUZ}-r){tK4Oc*-02p~))ykW*Y4hJU8P!;Rvm>}o$<$d|3`=F zE|7DIYFY|4RmZM;y{`E4bpJ;Sx0hzr^HxWC*Xr6Ppk*n8&sbMM&{e3vhspxId#ymu8XF#OJh0P)zHxw)GbS$>5$8boRB7VOaXgcP?o4~jG=|} z%c=aGdp?6K-(hT@89XL!+gIQI;vcK&!yH#0_v2omRtSg3r z>&&!(96I2Q+)df;nk6^J`+=Vbll1z|knbhXI>R|0Iu4PS*%sx(b(KA@iK2T+DL z!;6nOt%!%m%xkt1jrw*5zr%T1Vi*UEP1g@STbmlHGn9F=2i#0&ikU_(9jd4s&`9dO zy?Y8=(JQ_`K$JohV6~R~ZZ1izAuMOr@;OVEo=We}WibfqVGTfz@}?Jp)3o6z&sduG z;E>P~&s??jO@_<~IRB|bOy~mJgl03A@^0UTgDnL$uKu$3#-LhWb`Q z=6~+5nHxAencMy|kdIQ(mPL|>=Wd|xkW*D_egxv>2RBD^`aMNPj}IRuUOLxJyd3m zz&rirB*|SxZz_W_e?&k$luAU2N0AAqavrW$l8ysI02=+GGKE)rE-T4Tus7WT4R`dO++T@(&Sk+;BM^7Q5=b) zq2_D@d1+HRn%NqmJ|p~21^NrH#+oV)_d)9eMxNe*W!Y7zym4muj{kxQw(X2~$Dahx z>2DJ}s{b`i{*m2fsl56kJtKHqN+wgG0z#&)>rqUP$5RK9Gy(&K(bg(VxOn^7W7Q|4 zy7O-Q-;zw>7T8&nC!&pzOW1lvLzF3c_ol@a1wFvz6IM`qWA1< zEiQS)%$S0m(Nk@z1!8^Lot8IOv5+8$q#80ZFQ`gdLZVQBh7u@xHk?pxo!X`Y!U;yT zV9&geHFqb>9jXEXXKkOWxAHQ$swfDgsI1Cg3JJJm>a^#V>Eh(MsY~Ff|!X(;Zg8TwnS&1vah^ul7@4~nns()56G~~XOJ)fG+*TkUVBhmoVR>Skq z1{GZJlcS#72i;B9i7~M{O@-`4t`4aKou#BBAXt#(D56?F4brAF;94??^0eLLFua+B z)1#v~?00I)%&=Y;KDGeSFIUPF_uNzp*j+j(yvy=KlQSC!4+3Fd$mnvm-~&h(B}S~J zLR``O4C;=nB|j^lm~gUov4|>K4av7zYE@R8m}I0mPuI;6aV=q1kI>#`DuG%`@M0`B zH@)KPTX;SNzxKM`{!?+3>!AWj+--#|pDFzKuDSOgyhZ!oZax0+En(z!D`}RoFYSeZ zZd!d`RVtstggHyreG3))R)k#nG4Rs|V?VN27e`RwDBfmgXf)%Su{)ZJz>{=rwE`E= z6T1yIt}KClNx-K8iOGY>QDpaktmN=FCl$gs%AJ@wX;n0aN(<4Ps>Uba5z*0p;1%Mw zJm?a#_0JWCliL#<>e55@_i$y)+nWy<>Qntv2Pyg9DTdl(I0D`XLDt%Q!ZuG7^v<{Y zGG?Jr=D!0dlD<1ivoBKiU(?tDH99?=)r|9luNMQ$t(oXvpUc;UG~sVoZIv*Ug|VC# zfL}p*iQybOhz6&wF+d1hahR${WA-7#wUxVQvkr?44R`5AJW!8*eAq36$3_Oq-2lpN zD=-aj-lHL1Xg@Gxe^Qij)k2YMRZo*8zivp-ry;$jZ6DV0AkH#I!Rr$hPi4BOuehJs zjc}QIgo=$Rdtu}0Q;G+ z8f@Gg1tgC|H_1B@!JZK$2u!&(hImH-sS`15_%gESYql9LsZ&*W#}t+N)TSorQ{|d) z^&kv`Jd$)T=AOv6n*OLwtbG2U01!uoF6xQjWuDeQa40 z_ZWlsiCo@XQ}zP%CFcKN8lkbh2I!>ysp{_*KtXxumN1H`B!S@zspot@s^g;NEkBeo z??-TDzhRKkF~I;07T^}aZ&aEU25g^#iZBp{JcU*4ypZSthq&1J><%fdAV0^&cx0qR!i8l<~S2Mpf3|(f=ik)2g|GBhPJDX2$RnSS%`DSPwsCzH)mu!HA2v+xkWme<4 z_M4wmgmz>u94Wh`Iox?Ep%OUx7u&A@<(zL~J3ntuRNB0TNWxP!R}4}SL+)D!15+G0ynmrkBY0e;$&v6?5L*q z4bAb^dIianfZARpSxOHvK7R-z`d^}U5h3p4)~$f;$?Mi$=(3DODqJBIn;V1Ll5W8j zCK{;^ivkv)vv5(!FQ=xYM{S6b*%jqRTE|#;H6aENfw)&o1~mbd;Js_Ozs`b>syNb zj+Smd%c4{{6bDaNVh}mn;x&7}*KW|%3TU?;x$uguy4%B=biQ(mAZO&=k6)i4u!jrqd&&Y( zB>lWCqTs4jIoK%Uknd?S`yS}+{iP#*dsmWIwUJp+cX2Sbo{Eds2 z*V9FF*R#0==ork%|FWB%{=2*vbmjQ*1dsI0Duq>Ann0}R^Vnpes%yqFIUE|1Uz zY`$br1QQXQFV_LRmkLe7cwj^@J9SlYscieuKXJ#^mEQ$k#3kEx9b@sHO%w}k(9*_c zI^B|W?b-AD<7=d*2Y@Z=n#l@@&A211b`Slw5V|DleI9bABltj!6IWkZ)UPc0k_{6EC}Q&X(FNjY!45E84Z3x z$I4*Et{$T!Msz7k6-{{&GnX*MFHQM=?9{jqLLj?3T-oavFPE0qX+_21ypuc zpuLXc;XW5*lc|D`iC}j13$o#NC6=l4{Vukj;*vffTCUA3k7K2wbtx^B!JdEQ?gXv$ z@d79z*VRfn&k7!RJTC&Mj}kUXo;1FiyM{7dXL%pgMarar-uBVy9)$C~HINFEwgxy! zww4OXfq=`#E!&9(hfZINFJj%COcycF0$(U64@aKDM}34D8Y#2G0YJ*F3~>laER1HOMb>l>=k9d&Sh^WJ`-97;M-oc?Dc9$tPoAVUX zP92Y_zn=|OLWq}%!=YuDzEsNyN~=`&Kv$(JsxsmY`ZJk{p~ zD4SZU2q!5(D7TKhP7G}+cAHD{U1pVhOLdrbsy?)wp@QB91PFySQI_yKKU{i&G8c)g zBcyYWex8Kn4dH;a(Zc-i#k&U3EQ|JYXW^4op(Kl;c{x92F5`&l7sutto@}^&)P@Ed zEmS_<`$)1H(Xu`A6U@byC|@tjHVdwxHmIwnK9t4JMAO%{<-@Qlvx9OpkXGB{t)Do* z#LKkZS2xE)-2`m7XLxJ!%q>7Y3;M9r@d}zP-C=%+vvJi2FH>yIvaI2Z?>-^k`{4P? zfO*L-H3tq9Sc1z`<$0EunSz#-Zf6WU&q5N)W`OzjMHFnZYiSQr0lha#wj!5m53zlE z=l!G$8N;^uvjTeN;P#HN2JB4SwOIq&h;5RS+eVe^OjX7XS>0dWCtWnP$n)V?Wtj%R z-tUE-fBiOHfOi)tPCy@KQZ0(H0vPtpjB8fhBbLq53h;t&w+pwVd%OcD@W+*@TSy(o z*dTh~&KxT7a>Cui?k*XGE2LADAn?c_N2Hw(MJb$lvCIbeJ9fA$DP^$M#=jj4%Xr~38&Wt$N4Y~}rm_K#TV z38Y7J^7UQp%9m@>zn4+}t#!+P46p=kZA{EfogMW5ZvmW?xUGn#j6BkVCV)5}6bMot z+B9#mIv7kN(5Mj(BTi{8h$s#`enO9?Hn3cqvAWr-^htu}Br+Tg_YVA4fIYLh$ydL@ zbx+{wlk>XjIeoPK`QZ+w2Rem5jQ%@$bJ;BgFY9EDf_Fjsa^q;T+Q!nen_B&7Mx?{k zaiw+=oe;WA^)1p8$ELaIWtZxG)Hszw2~ML)r0#w%S7F^)Ott2B`d3+VDGIH) zIBnl{di7gIHpVbsU%#VOvkd3r5*aIMe7aALELch}<=nH$qDu|6YhMoCMttJM92)XE z^KM0EqR{m<$nTO->b1Jw*~W$1M~ZzUSkNeh`_=~eF-&@MNrQ7Hl!Y06`yd+Efw|SQ zAO3aexzN5FpW~%%R4cA12(M}^zml0Hq>1+>6sTjU zLPNR!S<}{Oo=wj|2#z*&g!3S0#|BFv4ja)`*e<=FE$XbUx!nEtRWeI`!5MfidAlqmysJN-CXU#*!Nekce6V#ZVa(@aoPENcLt=k^0zIth+X+ zHyG3{y;~s3w)?2=?5QH&4nCfgW!l=k(~4}Jrv=Mb67Fkw{F7X8{o-1_?F;MQGy+4~ z)C;U%_ah`R?M^zw$sh6aW5b+J7h6VHtC4&&-fw>ccx(6RK#Co9@N--xP;G18A1fwa$ zCee>3BNtNsP=^RmDl_o}5hMM!n(SX0%#W!Mn~rV74E;OaLW79U1UR-Gxey-gSqE}H zHUPOFpI2c@mWb~NDE7KDJ?pRWb^CW-{nW3{2KnCtpZ4!a)PDe9*v;6``TsaCB&kAp zBCVis13M5$=p(V{B`fJe)OVH^5*wFnePbO~p*A!CFETW@f{SB5GYbSXimw$~$0uKD z&XZc3X|%62>dm!6Xp3iDdHPECWIvh^M-6`4y?Zp@@^oBroawrITmIDX1nzZtV+|FC zG$>|HoBgffAt5VeX?m|^Fg*X;eNzJ4G27ep!D)`A3LgkkC3AV&EUYp)Lkc=7XL+I7 zKY8n8an#QDaW3v7uTN1l2I;8qGyP zGo@NCL*yrqPBSc%tI{Op+Uj8oSJmgXtUqrZNj5&)JWtex)zo&5TqOI6$(*mbi?*09jV8NM^q=~7HK@8ND z&vN68l_s#o2c$x~ep-k$I0#vnnjJ^D3?&XWL=24?H`-IU$*xUGqbEQj0=t%*#w1c} zq>DwBSCC3Y=!Y5n!9?|ywp8I~P{E4m*^t?n6snQ6QfCGs-q9HnfA8PO^ z1N!Pkvx4>;bv8178CXOHk6I??d^wa28AiXj>7vvG!{8bhvbpt!N^QcS^%sfd34w#J z*ic7ZLfg6N*o=SVlN)@8_=yGlz)+^O)Va6mf``r`TVNODns&wnQW-YQ_fHUHD%|>*U9631xSLio4|(~i#Hz%72ThiniprGkUijgXBk+{Q1)`uY zv1p^bdn7jaxL0Z z{Zc(2iyibQk>6wJ+Qf^JTKDc}40|_}DoYT4wsP&(MCPK^^zyU{F$hk!>McayQc-fX zG4T^=PrJTWZ%M$Dk~?3=3ndRxtTk~x1sDen+1#;`7p`tDC_i~Uw<%{%E#%k)4N;_z z_)tnv*im?xl8!7El1O@aGyS7~IGQjYOtW}QCLL&lSy4sKpv6Svo^jt{&0WSWE7RNQ zXMJeCYGrrXo^syCBq=k^Yp6WATl?5g=}O)aItJ~NH7E3x z8}7cCYt@eC%a`o?bs;BZps4ykulwV3IE$5mXI>v5XxJ=Cr04q{V(Qe{ zvb9mW^n%H~#z!b=Jc&9vtzLVyF4!#;XvUS5&QQ&bWwTg%>MsXMDmM6z2`*d02isc{ zcvhQ7c_z|UNda0@4gf#m`nu@Xjy=ZvXlLnN=IM{Hemi4 zp{UGjCfaRf4)yUwY}n~u^YVeeZ$iW^ zBJBJYg- ze9E0S`OXy%=;XkHZlWzF?aR*tR<0h(-U%rV_r3s)Y;FWZE`|BfwE^`>^vEF^)O z$G?O`1dT)^Tnoa2I-bgJ-QcXMkFgPchk`ET?Hzp^jQrhRy+6_m*ouH-1_r)fwmS?} zJb?;5bHvpBxA43%u5OxTg$k_z4Sy9Fbev6$9+E=#nYBHUCBA%jc+K1j;cZ>d*kh^| zaK@=6K4SWaBx|k1cQmm%If!lY-6Zz5b~mXq*LU*GXu#0OFH^E2%O${JJ8Z;xZIj6Q^6sgRB=E;`=6Nfv51nLu&4KRfVORYFQ+Dy#DzxBi+9`b~5tqoFmrpcOKzZf)MeQGfnzqaf*ZD!X0Mn))xrX z9{!URDm3nK7?i`DeP=jaS#d^nFq%?ibJsmLL)YAbDiZpbZLMm{d38dM=-A9hczOi_ zJrLVnxOrU=-@zPW2*M}E4}nd3q$etV1g8C>F=;)xZSXR^PHBCtrIMS#5b3_~4Ezt$ zZ79KZOS523`S}NbLE>}C036oYS-{Hl_MbMkAJaqSx6VpGrkLk<6q<(|_UgiotcD%u z^)~>@_N`ma;Pv9otwheygmDX zbNRlWqBq|UxPMeRPa_5FabGU5)JXqY<@{&kSe(BjJBC(&Z*BUY?Sy#$t3Ts6_=n%6 zp_8Dkwe?r`Ny^;D_^X6+`7$E?-wM+#<#QQKespf4h!cq}6a?$@B2~4%C5?5;#l>Ig zsdAQt1gAZ)=g2F)0?ESXlK1Ktcv5SHaI+y6FH^L_i8T4VF0|WTj?>T6&;!@JyguL6 zhDE@=p)FB5O7AFHVS{vzM*8Pvt#qm&HCZK!yVXnCSy(fxB-$pc0xHeJs=}SAtwetj zkV6-UzNMa%*q}Vb1QF@85!^FUyMjId8=lOhCZAf-gY1QI1=K6E!&3sGLlOmk4@OAq z(WFBQ%-Ro%*F&FCfz}y!Tu;0+k+X-L!W882Ja3$0G*R@nAs7Fq&Osn7(TIF~Go^q8Za8|$-Iy+a4Qn#}FVY!-Vc z_#iS^*LjbyR1reR#=gN9W1xB#ZSA{A|Dr6WFZAE#NB=U_@+kj|P;FBc# zjcCUc8R9kwUpY=b@W(gv0`iIww^6>ZXp&4na-U+L!?Mu%>JK+t(7JGYGy<=;)3Nru z({qZ=8SrMdj%>94!%@?$xg;yKPQ{Vk1bzpReU66li=+7#q~OPJV3u3A zi_X3x8SOy(_2x-ZjcLjly*Xx9nV={w_A}S>H?WONy^RUwM=Ixa`1N8h&7+Pk+z7;o zT}RTEEr^aejI(DRZTFl+caGt2-uy2y;0m%|!m$9R^}_72QWw|cDjHw#(6e0Mqr?g`$scr<)u=4{sv>;udHUn4Yq>Sz zUX`r*E%BFnf3GI}F42a;ZC{(uMSOwM=%E*|W;9p|xh|S`j8Z{9Gn6KBX-Z@wB#9E! zF?h^O&7(9G@5`(Zxck$rG?*?kI!Dz>n*3dXm>Z&Xoa@+tM%F-Dw)2hoo+8`}gnZ9j ztAy?{nqg`*#ybi*|L3_%s$N#t@PTo6fESL+fz2r;k2Mbf*D4e@;z(1A2tH z8zB6Q3iznqQ`558k0)QV*-fY4ZdYn*zG;ob5U!z{KvU(!ORKLcCobX+;)MrlW1}> zSrH=e8c|$;!6B&1l)RbjdZ5I=d{<^XGJnq%_QylWR9SQx@(fH+H-TBRuCaV5*We^W zquU6z;NCX>Nqxp;?>wejhO_ zUOtEm&3n&T;9_x>N=7V%KJ-yoiw8I}yf}~w-5|Ev$a8HxCA|Dy zCs>h!Y?ezghb$^;EwMq|q^By0S8#|DwUhIVdFL$JN{jN4_>Y@VzfG7tD0T>{Cw~F; z1=hu`A?e^NldDOPo7C?(Y6Gf--9~JxuJef9!-|x)CSlE;I1g7RS>`|y`|2sVKg%U% zX>U11G92lQ7^KG$(Y6ov++o|(KpqoF^|59`@wGjnswGRok$8swF9?_FnvD1VAbiVwwF0*+<5h=aKy zSnVTXx|3r2nH@&!17KmD2VS<#ya zy^Bgq=tFov5dCz`W`p6IF0YK>f_U+jK}valfCKsZw|cj(x&F>JB6O>;SR^*@UR?_O zbakqF*)zVUu7Oe3qKyc=TxJ4(2BZ;Ct_pQ}ayU;MLANSg--jGj+8jR37wsSMv* zKpgz+8R~L10&WiVCRf^XwT9^|A2}aN1oswPx0KR)>j>OIHS!CzycvVnWbKkA3iPF2 zu_@Js=HrwDR!!1Q#8@gB;Qdn;oiq?F^$Z1;e&z;K8)^Vy@A+BUx8;+)e{6U3?0fc8 z?Qfv2F@4>Z9%%R0bviB@!76IIFWcsv51*t1a&Ox4i9pCu#8>ntdxK1TD{-k=voI4} zB*SUFOgV(&bk}7$zB%J2FdVQvJbZDa?buE7cj{k-yNj)kWr%D23xnPvg)yy;)AsXw zTW~{2V=HP@hAne3lfrXgfu^U(xGIKvrKoDg7oQc7@4m;)+p0M41HAv>HWtVDBGq3V z-03e*kbfT}|4TaZFCmfN!PMFM%TQC;&CuBH|8{e;V)5)f1g?~Ba<3oxdMs0vZ zMu-Lw0ECbdh63QPjF}2d&Xa9`dy>fz;e5XFCf4DAL?OccneBdjxxRka-R9NV{-(7z zD-^v$nV2n2bS9IEGfRQ=M{1tjVBW>s=CL0?*Wkjg&!#X1Op3T=hBg8b7ZS?S`?;`tlS(@ zA_OF@wBb-?^%A1mJAD#u$G%7Our4Yc(>EA+;T5V9!Uu5+R^?@7cbP1a3ht33Nf+C) z&GB+k3H6cYa0@7u@Lyx(U@r0s&{LFj>W}3CSNhFs$Bq~8fjAYSWEdAt1e$%5BvPWU zY@^gF4J%Eu|2V)`YnDW%FP)L;SEl>-2gv$gWx0Pj!2iS}lfHClUkBHf)eF*d!}$UH zCpQTm$vAK@my}eJ$?ryI*g4s1Q(^eN<#`A0MifI5AXYe67gF41`k3jses}x)2lksY zTXP?wT#PZFdjFegA;N^*EZSH+2+4z>45vLZ0C3;hD?`nYNFjj*2~tj!48UYSm<{Oz ze^2~*IrD)pSK-ck(`BI_0Ixmry19>7y3zfTTF8ZJh&2vU{d=t~xsO;NZu%7>v4abq zI!lb$&Z2%+qtsb(On9eRyJSU?CtYM>B05Si^B7f8gRv_k{qeXkMk?CAmA*#(*}xf- zW?Q$7?pRr?T8gVDzJ7cL3GV)m`6Evqe>QU7`Grzy(~Z!(b3ZSi4Pg9eWuXq*xMWG& zVM~`H0RmpxcTZKmh?WO}`s++d?!mdVGz%09bCn5S6LXaXpA)kTGgdq3qOW@k@8sbI zi~Z%FI~KUvauTJ!4y@yEg<(wpjRTYYSC}blsv@Z(f54)V1&a47wW(F82?-JocBt@G zw1}WK+>LTXnX(8vwSeUw{3i%HX6-pvQS-~ zOmm#x+WyDG{=9#!>kDiLwrysHfZmiP)jx_=CY?5l5mS`pwuk=Q>4aETnU>n<$UY!J zCM`LAti908)Cl2ZixCqgv|P&&_8di%<^amHzD^77MAEgHZ)t)AHIIXIqDIe{yo-uM zL9f=qnO(_8(;97VJX}35$eJkyAfs`;RnL}rt*9hz5Xs|90DiFC2OO@ZB?l!MdW?Y! zVeW$Z2knWJ4@RJxr@0!9%l(-MHk=DYEl#4ev6Ge_Ebr~MUtrj*0P32f95h$u7#2~9 zhM|KP%(!GKDydv2y=;WeN9p1qJV7#xf~7NO6RJ*n*61NJ)-33TQ{}I zRJO7(=F0iqd5tRKCuN=Y>ce7iLGXL*r#jK1o=E#$hpC0Hw5mjjMX8T9T&|4Dal3CO z$n^Yq*7KP%JSfbV_NjYZf{9-%L2-wibG3!?PDz21yQnBSK{$cw0aS!b(~MH%+@Y^g zMbh^HDT{IkJhPp#^C~#|0yC3^d5Arm)5NNiSpq25j%UngFeBVnu~h> zF6a63K7QC#d~?Uq-H#2|W|=~t7C;0wMBTC6W6CFDxKLt2tEh74!D7i0?eogkWEP2>jmm?Q?6ZS)p&ZkxzP?QLz9V1yTAnzUG107^d4Edc`eU(7{J!5-g|<@s1*(lgQ*l63GoeHDU})F-AHL zvTY+9qB`=3Fo!*RAf{x*KSAfbPOq3%0h!l5u^eIT#VnZj2b@r(B}rE6_bCSU8n7qu zdec9Hxl#li5;L|xqIzgWajIz_wSJ(^J;CDo#OQT;>isx9bR#bKlQ`G@hyd_j7v0XU z*FuwLt6w(Lu!EGE2Wj%0P4wtqSqlayo+lvv zvIwLW5a2I5Wvx@<3FE9`l67?{Pqta37`H_2r~Rh`mvn?bJK@;O)^qixzSP z^P7CNTSUwq9Gw)M4gTZjzl6F|Dw_XLZ+{fiP*YDRx4HEw)6&%LXori@JXVM&1&$2V zCl9%_tkT{{zQOSrdbD;S|Z<8bkmY!{JPNXC^QcUh(0cJobNZ#riP{Tx=a`7jDT(xzwJmnVm}Q6nGa zT%9oRYxj^klt5N6rBVfWzD|HYra%E#V{M!|U{lqAWU5u;2wSi)CD3xrI}RgWkKKi* zt118z~o_nKw#_j#v?MmwVR4Y4%(_3PW5iE|2cLH5fIE*5dkli zhMU*G#1uhwUc7sWMQKdYx(}>KKo5C^Na{U&-}Juh(tJ@rJN|MpKkE-g*?$uEfI)Df zEKxb*aGUWk@AbOG4U4la2-@}0F=Hic3Hbt1$B5!c5KQ?(k1sgs-0D%@;n-Z!;Cq{_ zBxJAabMsyPcV@;G1Rigb1OIssZO!;$tnF|9-D0Ch+6n9!tdd`(8ByDFFBrN*Pw-ox zcV*7Bjv^{JEh7HuPApmjnY9PxmQ)K@DFj4j3(eN;VU44QQrXUERI5f0;}m-Qhavv{ zAo};V$FL>UK(bU-j-UyFc?~OsvWG++(fb-0aA?&mKI!s`30^Wcl%YSpWaxX6T@^c1 z9B2^VL6{LQH~s$jJ$`4p@eN3n2U2DV=D-vsx?58lKAsCS!SC4v^m0uDX+)@O*S*6p zxE&BJ&X}FQ`&WGT8o3PW#xq+Lc4Hrpp9a6o_4GuWGj_K@^PZT~F*)^q?e|>&QQasO zz!YVY&QCQ(D0S!VN*Dx((~2}A$YsEKa0aLWn#Aix;u5Zffc7dqF+dYcNSDBMynuIX zQZkv0a*uw4IsVMi4?Km>!1qz*GL=a@C11c_a3lYTCN&~ZuiavZO-Y(66Lb)0HNv#0 z`wt#_)H7j8^F@hB{uZPB{|#F7uNeJ{B02tr&7!1#Zk!nTbfl@$f&xVW!9zeWr@{_> z5%40FkfMzLCVdd4zSfl4>^b%D?OmojR)}P75Uw|bVR|d8=oe5MQ_9BG^z@sHiHpnQ z&dkjAw<9|`h=AIiRusuaVRK0h<~pLJrt@$Q?RJ$i3(W|bDpI93J*qasul!Ax-St@b zT70z{Z9$Ac#uW+8Hp8cW+BEZCFHLQE003gFJgjd6bC(a>_%r4gt1PIKDxdlOmG5bxg!q%}OBBmE^em zMD$CGBvlqmJ64Hwq#{I&4eLk+K>MijQH1o}Sp;1j}*B%iMG#<^c!LVvstF3s)e4ogyjcWT?4>;2{JEMM^F`i ztl&9)S?Kp*~8M)+^p!-&4ec07Sw$10W>b#&6n%ipaV=_5%8df_LS_JKqMhAo?C zqfLGE@2z6ldhp zB1D>7Em+1(_>RhmZGt+*m*>vO9G<q3-DZfdDKlO|pcqDz5KKociyxl*E4@0RqM*whqSsCQV%`BALQ}T07Xe zv6IXT6bWO|KoSQMh10z?M!+PW0uSf#1-I1kgk z$8cTzXe9WR9(n1HVJyrm=o%KA*Hs*XgBr zE~W$D{Akz4%O;jWEpVS~xHMj`dsp{o#$0+@dXX+_VySrh1<6m*YPkmw4uPY6vJ5|> zk3;DJ-lbq(C$EXJh2z*X?*4$HJyBVmnoTqFT`_J95tUE`O9u=LU;nba8?|q`5IjUX zI{BaGy-liq*$IgD_s6J_j=g@C%d8izHOUrg{RJtXW*OPMx*~M{ZIa|kJrE^ zZ(;A+Tvr91Ir=~(%4j6geD?WU0);@_g?gbbo=l=iVVjjY6%Lr~YRs0YC@-KA`pP|` z>K$Ca=mj>xP}M+LwguRU`7>bsXU^y~bxIMUgGB*h|G4G2z9$<4Q;6eyG8fq)kX@0% zwGHQP*A3~Cf|`RB_Ob%FYqQb4%8MAsKvVs9gj>z9HSWtP+@(LptM+K+Y_h3aH9hP# z^Q90YIiG!q(x%+4Vr&>svY;)Z&Ew@1EoHHo?Amx~asX+u?q3v`zgzS7e&fnR$>20R zrP3L77h8PI5}d&I9(6aP{E~wyCdb;fiS9$(;^4JnczkSvfXefJf35vR||0K|IC(?ottwQUIsMi9qL-Ki1PC5|H3*{%XN(vI#!0?7F?op25ln65L)@Tz?(<+kxO<@M9G=^I#=9#3WgVT| zbl4nf1a+Z@&odHk*mqzIJ=?%Y1ViaVpn3@R6~TLbG?~$hX}&VYvoWg7VH@-iPK$D+ zp=cy^wSS3hojkEf*hOx2F4Om(YXd10{e&yT!%sCcf=xKZtyz{x)}4C6it(*XMQ>&R z4Z2SnR+GnjToyoV2iGEZuo%;D!GfAc+?So=e;}fkPp_O|MsuCNM6*e+(Ip-I=Dqy( ziA_?>c;WB1-#U;9w9p~7FQuA@-mRyha=^kiNVj5_bGj0q`62iOw)W2<$OZDt_U2bw z{RZ=QK}G4mA5;YO9gV*%aE)yo&7I6$j1|AWUbHd&qQG|gUmDK;vq(qriv{x|f0(p5 z6$f zH|!s{Xq#l;{(2gCeZ1en^x!yQse=Rf;JA5?0vLCro|MS13y${dX197%bU4wYS~*T7 zNMPGwgSIU0JW2NftQ-3$QXmuq?@1Y^@`;R^fPG&PD=ww}!g($Q^w@U%jh~>J&{$ zIT8p4^dD`WnJ_Z>t>mLFB_6}o5mz%Gl{ncGYtQr!*NEda(Jb9YovwZL-9Tsg=!3Nl&5$2Pez6&4IAf6x^6Qf=1#(zvhhNAUu7#{N>lx@!d z+2KhRXK3(adQQw|B#w9(1`V(JO-7w)D&ou3Aw-!D{s&7PYIJVqQo|)uLy|#Jserq0 zp;ZCFc%J&KZ-~*Vm$tJYJ;QtohtMEla^-AW-eR_`_ipuJ`1HUK?hs)m#r%vaUS-_* z+@<QOd6bSo61=b|nA%cU98n%d+|}3iuZ( z{8|y|Wc(Kyyi_}NMOH@r>?#ywo&q)`n)@kP_C0=jJ~z~WUJzu^3|ueO$e+=ys6z^p zQ`uVC8K^aSoto0do?vf!^n}e&Pbvi6emgpQ{|E0Y-qTPIUsp?cdxMi>EfTK>n^V_= z>-GEQVOL6xug5j;H_O{Le+Iv*Z3DA0iX zHb3Sb%u&(Yt_VcM08@~gL9&uQc)pu7mkm)2gtU2&;d73)p35qTW<8pc`u|WSj&}5nCmZjz<;EMxr zl^p?8=QuuhYi%?t`?^5`>fPlcL=?5&sw70n{tXS9I(P(|C2?whWVVPPS0gYFXU~@9 zjC{H9W=#m1rJ_}^$ACWgAJM(d3YQc*^yKM;$*UHR#$ZkhD8JM-(W{;BZY2Y$wW#bd zXwlT>OFC98rxTg-En@tsKv>>1AlkY#AIY3%lIg3FTe;NcQu9g5b*&bcsIrzU=I3#i z8nu>|Y*v(~l$yTfiuZwyA5s{)-d`;s9gLc273l3pQsn#yLw)m$zh;@hofUhA5iV_S z^Jc-XQ>~@+cQ!jTYg5rv2lRKSMbRK?+T%b-otosVU)L?64nHW3X-F&MiFN$=y<94o zUQldpIV*N1p2VbtRH9#Kj$p&r;g2e(ZcVm;a+wq#hlUi+fEkQ4c>2B}!hY0BP&*#e%)U|_eQgXde%vfhiAhy&HT&-bI#pprT2RHl-n9Or9kKY@ z*y6h^2Ln;NAa*rkeMxTgnOJI23y^g-A!~?`3V~4otb&p;eW9M5-lobP=P*BL2RaxZ3%Wziqya7JN{_s8TzoHXh3ST@OSRX1e6 z>$kR7wI$QYF$t&v}!NXCxg*MV=COu(&$S|cT(SuBvRZ&%%PHyp%;O;VXhH_;x z2HE2!upKD-`%LYo4-j(^+!AN!uZa;`%`G%%&#FDxOtExn{+1$mp2Zq&fXt@IQ+Vd5 zxy8=T8HbuT)*Nf;;=>yVza}=`u*qPzR-qSAEnH34$p9#bZ^G__*EM(OsuHn9s(iSs z@1b-`{6L6cDAQp=<-~@Rg8P;+;HJIPnVAD4Dh;+F&&1@R@G%6ml^W!^W;MP0d)imB zbBq?EBbgVY&-X?b)b_aAoKZUE36E1#{7!D%s3ckf+ca?KU~yW?7Cs%}4bKpA3#HZL zY9w6<)gF>&;-Yp^>p9k(4$X1%!Lb75zWg?uNWkgi10?l4%`F`Zu-y%^bv*Eb-G1bx zfx(%lYkITUQU0wktRS*;%_P0Oi@k^)R&}m?Z&ryTJbM7h6wNb0mMpv9Y>ilHz81R| zNa)#|zlxlfx|5EZ>g%QadIiiL)E8+5jg3iqB0IB;t?;L)3$_{phsj~;UI0o%gKX0g z(gwmaY_#YBn3m`RBz41p#ldnxLp79&YIMO%dpLkd4_drcD1y-7of@f5?&C7T7bg!* z+9O$vNRgMdT#m~Ql>Nl~UZcEw+Do(CxnWs%MNl)erW)%a9eV7n)cJr@N4*@WH$=Sr zAhZ%9vs<41`&UP6;T>@`?np7*dBd--?u-hXv~`mYkhSp%X)aEIJ5@3x@SZdI9=Z7^ zm`a$T8G>!TbmyVE+@a)*=B%I01?eWpM`#8RPKUTB|8^2_5otvAK&gp4QmeXLlLl8< z7q`?^RRNV0Zx>wC?=eUpiywAApVgW1 z26PBx#Gj)=xWi}Wm@kzi;q}eouVi_z3bwY7Et>>Nthd&%~TRU2RklNMo zjR1tO$Zmf2ikfZdY{w4qmcEwuj?VBt(Z~4uu{D*;?462ZUxjtkN26g-Mx^A|7~3vj$%%WKOuq#P1%TfMi%b5 z3A+m!PpQ1fx`!Y4u-@>yAKa9?1&rN1_!|NmOYN}D@6ev!<-68YDd`CqblRnk9+=E&zlax$$Z zEo3QqIOH#=`aS0F!U%onRIz#%d+Uu-ZTV~+KOW5lgf3#92 zs=j>nz*M{C5^SxuTa3NC5PoHADLhR5{6QFiJm3{lXa=#5F|Pw|uTB(`gmtPyy?-|e- zo!SpO%F=zX?002uubhHWls4g@ z$#c|C53m9UmMZnqljx2rvZ|CtTMy21QWa}%;DQqL1`b>3BPxm@4VTtyDBge$=!Puw zyd&F+VEvOtPlX2!>NBKqg7?CC`V+rmZA=K7Y?*qaE@CQvOWin}e)41=!WLN*AmICp zmApxQI7fZ@Fn$iKs11M+Um$0c@jZLYE;LiUT>Q z;mj4M9@HGF55B8!suGMpT5sP$Z0H81g`%akXopX=;Vuyya|V^5eGs80E$GcNc_7{w z^8xFDCK;Ge+b0TnY01uz&_%fk-3~ zvi@tUr$)PwWk9(8y{S8#NB)r=Z&8RFES$pdKZz}*U-@kS(R3c6ORIFKDCtI3bCeVK5Ouo`CNgYaXVC;;%_1`Y%C zS$Gkx5qw1G7=P5+GQv2jWqBM^c;nED(khcK>H|id>bS}R(2;{C#FXUv_o-0C=w18S z!7fg}MXAN-iF$lV4>ADs{#}r_Pj3`vONGc>LbCQ$kqa~BpZsXaR3r4-jfEZh6lG;g zH2?O&x)$tLCc6%_^X-$8UCQbq`iWZf3k_#t`>d-3RZ1*6t})5ZW#k?<7x4jX1;FIv z#JqAvG!v>ArA>Oj^}~zAj*s-^uw4QHo?OwxadvD*vQw8q!$k+PkzQ$ck-*m5V;_V^ zO&2BUt>Gxc!AIbE;ki~+_O#~NVhaYQx6FHt%&w_T7mmi9xrCyXhJ_PZ`?rYlZS;Gx zW*VdJVQtk}tC$DGfP9YCu&PI)g+*tzI1J1+`ggxT`r>R1{5ZK7^vgg50`)~XxH#op zaFi4=I&6N~23d3&(`fqN-9g-AD4TjsqHwXNH!B-hK#bOSvK=vpVyEh|pjvqg?2bX_Aq~vcQBK+U4{r-Z;e{M_^DgE#9TxFsI4gL-&iiIYv zc6g{nT!eB$I+&D&*!`uP%y|6Qh;DOl`zGXO4+>ozdgcSKpd0AWrFrJpE8_Np(d2u{OsCVzDh!qE*XZ~Qkk-UV;Za2i^fWH z4GBwmrBGEgJC z2615hax*kh=rlN!7SVm_!m?!&jd>4(rm^_RjHa;s7IJgmpKidx6*{aw&1Vjb5xBy0^j5%jkNfAs?F~Z@CFq3O^wFH- z#IYRF>aR{2o|F+6=`?(!PHgaN-~%e>IHc&2lxTYNE~aNaMm0JjWHoW#EQ1yr@uOXY zKBd2o6w+Rpm!V{ui6q0wL35|47?O$R;hFf&*I;d1L?g;zf#AW{5r+BsgjI9#8$50~ z&kOiWjaUVk9(WcPI%tIn+M%Q%H=Lk!9ECDuUV&bs)b8?PYtO4@A55o)1xlN-2uVDn zw7Ka-zkOkWep`@x4Vn~s$4_Lb3lX-~ySpE74Ur15s#rZA1R#rs6CJQyr_^D_>jwn= zcz|gF9BRbkd}iENr&_k%#j~p{}>)f0wtqOec{LNZ}B7YKgG}glU<4wq-_`Y;Jx=- z#m|G8r1QKMaQP%WN{5nEP~iRe!q+7D+3nU_iCn2Xt*cmrczfZ_Ai{uof8r?v&P6Cg zbtF{QyzfLBY+bXDRt{rwzUdfr1pT~euQjifNXm4`tZ-zxMXMN(x6U-;z(sYho*Way z;!$Zfczr8%YNuBT7-k=DyG^RowGu^y(QO&%=nRCdBrv~E$7_y&?K!6DP-#b?a_ojj86^W z&>qkL(X+DkI^|n^^#TTQ88cjqV^Ut;YOxE@e{|8suiT~=n*p!+*rx42!=v6v4#vEx z2yh*NAiv>w>={9^8@c$;SO)UNrtQ@wk3hM8=^JP-igxR51Qx_72dHv$GqPmq4 z(E|^Cw3ope@#CReHwW%Uu9gg87a=azdA81=6> z`d6FxKgOtve;L#%YBX0`mVrV(g+b2KHd6WQh%WsAkdlHhrDA&huJ59dZ2q#D_y4jm zhw@4ilE@F^?d>rVI<`>-2@eYn*~;?#ilJ$33$~s)JwT~~(t_b~cLBvDYyCPYDw0;> zGagu>E}CG;mmJIf+ZGTtbti7W+rR}dq-a}+Mjlo2dvDV*=L6q@e<3DQbrv^uHWOTi z&XW0)=G8upEJW2Hyu7E*3-&)Eg!Y*Cm!1c;5PiYrE7+NQX?p&Bh50|`)Bk3cp(Opqr_p^(+Kr9X$+rnLX&MeW5Zt-D}b4V$BS=UJD|xt*F3*Vo6OHIj>hb z@3>|ruWGipeZHv;v_nka%)?nkn}u6wbHLaWC*1+yr;4F7%a1vPd*_LPp&Yfy2+EO zBsv&8pr30tVSW-^u;e(0PH!WZzc2s2DJfy8-d^JeU)MhCJxZZUez zJF5P5ln|;{3z;aB3sH*>7p)^yOi7c|Ia7nlM^IU^Mp>LO^y*1%al!pk5cX9Z`8J95 zt_qXct{-X)mk2s#Gps{N;>a;1F&d-Y$lfj0GWlL<)IUaumu}UVA8U?U7{6J!0CCqq z9vN&-9eW=a+N5h!PU$TmkrW#ce&^X%RoZ+F~T?ID_qB<7o;6)tE?w27|Os*&^xT@2LZzS)!=F9Rs>0^B|0u-B}( zNl0w@E%`{tV4q4{t{__9SVnWcNEc?!;cl=6y&*Vw9Pc07N2Ov@%v%!fnZhC)wX%C0%n=#QHv5J7TY8!vhxp{?=|zv7 zAEG-l>AX-1l3ws!-vLVLAv(vo8p4K)$v6X%<}{pS8vKc{%CQF|KZfD;Bq>oi=_`D21zg3JX3?P=l`+lVmBQ!pkr~VHokJ zkUjk=g6YEs30vQeuhMQF-A(SCx$7>Tpm87k%W?nw-!JliUfyGe0OQZm{Xfdg^EfER zKtCPu%<_~V)vqMSAQB}a7PZV%Qm;tm%IS*dkLUrQ>~{qqzMyjkBY?B%eG35?O&kW}0mXETeorvq1l6J1rIfv^TUGSBgSo70>;HXQrLxnw#l zzSR3fe*g)pStm&xV^_TOqpW~Evs)ooSiO^JRga^PsCScYkR|wtxxRc;A!_Y3S%%h> ziF!I)cB4pSS!2O`D93)MG6F7UigV8r6_L!_C@>`!<>O2(x?eG zS(xrKNzk#e2;SgykHF$k)tvEi)JQXqe+75%;zGtiDSmBypv(DEa%x+{Q1W0jS2^Ar z;YD~xkS_*DhM;Kax5gw4>v^vR`?{Bsf<_TIx!qdaz5peT)}_<+*GaY^MaJYf6k3+c z1VP?sheS}%x=20boUc{2NQYcrsn+u6g|QgUn7Xr=&95h=PS2`a&?ZI{Y+fTY;n6nF zc7mHHa6>*W)Exe8+i+#C=(_{jHdOrb>P_a~k1S=t>t9^Hbu0hz8K$a+N%ewu2@#`4 z3l9D>qu&b{8dyP8AW{qdY;4u+9>*O0!Pf1eASy#J(s!`$;MxT4huv5=k9xT05S8Fk zLV}SNK%VL!I9b1Z;9j^mJjM62nGYrvabBqxRa6r3P){+cB(b!c#E1{EA9C+!DM+(b zpZ4b-On~nwlXTihz8P~=*`>q)xkz4q&ZgwU5%)XD6s@2@2N4Y=qS?{wvuDmz`uS^; z9S^@prtP4EZ8BwWEjPltC?sv&m%_e!gGX31f*cO6kCtHR66>eBX?(4+7@=rPAs!^n z3spoM2EfOEfowchCdA?3?LF7Nvl)~lWA=t;HjA1*k2C~3OY`F6rva(4H#7;73O2hd zqSTbHq{@7Ug6b@kVXMpX?I+@xue3xr`7tM{>(pqa=9X0oSUxpQ3=hShumN9(NinFl$s?Q8J<@-6+ChwFU0UJCfs*;U-p3wK6*i}AC@um4L8yQV z-FS*mbw#A8CzujxFrLzM{h8e1v(#{DS$0d2g-2;uz>SIdW_QyfZfW-Ru;LWh%Th}z zr$(}3W%cmo*^E9w2k|l95$0#I`71Zc^YBZfNl&GI>=mER>y*IJl0EX*@3)38W31=~ zv4ujAYPVOElT}d?Bz$W}jS#G|d;0)Oe#}+DD?EgL)-kQr(2sUWB=@sMAKQnG#|7u(x2 z)M#MD`z668XwdFC)-^2vv=+pR_5hP*Z|e7EC;e|Sc%8KSi4e}OlI`}nzg)S0xpiNE zVnyI~LF5%`_%47>P?Tvx-pn4iEX~*`v9cdQ3Gf7GVZpetYI47%6yDJR$Gg_3#jBwM z#(yXZI*`c9x3a(R7}q;uV3i*C!&H#2MFsB?Jah-VTPg{$PNpyGAYE~K&_|saU3*pd zd6||7FO*H#WS{(r$rK~lXnF9-LD|WQ)r7UJiwUOTgDc-uTzAb6wHp>{L?uwmWf$8J zxR2V0yw4>)QfKg4G!ai4eRxQXU%W)F>B1@n=BxO-zs=t`91mx@sZ+zc=nxD2Vu4m~ zZYte|mCV@3kldi~wGh5GnIKHuJD?iJ&rj3A18zh<$PUuq(s&w+WzO7yB$XsgY8tg_ z7SUU^7u#70c~jRwPBjz<SJi3`odU zmq#fdmS}~iWq-w}7N=m$Vb9@WrM~ z{%r%(NO6`w6&H^H&up8LT@eHaiJ*{+-ay2}+_%Yw4KF!i6KTnT;t0g)7h!NonrhEY zddbMJq5{g5z-p={e2D-PBlLv>BXb*>vS63U5Q^0A1~)93xzR#IkZ6T$C7xny>tYbOh!m+CjB#s@$O&J}%2rvMwpjU51_{tnM&kfLv(F%N80N!> zVP}2xs$MuVKJlG8r`0aq>WLQ5o(l1JV;GE4z~nqX&tCVN9nKDZdc7uGYO10PZXO@= z@s{l6l6nxcb6Q7mkW+rJbB}ntX<+tJ?CD!Ei(XkoUP#rqMRfQ&oxVQIwY1^V`ssu| z7vwl|$rf4gI_t2;;%~G?i{Oqp?fHDP5SkfBi~;JOhg0-|wkH)bLT(9^Jx?}$Tks<{ z&nXBBMs$fB+hA342M<}RuV5j3j5x|17a5iIO4U_cYO|F(onU5Q9S&tJY^cx;0}m{f zsJ`xhI^R3X~j1MPVe+zPYsVBQw6SU!W%4f%#@2 zkG6br=Z)@*rW@lfC0>^oy(Q-;h{vhk5ibfRGp0(0H+y+(7v)#Kq2a$PN&A2Z{nXdd zstoxQ5nnuxrEDCggii_RS+x8vO5D8~*u?>;Ji6YorzD76-iwB@9qVDXJTnTej1hWi zM?u|WwAx&4>jD)h`g$}llxvrCMD&a4<4}eZkC8e2 zCepXI)#OPr^e9_{ zYd4Scc9b?M0?Jz1lkfc3fi&-&*qbxPfLgdLG8~pq1<>iZ$_`4dIZL(Me31@#^Hxb6 zwURj`a&pz#Z#Az4VXv19WtoC$un3pY5O3qhtj8$vZ^Lipbw{UEw$D5T8T(nke`NNn zn!9cjtETsmx>VAe>n)DGY(?0+mG@-BThH473ZckUtQ-)a>9LVXS)Z5%IOR&y_GN?$ zC*s+#d=a9DxHiygz;9mL?ZK+bl;j-y`Oc0 zvPu_k+{!kKw)47^1rj0BX z@zvAzPeR^{BqoO}bT5e8rSTAOBOYQ6SGveRQqE0;Be%zu+vW}!wJ z*GFPOUqaXO4arQg?Zj?+4mo#CMpbAcBXxP$07>Q1O-$9^sPFY=Hcsx4O9L+TIU^raS#^ovwxDwoPDB(vMdHzNV1yxNs zwT0D=68C7?L}bU3t+3}r*wjmhis;f+eVL-()6%cwdi3dMrKhrSR#{CK*G(gwBI9;h zG&F~-op}z=mcpJr8hVw6+$Ia;umjKWAPEXiO>=HmvtHelBsjtNGLF6jTazN?UQEh> z*R7gWALMr8?S)e%Fikr#R7s;9dj;uG@a;msE07M;{L+m7!r-wt`>qL-3;{Bmv8h-Z z3di;%JyzsXQTNmj(OPJVS7hiZJ0F^NHB-)O$Twv>>kD*7Rlh=h!!orwe{1@drC;^GUBR&u5qtIFNF(8ji_75OmnK6P4q3 zCE^BD<~IPPp(|@`rjVx;HDp_xw}x( z7%FkWhm!4e4Ly@*8KNAoqs#wBuR-ouM?bY~-Lna&)8@xdMRcOAurIjB)H1~Hc7&|{ zLTOd$yK9>8IRNwWWuYOrWq5+ac^-X}WHl9g>e1Sf9^d5K+hZb+OsWjRHYxLYmDQt0 zXzNU*3vJa8sYR0QV5w?%=4E zN?&Rbk>-u)qG>uT{m_YTr|yV=n3{U^sbx&F-m)DRK&u$S%~kGs zTH$)RCwi%PJvT>B2%>VFUw-ZsJ|ea|LgORx>|rQDNS8OG&*&cTl2ctYk-maGV)*{l zv$HFM!fJ8-T=Vi3`PG5bIn*FYm%^pn>|U;%;sMe*Mh1b&P%(G7$L8r)fpf;^8wlA; z^wp7#QQ~XTb+$`;U-tFv8o<>ie(Er}K*HC#xSjk+#e*l@eCGw&vucjttCh=deLQPM zjh~b$LzTz#oGyRL3vP^rn93<#=#2rB3Voyka776e4|et;InBp7#BIjKh~^I^pbFw* z2|GjYx#4AAtm_IvN>N|Dx3(JCw>HiThEc&YhW4{z ziN+s?4tWAr_*UPsyxi_>7*LygZXy^_JmmX$#U0h0GR3ANlci70c?Bb3>R1#>iIjAq(S{mMok@b!UR&rJGT z!}ajGkq%L`+k4r*bERW&J_(H=9F%URu;XHA+qUJexjGD(_b0VQ`W%rci!{rgl7!dY974z_%*3gps|ODyecqNgmTxu+K3iNgXAJxf6EE zIW@ei=IR5ddbn$YESSluDwtBfC-&&;5;-({8s{PC)!25X1pthkSe5eF)heGVWp!<# z2Klm2UBH3FLiXYk>hf)k1jo2(6Fir&U&s6}RggF7(@MR+Q=+b8>R6eY~V* zqnNH5BR*k_bSTAWAi=xC^Y%_gpqJ86!QAc^~^Z4Ps*iwxC7UZKqX z`NDU`=UMisO?a@SRa~6b&9RGLuti~UhoXYCr=nE0Zay5PY zBs60NHz?mxeH?s~AnqWm>bl@D8LG}_K7E(hwbBgMJN)05m;|g;WJWTNIpWm4vdn`Q zzKUQbYI%f9>bN9pRX^c1Z>0vsv9THMkMAH^69^b`dGwZVke zXqVcM50=?#K24Y*ZED#fOPCus=jKxw^dU>&T^VMhON^LMz}+vbR(rp-zfcu#0ArAg zPP;--pt@l}T8paV*uQ;B1SW6$n*6grN zT_-8%{EPgSIU>?VpzkpCt>@ciw1ey4{GQmSudb_*!N7o2zq+US+cS~h4nhq72(P|l zy8Hc1q)f%^jw{&X9p+%4Z+iqY6|9(UTU8W&ZImux1p>99F*pUs~&uk(wa z>12FgwE}zcH4+69@{*o6aVpf+c=QG1=AanyO$!OVgB88LW*fy4t+d?JP~E z-H@H(fW+K#3ZzigYJ37sxsNa%*63-SbOyw<%rQjAb1G6oGMchB9n)%EvU_i9_{!1Z zP1kUI;zmRS$0xj0HmR}kJ$9+>dh@3&@cFEC73}f`OpDmH9s*Vfr^B$)=er1RI1oJ` zU+82p)4mo#5eW>CnI=J&J{}gWP|mc(*n@o!e6g3aA<_#CGhad+mJhRMRY4*uKfkWA zJ5m8Y3gZYjUv18=KX(}t_AI3Sb)BYfKsfz$s0buK#BO-I*@mb>=1iPjZxs{|+Ix0) zS?6tE`WIQxd|E;h8?_M4c1-%9jHNPjma@dseNphP`SLiKaN6~}JDo^7sGekz4#2s+ z>=fprK_0>>(YGjpmmjEv@{P$M_6~QzMM3y9nL=BD>5h?u5;mdE8veBBfC){DF4jK~ zHJpsC{G5qAnc&j_j4X@@=E)e4Bz}vVb})!oHZgG+_Y@~tz}R4HVB>;&fn#-E6M;LF zVtL*(5b6U-uo^}T&vl5O^2$^9@^3v=$Riado%qDxk0R@g-0xV;LoCrR;U0_@J@C z>uGtz(a|tb@8>iOlvwP1!F)DSweafR0)+G7bdp3}O1UJCqPDt*NI)cByZP2$V>UNM|uud8-v z-64JmvjGO)LY#6_cfodFPZrAh3%xuD_Jl$+F9Q_;Io?g>l+%m-3#qRb@E%0G>!GEO zS`}F?6WL$&z@@5w9*}uDDAqC?#CszTL)OX#ITQ9}_?mRhCm#DTY)s9PDE0(W$SC(`6j zZ-co==Vd&6!B9M`$+dn}z+<(_kW@5;*F%8Kc z_rTY}>*1bvz+bomfD)PNYATayfBuov(FS3z3->J`KSGJHhQQW zm+?%nE*$Dl@ld%WwmS`dP`x*fDSIp8&ocBIZ#tZTx*=nh>$wpgSxI2uXFYwsj!|Fiuivcw=)!HRLSB{Gx-<@~n!QqZ z#bNhJEVwX-OYn5C*?`inLYhIC{gvcZ0eYf^8$lu(AI8@@`i6bz^z=j#mZ^1!dKGfU zVuXm;7#paZasHS7qdg+&@_^P*tYRe(xdu=F9OTyb_Lpz+hRZM<2vQ|uViE@X z)XMpMDn@W9HkHfr-Kx)+ZsOY0W200)HB38EAwE9JR)x*<)g@1QE;C`f&khyo>7YG9 z?xRGIdkMRH0tSwsB6)*02Uy{Sg#dnHP8!Ler-$cGa9u){}=A&D)}f6^Xnu1jgvk5Ou%ju$#HX z@C<&+l_|L#J)ng`K4cA<0L+$vr+(kSlOC2C#8cvHfqsXT(&D!R52(@44LTKIW9 z&s?K0TJx}M$37;8NcA?;UF(MM?t&qRc>Vb{G#HpGXhHqoP7gePcSZN7#q@W_p5K?$ zv^$rcJD=eM0JW4igmOzRjF2XfHsmA+L$u2;7bQ03sWa}ZM3Z5YWvwRqZLmP<`I0XM zjUejD453kTbraA(087Wwac|yjuK`3{d2zK&>4i~Bd%#>eRTk2N+pL745l#rB=w^8+ zCak8>KT?A=Zys_a_FiS#nEPF-ev{s|gQB39o^uAF_0U&i(YeoaSmde1&TZidreo@# zxh-ZIvsO>?(~LG4H!x!7=%twG-trEw@~T12jSWdUhD-WzFHG#RLwk~_8^Tyj43Z!` zgH}E!E!7Ru13m%*)URJ=`=hk$KEuwYxkNU^j`@&LXYSVF+JA;Xf;{v|YM#ngD$$J* zyP|~0=Htq(IBGU-F-#K`lrFXunVUEqTAl=kVp9G*jg@Ny+kCkXEy$NWguW9Q1AuM; z2p!@iUj)Js%Sr&6oEsQYY^njhC0$IzL!I?GZ+OCRUd3O2U=5>ml^_d!R3AVN6^amD zU6)DXP1Zj$@ud-1E2L(ebi{+Y>|ACv?b?Y9s5aKnUw9cEAO^+OvePih-?$xC>J!fz zVACH(ElWFliv?cC4|P}X4An~j;&!Z@?eP?NuYi%L+i!l3o&Ofr|; z)tY=*7~}O(2m1R4_1DvZ2#Z4RjpDmlwOoxaA$W7ivDY?wZjPs6w0NRb{2c}SOnY+! zH+i2&Q^s|h;>+R-%A^rh+4(J6VP7m6MvieVeGMb^!VWOS&q>>w8ev#FuJ;=x(C+LU z%xy7P;)j-FszyuW@0fo#p&Eu~;0?I&#ga`6xaqCm>$IA`p5J>)n%)LkncfAHZ{z8cLT!f? z7+w>pxMXWfwbk?`EL5zwbQ#dMU5E#fpO}luPRNyVUBvgWT(01H-PDQ8{2Hh<9!T zUsa*7eD#3U^poU!)1b#rv13vnn4Vy!(Gj7gkQmPDiz-t#Ts9VgQ!$R)pSdp$ThJrZ zy2-|~NOqVO5L*c&_R0!%K#P5h;5Mco3E$)OxiJgL6WufKl@&|lGhKtx&#y`h9S#p* z^Tbo>GA#^<=>hsPJp&WE4&>dcl^njftX!&Eo=L(^Etw5+z!Y!5aL!foh9mT)0ReyC zbJ(V$*ZcT)y}vJH85jieZ(#qWTcr5k_5Q=eZ}+}Q9#O7&!@Zy06ttL}UY%QEH3Stw> zQf&xDZC_&;N!AS@bzD#%c<|vW943zxN5W2sY6AC-P-R)bD^YMMS~Zd2ij*zJ-bJqy zIcAuom)kUQkZ-b#Qa*-=vc?3zS3GMq;Uz1*y0+clRJO}lM6Z@_a)Oi8bfrV=dI zG~}ijJz9lVr=Z~rH8cl8*y%Kzj_4}BD+YM>Y#{)KzY1CIe#C1$fu?WHuE9GVY z(oY&lK|24V!BWrB2=FKP`-O3SDy;wK!e&+s_Ij`NY|VbDhVmyhCBIVhTb<~gZ1t?I zjcosuw=WZKvX9)J6ltO^o`=DX}t=rE^t*tB>tZl78`t8k(?0#iCkjK(J$pArE z*_!;RQg{FI!`dK*se3a1M+rS^Jp)stUlv5UR}2j731~FkLH$wi-*%MTUlsq!rjLFf zrFXdj#-^`(gg`5oE*u!xT{^WN0tCOy!t|$F{7@rgWo3VtC%{@p&kO(xm;7&bfZr^7 z4}g6~I2#pYiB*s~mLJ+dParri=&ksl03t@ldJY!$A|QSR3oAWC5G5Y-?>otd`Ui1! z;9x=etwG(T_>=xJPF{-;WryUFd3L|}JA^slXOKb5+`Ps+tX^UVKL{!-80RM5`O$Wk9< z2{LIb13e27Gtk>$rtk1yTIz=lxt|>tWQ_j^5FEhwPqF^G758%`-es5lAwclQBEQi5 zaJ>JNYxZI7@26$^d74lJv0MI6Oa0LUpe@Y99E=YE?x#Yz%kK6=fZ);~=g_|c_&L|x zZ@T}-N_>}0<-fwM@(bN}sZ}0U^M2}wJMQuy0t65EJ5_(5SmhzueF}AumH#6^@B{U~ zsrL`CfATr;5cWRt_s?y_(D@tKd)wCk!Pfo|>^^Dr9hdkI0fJBI{&TPgd*p{8_i0-1 zE(LxF5Ij)-pM%^#&v=M%pJejquDUe&=Lo+$X8wZw^&#wiWK JS$+5G{{hr`vzY(@ diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index fa87ad7d..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,2 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw deleted file mode 100755 index d2f0ea38..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw +++ /dev/null @@ -1,310 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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 -# -# http://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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - else - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` - fi - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" - else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" - fi - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f - else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f - fi - - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` - fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd deleted file mode 100644 index b26ab24f..00000000 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/mvnw.cmd +++ /dev/null @@ -1,182 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - -FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% From 75f1d8c3ab311818a5c8a80e99e30bc33f4db81a Mon Sep 17 00:00:00 2001 From: buildmaster Date: Tue, 15 Sep 2020 11:51:53 +0000 Subject: [PATCH 09/13] Bumping versions --- .../kubernetes-loadbalancer-example/greeting-service/pom.xml | 2 +- .../kubernetes-loadbalancer-example/name-service/pom.xml | 2 +- .../kubernetes-loadbalancer-example/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml index a8e2cf79..648e4dc2 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/pom.xml @@ -5,7 +5,7 @@ kubernetes-loadbalancer-example org.springframework.cloud - 1.1.7.BUILD-SNAPSHOT + 2.0.0-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml index 8f982f69..a95e5320 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/pom.xml @@ -5,7 +5,7 @@ kubernetes-loadbalancer-example org.springframework.cloud - 1.1.7.BUILD-SNAPSHOT + 2.0.0-SNAPSHOT 4.0.0 diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml index a2cc919f..048c8ff6 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/pom.xml @@ -5,7 +5,7 @@ spring-cloud-kubernetes-examples org.springframework.cloud - 1.1.7.BUILD-SNAPSHOT + 2.0.0-SNAPSHOT 4.0.0 kubernetes-loadbalancer-example From ca8b89bf38a2207dc0543c04c5589c7318ce56ff Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 15 Sep 2020 16:48:48 -0400 Subject: [PATCH 10/13] Update documentation to add note about refresh when using mounted configmaps and secrets. Fixes #579 --- docs/src/main/asciidoc/property-source-config.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/main/asciidoc/property-source-config.adoc b/docs/src/main/asciidoc/property-source-config.adoc index d3435424..9d3d102e 100644 --- a/docs/src/main/asciidoc/property-source-config.adoc +++ b/docs/src/main/asciidoc/property-source-config.adoc @@ -279,6 +279,10 @@ You can specify multiple (exact) file paths in `spring.cloud.kubernetes.config.p NOTE: You have to provide the full exact path to each property file, because directories are not being recursively parsed. +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. + .Properties: [options="header,footer"] |=== From be52b0eb501d5809c39ca674f1f395343d38974f Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Tue, 15 Sep 2020 20:26:56 -0400 Subject: [PATCH 11/13] Trying previous version of nginx ingress deployment --- .../spring-cloud-kubernetes-configuration-watcher-it/run.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/run.sh b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/run.sh index 3f266f2b..5cc30242 100755 --- a/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/run.sh +++ b/spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-configuration-watcher-it/run.sh @@ -123,7 +123,8 @@ main() { kubectl cluster-info --context kind-kind #setup nginx ingress - kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml +# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml + kubectl apply -fhttps://raw.githubusercontent.com/kubernetes/ingress-nginx/12150e318b972a03fb49d827e6cabb8ef62247ef/deploy/static/provider/kind/deploy.yaml kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=360s # This creates the service account, role, and role binding necessary for Spring Cloud k8s apps From 3126157493568f6f57bd915522bacd09704a9950 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Wed, 16 Sep 2020 11:47:38 +0000 Subject: [PATCH 12/13] Bumping versions --- README.adoc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.adoc b/README.adoc index a2e5a348..7d534f18 100644 --- a/README.adoc +++ b/README.adoc @@ -437,6 +437,10 @@ You can specify multiple (exact) file paths in `spring.cloud.kubernetes.config.p NOTE: You have to provide the full exact path to each property file, because directories are not being recursively parsed. +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. + .Properties: [options="header,footer"] |=== From 7f6ddf69c5b6d6bebe87e2f0f7e124362ff20aea Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 18 Sep 2020 11:47:22 +0000 Subject: [PATCH 13/13] Bumping versions --- .../config/BootstrapConfiguration.java | 15 +- .../config/ConfigMapConfigProperties.java | 9 +- .../config/ConfigMapPropertySource.java | 72 ++--- .../ConfigMapPropertySourceLocator.java | 47 +-- .../cloud/kubernetes/config/ConfigUtils.java | 17 +- .../config/PropertySourceUtils.java | 9 +- .../config/SecretsConfigProperties.java | 25 +- .../config/SecretsPropertySource.java | 41 ++- .../config/SecretsPropertySourceLocator.java | 35 +-- .../reload/ConfigReloadAutoConfiguration.java | 55 ++-- .../ConfigReloadDefaultAutoConfiguration.java | 38 +-- .../reload/ConfigurationChangeDetector.java | 35 +-- ...EventBasedConfigurationChangeDetector.java | 72 ++--- .../PollingConfigurationChangeDetector.java | 15 +- .../kubernetes/config/ConfigMapTestUtil.java | 3 +- .../config/ConfigMapsFromFilePathsTests.java | 43 ++- .../config/ConfigMapsMixedTests.java | 28 +- .../kubernetes/config/ConfigMapsTest.java | 97 ++---- .../kubernetes/config/ConfigMapsTests.java | 25 +- ...ConfigMapsWithActiveProfilesNameTests.java | 32 +- .../ConfigMapsWithProfileExpressionTests.java | 19 +- ...gMapsWithProfilesNoActiveProfileTests.java | 22 +- .../config/ConfigMapsWithProfilesTests.java | 22 +- .../ConfigMapsWithoutProfilesTests.java | 27 +- .../cloud/kubernetes/config/CoreTest.java | 47 ++- .../config/HealthIndicatorTest.java | 13 +- .../KubernetesConfigConfigurationTest.java | 9 +- .../config/MissingActuatorTest.java | 17 +- .../config/MultipleConfigMapsTests.java | 38 +-- .../config/MultipleSecretsTests.java | 30 +- .../config/SecretsPropertySourceTest.java | 16 +- .../config/example/GreetingController.java | 9 +- .../config/example2/ExampleApp.java | 3 +- ...BasedConfigurationChangeDetectorTests.java | 23 +- ...sedConfigurationWatcherChangeDetector.java | 28 +- .../ConfigurationWatcherApplication.java | 4 +- ...ConfigurationWatcherAutoConfiguration.java | 33 +- .../ConfigurationWatcherChangeDetector.java | 50 ++- ...BasedConfigurationWatchChangeDetector.java | 64 ++-- ...nfigurationWatcherChangeDetectorTests.java | 14 +- ...ConfigurationWatchChangeDetectorTests.java | 69 ++--- .../KubernetesAutoConfiguration.java | 70 ++--- .../kubernetes/KubernetesHealthIndicator.java | 6 +- .../cloud/kubernetes/StandardPodUtils.java | 12 +- ...rnetesProfileEnvironmentPostProcessor.java | 16 +- .../HealthIndicatorDisabledTest.java | 13 +- .../cloud/kubernetes/HealthIndicatorTest.java | 13 +- .../cloud/kubernetes/InfoContributorTest.java | 14 +- .../KubernetesAutoConfigurationTests.java | 15 +- .../kubernetes/LazilyInstantiateTest.java | 6 +- ...nditionalOnKubernetesDiscoveryEnabled.java | 3 +- .../DefaultIsServicePortSecureResolver.java | 24 +- .../discovery/KubernetesCatalogWatch.java | 32 +- ...bernetesCatalogWatchAutoConfiguration.java | 3 +- .../discovery/KubernetesDiscoveryClient.java | 72 ++--- ...netesDiscoveryClientAutoConfiguration.java | 26 +- ...entConfigClientBootstrapConfiguration.java | 3 +- .../KubernetesDiscoveryProperties.java | 14 +- .../discovery/KubernetesServiceInstance.java | 7 +- .../KubernetesReactiveDiscoveryClient.java | 13 +- ...ctiveDiscoveryClientAutoConfiguration.java | 13 +- .../KubernetesAutoServiceRegistration.java | 12 +- .../registry/KubernetesRegistration.java | 7 +- .../registry/KubernetesServiceRegistry.java | 3 +- ...efaultIsServicePortSecureResolverTest.java | 39 +-- ...CatalogServicesWatchConfigurationTest.java | 9 +- .../discovery/KubernetesCatalogWatchTest.java | 83 ++--- ...lientAutoConfigurationPropertiesTests.java | 21 +- ...DiscoveryClientAutoConfigurationTests.java | 7 +- ...nfigClientBootstrapConfigurationTests.java | 28 +- ...etesDiscoveryClientFilterMetadataTest.java | 286 ++++++++---------- .../KubernetesDiscoveryClientFilterTest.java | 16 +- .../KubernetesDiscoveryClientTest.java | 245 +++++++-------- .../KubernetesServiceInstanceTests.java | 5 +- ...DiscoveryClientAutoConfigurationTests.java | 88 ++---- ...ubernetesReactiveDiscoveryClientTests.java | 254 +++++++--------- .../support/KubernetesExtension.java | 16 +- .../kubernetes/examples/LeaderController.java | 9 +- .../examples/LeaderControllerTest.java | 12 +- .../examples/GreetingController.java | 6 +- .../kubernetes/examples/NameService.java | 3 +- .../kubernetes/examples/NameController.java | 6 +- .../cloud/kubernetes/it/ServicesIT.java | 16 +- .../LoadBalancerAllNamespacesTests.java | 26 +- .../loadbalancer/LoadBalancerTests.java | 26 +- .../LoadBalancerWithServiceTests.java | 26 +- .../cloud/kubernetes/it/GreetingIT.java | 14 +- .../kubernetes/it/GreetingAndHealthIT.java | 16 +- .../istio/IstioBootstrapConfiguration.java | 9 +- .../kubernetes/istio/utils/MeshUtils.java | 17 +- .../cloud/kubernetes/leader/Leader.java | 6 +- .../leader/LeaderAutoConfiguration.java | 38 +-- .../kubernetes/leader/LeaderContext.java | 3 +- .../leader/LeaderInfoContributor.java | 3 +- .../kubernetes/leader/LeaderInitiator.java | 9 +- .../leader/LeaderRecordWatcher.java | 12 +- .../leader/LeadershipController.java | 55 ++-- .../leader/PodReadinessWatcher.java | 11 +- .../leader/LeaderAutoConfigurationTests.java | 5 +- .../kubernetes/leader/LeaderContextTest.java | 12 +- .../leader/LeaderInfoContributorTest.java | 18 +- .../leader/LeaderInitiatorTest.java | 20 +- .../leader/LeaderRecordWatcherTest.java | 13 +- .../leader/LeadershipControllerTest.java | 5 +- .../leader/PodReadinessWatcherTest.java | 3 +- ...bernetesLoadBalancerAutoConfiguration.java | 6 +- ...rnetesLoadBalancerClientConfiguration.java | 6 +- .../KubernetesServiceInstanceMapper.java | 33 +- .../KubernetesServicesListSupplier.java | 11 +- .../KubernetesServiceInstanceMapperTests.java | 30 +- .../KubernetesServiceListSupplierTests.java | 30 +- 111 files changed, 1272 insertions(+), 2007 deletions(-) diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java index 9b6d72c6..4754fecf 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/BootstrapConfiguration.java @@ -41,26 +41,21 @@ public class BootstrapConfiguration { @Configuration(proxyBeanMethods = false) @Import(KubernetesAutoConfiguration.class) - @EnableConfigurationProperties({ ConfigMapConfigProperties.class, - SecretsConfigProperties.class }) + @EnableConfigurationProperties({ ConfigMapConfigProperties.class, SecretsConfigProperties.class }) protected static class KubernetesPropertySourceConfiguration { @Autowired private KubernetesClient client; @Bean - @ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled", - matchIfMissing = true) - public ConfigMapPropertySourceLocator configMapPropertySourceLocator( - ConfigMapConfigProperties properties) { + @ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled", matchIfMissing = true) + public ConfigMapPropertySourceLocator configMapPropertySourceLocator(ConfigMapConfigProperties properties) { return new ConfigMapPropertySourceLocator(this.client, properties); } @Bean - @ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled", - matchIfMissing = true) - public SecretsPropertySourceLocator secretsPropertySourceLocator( - SecretsConfigProperties properties) { + @ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled", matchIfMissing = true) + public SecretsPropertySourceLocator secretsPropertySourceLocator(SecretsConfigProperties properties) { return new SecretsPropertySourceLocator(this.client, properties); } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java index 2256ac19..8f299ba9 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapConfigProperties.java @@ -82,8 +82,7 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties { }; } - return this.sources.stream().map(s -> s.normalize(this.name, this.namespace)) - .collect(Collectors.toList()); + return this.sources.stream().map(s -> s.normalize(this.name, this.namespace)).collect(Collectors.toList()); } @Override @@ -135,10 +134,8 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties { } public NormalizedSource normalize(String defaultName, String defaultNamespace) { - final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName - : this.name; - final String normalizedNamespace = StringUtils.isEmpty(this.namespace) - ? defaultNamespace : this.namespace; + final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName : this.name; + final String normalizedNamespace = StringUtils.isEmpty(this.namespace) ? defaultNamespace : this.namespace; return new NormalizedSource(normalizedName, normalizedNamespace); } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java index 4d561dbd..41cac15f 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySource.java @@ -60,40 +60,31 @@ public class ConfigMapPropertySource extends MapPropertySource { this(client, name, null, (Environment) null); } - public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, - String[] profiles) { + public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, String[] profiles) { this(client, name, namespace, createEnvironmentWithActiveProfiles(profiles)); } - private static Environment createEnvironmentWithActiveProfiles( - String[] activeProfiles) { + private static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) { StandardEnvironment environment = new StandardEnvironment(); environment.setActiveProfiles(activeProfiles); return environment; } - public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, - Environment environment) { - super(getName(client, name, namespace), - asObjectMap(getData(client, name, namespace, environment))); + public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, Environment environment) { + super(getName(client, name, namespace), asObjectMap(getData(client, name, namespace, environment))); } - private static String getName(KubernetesClient client, String name, - String namespace) { - return new StringBuilder().append(PREFIX) - .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name) + private static String getName(KubernetesClient client, String name, String namespace) { + return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name) .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR) - .append(namespace == null || namespace.isEmpty() ? client.getNamespace() - : namespace) - .toString(); + .append(namespace == null || namespace.isEmpty() ? client.getNamespace() : namespace).toString(); } - private static Map getData(KubernetesClient client, String name, - String namespace, Environment environment) { + private static Map getData(KubernetesClient client, String name, String namespace, + Environment environment) { try { Map result = new LinkedHashMap<>(); - ConfigMap map = StringUtils.isEmpty(namespace) - ? client.configMaps().withName(name).get() + ConfigMap map = StringUtils.isEmpty(namespace) ? client.configMaps().withName(name).get() : client.configMaps().inNamespace(namespace).withName(name).get(); if (map != null) { @@ -107,12 +98,10 @@ public class ConfigMapPropertySource extends MapPropertySource { ConfigMap mapWithProfile = StringUtils.isEmpty(namespace) ? client.configMaps().withName(mapNameWithProfile).get() - : client.configMaps().inNamespace(namespace) - .withName(mapNameWithProfile).get(); + : client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get(); if (mapWithProfile != null) { - result.putAll( - processAllEntries(mapWithProfile.getData(), environment)); + result.putAll(processAllEntries(mapWithProfile.getData(), environment)); } } @@ -122,15 +111,13 @@ public class ConfigMapPropertySource extends MapPropertySource { } catch (Exception e) { - LOG.warn("Can't read configMap with name: [" + name + "] in namespace:[" - + namespace + "]. Ignoring.", e); + LOG.warn("Can't read configMap with name: [" + name + "] in namespace:[" + namespace + "]. Ignoring.", e); } return new LinkedHashMap<>(); } - private static Map processAllEntries(Map input, - Environment environment) { + private static Map processAllEntries(Map input, Environment environment) { Set> entrySet = input.entrySet(); if (entrySet.size() == 1) { @@ -141,12 +128,10 @@ public class ConfigMapPropertySource extends MapPropertySource { String propertyValue = singleEntry.getValue(); if (propertyName.endsWith(".yml") || propertyName.endsWith(".yaml")) { if (LOG.isDebugEnabled()) { - LOG.debug("The single property with name: [" + propertyName - + "] will be treated as a yaml file"); + LOG.debug("The single property with name: [" + propertyName + "] will be treated as a yaml file"); } - return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP) - .apply(propertyValue); + return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(propertyValue); } else if (propertyName.endsWith(".properties")) { if (LOG.isDebugEnabled()) { @@ -154,8 +139,7 @@ public class ConfigMapPropertySource extends MapPropertySource { + "] will be treated as a properties file"); } - return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP) - .apply(propertyValue); + return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(propertyValue); } else { return defaultProcessAllEntries(input, environment); @@ -165,23 +149,17 @@ public class ConfigMapPropertySource extends MapPropertySource { return defaultProcessAllEntries(input, environment); } - private static Map defaultProcessAllEntries(Map input, - Environment environment) { + private static Map defaultProcessAllEntries(Map input, Environment environment) { - return input.entrySet().stream() - .map(e -> extractProperties(e.getKey(), e.getValue(), environment)) + return input.entrySet().stream().map(e -> extractProperties(e.getKey(), e.getValue(), environment)) .filter(m -> !m.isEmpty()).flatMap(m -> m.entrySet().stream()) - .collect(Collectors.toMap(Entry::getKey, Entry::getValue, - throwingMerger(), LinkedHashMap::new)); + .collect(Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), LinkedHashMap::new)); } - private static Map extractProperties(String resourceName, - String content, Environment environment) { + private static Map extractProperties(String resourceName, String content, Environment environment) { - if (resourceName.equals(APPLICATION_YAML) - || resourceName.equals(APPLICATION_YML)) { - return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP) - .apply(content); + if (resourceName.equals(APPLICATION_YAML) || resourceName.equals(APPLICATION_YML)) { + return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(content); } else if (resourceName.equals(APPLICATION_PROPERTIES)) { return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(content); @@ -195,8 +173,8 @@ public class ConfigMapPropertySource extends MapPropertySource { } private static Map asObjectMap(Map source) { - return source.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, - Map.Entry::getValue, throwingMerger(), LinkedHashMap::new)); + return source.entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, throwingMerger(), LinkedHashMap::new)); } } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java index 39116614..748385d9 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigMapPropertySourceLocator.java @@ -52,15 +52,13 @@ import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.ya @Order(0) public class ConfigMapPropertySourceLocator implements PropertySourceLocator { - private static final Log LOG = LogFactory - .getLog(ConfigMapPropertySourceLocator.class); + private static final Log LOG = LogFactory.getLog(ConfigMapPropertySourceLocator.class); private final KubernetesClient client; private final ConfigMapConfigProperties properties; - public ConfigMapPropertySourceLocator(KubernetesClient client, - ConfigMapConfigProperties properties) { + public ConfigMapPropertySourceLocator(KubernetesClient client, ConfigMapConfigProperties properties) { this.client = client; this.properties = properties; } @@ -70,13 +68,10 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator { if (environment instanceof ConfigurableEnvironment) { ConfigurableEnvironment env = (ConfigurableEnvironment) environment; - List sources = this.properties - .determineSources(); - CompositePropertySource composite = new CompositePropertySource( - "composite-configmap"); + List sources = this.properties.determineSources(); + CompositePropertySource composite = new CompositePropertySource("composite-configmap"); if (this.properties.isEnableApi()) { - sources.forEach(s -> composite.addFirstPropertySource( - getMapPropertySourceForSingleConfigMap(env, s))); + sources.forEach(s -> composite.addFirstPropertySource(getMapPropertySourceForSingleConfigMap(env, s))); } addPropertySourcesFromPaths(environment, composite); @@ -86,20 +81,17 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator { return null; } - private MapPropertySource getMapPropertySourceForSingleConfigMap( - ConfigurableEnvironment environment, NormalizedSource normalizedSource) { + private MapPropertySource getMapPropertySourceForSingleConfigMap(ConfigurableEnvironment environment, + NormalizedSource normalizedSource) { String configurationTarget = this.properties.getConfigurationTarget(); return new ConfigMapPropertySource(this.client, - getApplicationName(environment, normalizedSource.getName(), - configurationTarget), - getApplicationNamespace(this.client, normalizedSource.getNamespace(), - configurationTarget), + getApplicationName(environment, normalizedSource.getName(), configurationTarget), + getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget), environment); } - private void addPropertySourcesFromPaths(Environment environment, - CompositePropertySource composite) { + private void addPropertySourcesFromPaths(Environment environment, CompositePropertySource composite) { this.properties.getPaths().stream().map(Paths::get).peek(p -> { if (!Files.exists(p)) { LOG.warn("Configured input path: " + p @@ -107,23 +99,18 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator { } }).filter(Files::exists).peek(p -> { if (!Files.isRegularFile(p)) { - LOG.warn("Configured input path: " + p - + " will be ignored because it is not a regular file"); + LOG.warn("Configured input path: " + p + " will be ignored because it is not a regular file"); } }).filter(Files::isRegularFile).forEach(p -> { try { String content = new String(Files.readAllBytes(p)).trim(); String filename = p.getFileName().toString().toLowerCase(); if (filename.endsWith(".properties")) { - addPropertySourceIfNeeded( - c -> PROPERTIES_TO_MAP - .apply(KEY_VALUE_TO_PROPERTIES.apply(c)), - content, filename, composite); + 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 -> PROPERTIES_TO_MAP - .apply(yamlParserGenerator(environment).apply(c)), + addPropertySourceIfNeeded(c -> PROPERTIES_TO_MAP.apply(yamlParserGenerator(environment).apply(c)), content, filename, composite); } } @@ -133,15 +120,13 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator { }); } - private void addPropertySourceIfNeeded( - Function> contentToMapFunction, String content, + private void addPropertySourceIfNeeded(Function> contentToMapFunction, String content, String name, CompositePropertySource composite) { Map map = new HashMap<>(); map.putAll(contentToMapFunction.apply(content)); if (map.isEmpty()) { - LOG.warn("Property source: " + name - + "will be ignored because no properties could be found"); + LOG.warn("Property source: " + name + "will be ignored because no properties could be found"); } else { composite.addFirstPropertySource(new MapPropertySource(name, map)); diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java index b186cf93..f867b092 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/ConfigUtils.java @@ -39,16 +39,14 @@ public final class ConfigUtils { throw new IllegalStateException("Can't instantiate a utility class"); } - public static String getApplicationName( - Environment env, String configName, String configurationTarget) { + public static String getApplicationName(Environment env, String configName, + String configurationTarget) { String name = configName; if (StringUtils.isEmpty(name)) { // TODO: use relaxed binding if (LOG.isDebugEnabled()) { - LOG.debug(configurationTarget - + " name has not been set, taking it from property/env " - + SPRING_APPLICATION_NAME + " (default=" - + FALLBACK_APPLICATION_NAME + ")"); + LOG.debug(configurationTarget + " name has not been set, taking it from property/env " + + SPRING_APPLICATION_NAME + " (default=" + FALLBACK_APPLICATION_NAME + ")"); } name = env.getProperty(SPRING_APPLICATION_NAME, FALLBACK_APPLICATION_NAME); @@ -57,13 +55,12 @@ public final class ConfigUtils { return name; } - public static String getApplicationNamespace( - KubernetesClient client, String configNamespace, String configurationTarget) { + public static String getApplicationNamespace(KubernetesClient client, + String configNamespace, String configurationTarget) { String namespace = configNamespace; if (StringUtils.isEmpty(namespace)) { if (LOG.isDebugEnabled()) { - LOG.debug(configurationTarget - + " namespace has not been set, taking it from client (ns=" + LOG.debug(configurationTarget + " namespace has not been set, taking it from client (ns=" + client.getNamespace() + ")"); } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java index b89294dd..ad9641fd 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/PropertySourceUtils.java @@ -52,9 +52,9 @@ public final class PropertySourceUtils { throw new IllegalArgumentException(); } }; - static final Function> PROPERTIES_TO_MAP = p -> p - .entrySet().stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()), - Map.Entry::getValue, throwingMerger(), java.util.LinkedHashMap::new)); + static final Function> PROPERTIES_TO_MAP = p -> p.entrySet().stream() + .collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue, throwingMerger(), + java.util.LinkedHashMap::new)); private PropertySourceUtils() { throw new IllegalStateException("Can't instantiate a utility class"); @@ -66,8 +66,7 @@ public final class PropertySourceUtils { yamlFactory.setDocumentMatchers(properties -> { String profiles = properties.getProperty("spring.profiles"); if (environment != null && StringUtils.hasText(profiles)) { - return environment.acceptsProfiles(Profiles.of(profiles)) ? FOUND - : NOT_FOUND; + return environment.acceptsProfiles(Profiles.of(profiles)) ? FOUND : NOT_FOUND; } else { return ABSTAIN; diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java index 93edcebb..2a1c23c3 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsConfigProperties.java @@ -94,16 +94,13 @@ public class SecretsConfigProperties extends AbstractConfigProperties { if (this.sources.isEmpty()) { return new ArrayList() { { - add(new SecretsConfigProperties.NormalizedSource( - SecretsConfigProperties.this.name, - SecretsConfigProperties.this.namespace, - SecretsConfigProperties.this.labels)); + add(new SecretsConfigProperties.NormalizedSource(SecretsConfigProperties.this.name, + SecretsConfigProperties.this.namespace, SecretsConfigProperties.this.labels)); } }; } - return this.sources.stream() - .map(s -> s.normalize(this.name, this.namespace, this.labels)) + return this.sources.stream().map(s -> s.normalize(this.name, this.namespace, this.labels)) .collect(Collectors.toList()); } @@ -161,17 +158,13 @@ public class SecretsConfigProperties extends AbstractConfigProperties { return StringUtils.isEmpty(this.name) && StringUtils.isEmpty(this.namespace); } - public SecretsConfigProperties.NormalizedSource normalize(String defaultName, - String defaultNamespace, Map defaultLabels) { - final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName - : this.name; - final String normalizedNamespace = StringUtils.isEmpty(this.namespace) - ? defaultNamespace : this.namespace; - final Map normalizedLabels = this.labels.isEmpty() - ? defaultLabels : this.labels; + public SecretsConfigProperties.NormalizedSource normalize(String defaultName, String defaultNamespace, + Map defaultLabels) { + final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName : this.name; + final String normalizedNamespace = StringUtils.isEmpty(this.namespace) ? defaultNamespace : this.namespace; + final Map normalizedLabels = this.labels.isEmpty() ? defaultLabels : this.labels; - return new SecretsConfigProperties.NormalizedSource(normalizedName, - normalizedNamespace, normalizedLabels); + return new SecretsConfigProperties.NormalizedSource(normalizedName, normalizedNamespace, normalizedLabels); } } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java index 5168ad4a..7c96c1db 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySource.java @@ -41,22 +41,18 @@ public class SecretsPropertySource extends MapPropertySource { private static final String PREFIX = "secrets"; - public SecretsPropertySource(KubernetesClient client, Environment env, String name, + public SecretsPropertySource(KubernetesClient client, Environment env, String name, String namespace, + Map labels) { + super(getSourceName(client, env, name, namespace), getSourceData(client, env, name, namespace, labels)); + } + + private static String getSourceName(KubernetesClient client, Environment env, String name, String namespace) { + return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name) + .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace).toString(); + } + + private static Map getSourceData(KubernetesClient client, Environment env, String name, String namespace, Map labels) { - super(getSourceName(client, env, name, namespace), - getSourceData(client, env, name, namespace, labels)); - } - - private static String getSourceName(KubernetesClient client, Environment env, - String name, String namespace) { - return new StringBuilder().append(PREFIX) - .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name) - .append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace) - .toString(); - } - - private static Map getSourceData(KubernetesClient client, - Environment env, String name, String namespace, Map labels) { Map result = new HashMap<>(); try { @@ -73,19 +69,17 @@ public class SecretsPropertySource extends MapPropertySource { // Read for secrets api (label) if (!labels.isEmpty()) { if (StringUtils.isEmpty(namespace)) { - client.secrets().withLabels(labels).list().getItems() - .forEach(s -> putAll(s, result)); + client.secrets().withLabels(labels).list().getItems().forEach(s -> putAll(s, result)); } else { - client.secrets().inNamespace(namespace).withLabels(labels).list() - .getItems().forEach(s -> putAll(s, result)); + client.secrets().inNamespace(namespace).withLabels(labels).list().getItems() + .forEach(s -> putAll(s, result)); } } } catch (Exception e) { - LOG.warn("Can't read secret with name: [" + name + "] or labels [" + labels - + "] in namespace:[" + namespace + "] (cause: " + e.getMessage() - + "). Ignoring"); + LOG.warn("Can't read secret with name: [" + name + "] or labels [" + labels + "] in namespace:[" + namespace + + "] (cause: " + e.getMessage() + "). Ignoring"); } return result; @@ -96,8 +90,7 @@ public class SecretsPropertySource extends MapPropertySource { // ***************************** private static void putAll(Secret secret, Map result) { if (secret != null && secret.getData() != null) { - secret.getData().forEach((k, v) -> result.put(k, - new String(Base64.getDecoder().decode(v)).trim())); + secret.getData().forEach((k, v) -> result.put(k, new String(Base64.getDecoder().decode(v)).trim())); } } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java index 8b00632e..862712f4 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceLocator.java @@ -54,8 +54,7 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator { private final SecretsConfigProperties properties; - public SecretsPropertySourceLocator(KubernetesClient client, - SecretsConfigProperties properties) { + public SecretsPropertySourceLocator(KubernetesClient client, SecretsConfigProperties properties) { this.client = client; this.properties = properties; } @@ -65,13 +64,11 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator { if (environment instanceof ConfigurableEnvironment) { ConfigurableEnvironment env = (ConfigurableEnvironment) environment; - List sources = this.properties - .determineSources(); - CompositePropertySource composite = new CompositePropertySource( - "composite-secrets"); + List sources = this.properties.determineSources(); + CompositePropertySource composite = new CompositePropertySource("composite-secrets"); if (this.properties.isEnableApi()) { - sources.forEach(s -> composite.addFirstPropertySource( - getKubernetesPropertySourceForSingleSecret(env, s))); + sources.forEach( + s -> composite.addFirstPropertySource(getKubernetesPropertySourceForSingleSecret(env, s))); } // read for secrets mount @@ -82,29 +79,24 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator { return null; } - private MapPropertySource getKubernetesPropertySourceForSingleSecret( - ConfigurableEnvironment environment, + private MapPropertySource getKubernetesPropertySourceForSingleSecret(ConfigurableEnvironment environment, SecretsConfigProperties.NormalizedSource normalizedSource) { String configurationTarget = this.properties.getConfigurationTarget(); return new SecretsPropertySource(this.client, environment, - getApplicationName(environment, normalizedSource.getName(), - configurationTarget), - getApplicationNamespace(this.client, normalizedSource.getNamespace(), - configurationTarget), + getApplicationName(environment, normalizedSource.getName(), configurationTarget), + getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget), normalizedSource.getLabels()); } private void putPathConfig(CompositePropertySource composite) { - this.properties.getPaths().stream().map(Paths::get).filter(Files::exists) - .forEach(p -> putAll(p, composite)); + this.properties.getPaths().stream().map(Paths::get).filter(Files::exists).forEach(p -> putAll(p, composite)); } private void putAll(Path path, CompositePropertySource composite) { try { - Files.walk(path).filter(Files::isRegularFile) - .forEach(p -> readFile(p, composite)); + Files.walk(path).filter(Files::isRegularFile).forEach(p -> readFile(p, composite)); } catch (IOException e) { LOG.warn("Error walking properties files", e); @@ -114,11 +106,10 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator { private void readFile(Path path, CompositePropertySource composite) { try { Map result = new HashMap<>(); - result.put(path.getFileName().toString(), - new String(Files.readAllBytes(path)).trim()); + result.put(path.getFileName().toString(), new String(Files.readAllBytes(path)).trim()); if (!result.isEmpty()) { - composite.addFirstPropertySource(new MapPropertySource( - path.getFileName().toString().toLowerCase(), result)); + composite.addFirstPropertySource( + new MapPropertySource(path.getFileName().toString().toLowerCase(), result)); } } catch (IOException e) { diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java index 8b0d33e6..852dd73b 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadAutoConfiguration.java @@ -50,8 +50,8 @@ import org.springframework.util.Assert; @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "spring.cloud.kubernetes.enabled", matchIfMissing = true) @ConditionalOnClass(EndpointAutoConfiguration.class) -@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, - RefreshEndpointAutoConfiguration.class, RefreshAutoConfiguration.class }) +@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class, + RefreshAutoConfiguration.class }) @EnableConfigurationProperties(ConfigReloadProperties.class) public class ConfigReloadAutoConfiguration { @@ -84,22 +84,17 @@ public class ConfigReloadAutoConfiguration { */ @Bean @ConditionalOnMissingBean - public ConfigurationChangeDetector propertyChangeWatcher( - ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy) { + public ConfigurationChangeDetector propertyChangeWatcher(ConfigReloadProperties properties, + ConfigurationUpdateStrategy strategy) { switch (properties.getMode()) { case POLLING: - return new PollingConfigurationChangeDetector(this.environment, - properties, this.kubernetesClient, strategy, - this.configMapPropertySourceLocator, - this.secretsPropertySourceLocator); + return new PollingConfigurationChangeDetector(this.environment, properties, this.kubernetesClient, + strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator); case EVENT: - return new EventBasedConfigurationChangeDetector(this.environment, - properties, this.kubernetesClient, strategy, - this.configMapPropertySourceLocator, - this.secretsPropertySourceLocator); + return new EventBasedConfigurationChangeDetector(this.environment, properties, this.kubernetesClient, + strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator); } - throw new IllegalStateException( - "Unsupported configuration reload mode: " + properties.getMode()); + throw new IllegalStateException("Unsupported configuration reload mode: " + properties.getMode()); } /** @@ -111,35 +106,29 @@ public class ConfigReloadAutoConfiguration { */ @Bean @ConditionalOnMissingBean - public ConfigurationUpdateStrategy configurationUpdateStrategy( - ConfigReloadProperties properties, ConfigurableApplicationContext ctx, - @Autowired(required = false) RestartEndpoint restarter, + public ConfigurationUpdateStrategy configurationUpdateStrategy(ConfigReloadProperties properties, + ConfigurableApplicationContext ctx, @Autowired(required = false) RestartEndpoint restarter, ContextRefresher refresher) { switch (properties.getStrategy()) { case RESTART_CONTEXT: Assert.notNull(restarter, "Restart endpoint is not enabled"); - return new ConfigurationUpdateStrategy(properties.getStrategy().name(), - () -> { - wait(properties); - restarter.restart(); - }); + return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> { + wait(properties); + restarter.restart(); + }); case REFRESH: - return new ConfigurationUpdateStrategy(properties.getStrategy().name(), - refresher::refresh); + return new ConfigurationUpdateStrategy(properties.getStrategy().name(), refresher::refresh); case SHUTDOWN: - return new ConfigurationUpdateStrategy(properties.getStrategy().name(), - () -> { - wait(properties); - ctx.close(); - }); + return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> { + wait(properties); + ctx.close(); + }); } - throw new IllegalStateException("Unsupported configuration update strategy: " - + properties.getStrategy()); + throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy()); } private static void wait(ConfigReloadProperties properties) { - final long waitMillis = ThreadLocalRandom.current() - .nextLong(properties.getMaxWaitForRestart().toMillis()); + final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis()); try { Thread.sleep(waitMillis); } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java index d4097f97..66f3200e 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigReloadDefaultAutoConfiguration.java @@ -69,22 +69,17 @@ public class ConfigReloadDefaultAutoConfiguration { */ @Bean @ConditionalOnMissingBean - public ConfigurationChangeDetector propertyChangeWatcher( - ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy) { + public ConfigurationChangeDetector propertyChangeWatcher(ConfigReloadProperties properties, + ConfigurationUpdateStrategy strategy) { switch (properties.getMode()) { case POLLING: - return new PollingConfigurationChangeDetector(this.environment, - properties, this.kubernetesClient, strategy, - this.configMapPropertySourceLocator, - this.secretsPropertySourceLocator); + return new PollingConfigurationChangeDetector(this.environment, properties, this.kubernetesClient, + strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator); case EVENT: - return new EventBasedConfigurationChangeDetector(this.environment, - properties, this.kubernetesClient, strategy, - this.configMapPropertySourceLocator, - this.secretsPropertySourceLocator); + return new EventBasedConfigurationChangeDetector(this.environment, properties, this.kubernetesClient, + strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator); } - throw new IllegalStateException( - "Unsupported configuration reload mode: " + properties.getMode()); + throw new IllegalStateException("Unsupported configuration reload mode: " + properties.getMode()); } /** @@ -96,23 +91,20 @@ public class ConfigReloadDefaultAutoConfiguration { */ @Bean @ConditionalOnMissingBean - public ConfigurationUpdateStrategy configurationUpdateStrategy( - ConfigReloadProperties properties, ConfigurableApplicationContext ctx) { + public ConfigurationUpdateStrategy configurationUpdateStrategy(ConfigReloadProperties properties, + ConfigurableApplicationContext ctx) { switch (properties.getStrategy()) { case SHUTDOWN: - return new ConfigurationUpdateStrategy(properties.getStrategy().name(), - () -> { - wait(properties); - ctx.close(); - }); + return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> { + wait(properties); + ctx.close(); + }); } - throw new IllegalStateException("Unsupported configuration update strategy: " - + properties.getStrategy()); + throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy()); } private static void wait(ConfigReloadProperties properties) { - final long waitMillis = ThreadLocalRandom.current() - .nextLong(properties.getMaxWaitForRestart().toMillis()); + final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis()); try { Thread.sleep(waitMillis); } diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java index 12034a49..a272f28b 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/ConfigurationChangeDetector.java @@ -54,9 +54,8 @@ public abstract class ConfigurationChangeDetector { protected ConfigurationUpdateStrategy strategy; - public ConfigurationChangeDetector(ConfigurableEnvironment environment, - ConfigReloadProperties properties, KubernetesClient kubernetesClient, - ConfigurationUpdateStrategy strategy) { + public ConfigurationChangeDetector(ConfigurableEnvironment environment, ConfigReloadProperties properties, + KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy) { this.environment = environment; this.properties = properties; this.kubernetesClient = kubernetesClient; @@ -95,13 +94,11 @@ public abstract class ConfigurationChangeDetector { return s1 == null ? s2 != null : !s1.equals(s2); } - protected boolean changed(List l1, - List l2) { + protected boolean changed(List l1, List l2) { if (l1.size() != l2.size()) { - this.log.warn( - "The current number of ConfigMap PropertySources does not match " - + "the ones loaded from the Kubernetes - No reload will take place"); + this.log.warn("The current number of ConfigMap PropertySources does not match " + + "the ones loaded from the Kubernetes - No reload will take place"); return false; } @@ -136,12 +133,10 @@ public abstract class ConfigurationChangeDetector { * @param sourceClass class for which property sources will be found * @return finds all registered property sources of the given type */ - protected > List findPropertySources( - Class sourceClass) { + protected > List findPropertySources(Class sourceClass) { List managedSources = new LinkedList<>(); - LinkedList> sources = toLinkedList( - this.environment.getPropertySources()); + LinkedList> sources = toLinkedList(this.environment.getPropertySources()); while (!sources.isEmpty()) { PropertySource source = sources.pop(); if (source instanceof CompositePropertySource) { @@ -152,8 +147,7 @@ public abstract class ConfigurationChangeDetector { managedSources.add(sourceClass.cast(source)); } else if (BootstrapPropertySource.class.isInstance(source)) { - PropertySource propertySource = ((BootstrapPropertySource) source) - .getDelegate(); + PropertySource propertySource = ((BootstrapPropertySource) source).getDelegate(); if (sourceClass.isInstance(propertySource)) { sources.add(propertySource); } @@ -179,8 +173,8 @@ public abstract class ConfigurationChangeDetector { * @return a list of MapPropertySource that correspond to the current state of the * system */ - protected List locateMapPropertySources( - PropertySourceLocator propertySourceLocator, Environment environment) { + protected List locateMapPropertySources(PropertySourceLocator propertySourceLocator, + Environment environment) { List result = new ArrayList<>(); PropertySource propertySource = propertySourceLocator.locate(environment); @@ -188,13 +182,12 @@ public abstract class ConfigurationChangeDetector { result.add((MapPropertySource) propertySource); } else if (propertySource instanceof CompositePropertySource) { - result.addAll(((CompositePropertySource) propertySource).getPropertySources() - .stream().filter(p -> p instanceof MapPropertySource) - .map(p -> (MapPropertySource) p).collect(Collectors.toList())); + result.addAll(((CompositePropertySource) propertySource).getPropertySources().stream() + .filter(p -> p instanceof MapPropertySource).map(p -> (MapPropertySource) p) + .collect(Collectors.toList())); } else { - this.log.debug("Found property source that cannot be handled: " - + propertySource.getClass()); + this.log.debug("Found property source that cannot be handled: " + propertySource.getClass()); } return result; diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java index 43b675f6..25d8777a 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetector.java @@ -50,9 +50,8 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe private Map watches; - public EventBasedConfigurationChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties properties, KubernetesClient kubernetesClient, - ConfigurationUpdateStrategy strategy, + public EventBasedConfigurationChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties, + KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator, SecretsPropertySourceLocator secretsPropertySourceLocator) { super(environment, properties, kubernetesClient, strategy); @@ -69,22 +68,19 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe if (this.properties.isMonitoringConfigMaps()) { try { String name = "config-maps-watch"; - this.watches.put(name, this.kubernetesClient.configMaps() - .watch(new Watcher() { - @Override - public void eventReceived(Action action, - ConfigMap configMap) { - if (log.isDebugEnabled()) { - log.debug(name + " received event for ConfigMap " - + configMap.getMetadata().getName()); - } - onEvent(configMap); - } + this.watches.put(name, this.kubernetesClient.configMaps().watch(new Watcher() { + @Override + public void eventReceived(Action action, ConfigMap configMap) { + if (log.isDebugEnabled()) { + log.debug(name + " received event for ConfigMap " + configMap.getMetadata().getName()); + } + onEvent(configMap); + } - @Override - public void onClose(KubernetesClientException e) { - } - })); + @Override + public void onClose(KubernetesClientException e) { + } + })); activated = true; this.log.info("Added new Kubernetes watch: " + name); } @@ -99,34 +95,30 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe try { activated = false; String name = "secrets-watch"; - this.watches.put(name, - this.kubernetesClient.secrets().watch(new Watcher() { - @Override - public void eventReceived(Action action, Secret secret) { - if (log.isDebugEnabled()) { - log.debug(name + " received and event for Secret " - + secret.getMetadata().getName()); - } - onEvent(secret); - } + this.watches.put(name, this.kubernetesClient.secrets().watch(new Watcher() { + @Override + public void eventReceived(Action action, Secret secret) { + if (log.isDebugEnabled()) { + log.debug(name + " received and event for Secret " + secret.getMetadata().getName()); + } + onEvent(secret); + } - @Override - public void onClose(KubernetesClientException e) { - } - })); + @Override + public void onClose(KubernetesClientException e) { + } + })); activated = true; this.log.info("Added new Kubernetes watch: " + name); } catch (Exception e) { - this.log.error( - "Error while establishing a connection to watch secrets: configuration may remain stale", + this.log.error("Error while establishing a connection to watch secrets: configuration may remain stale", e); } } if (activated) { - this.log.info( - "Kubernetes event-based configuration change detector activated"); + this.log.info("Kubernetes event-based configuration change detector activated"); } } @@ -147,9 +139,7 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe } protected void onEvent(ConfigMap configMap) { - boolean changed = changed( - locateMapPropertySources(this.configMapPropertySourceLocator, - this.environment), + boolean changed = changed(locateMapPropertySources(this.configMapPropertySourceLocator, this.environment), findPropertySources(ConfigMapPropertySource.class)); if (changed) { this.log.info("Detected change in config maps"); @@ -158,9 +148,7 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe } protected void onEvent(Secret secret) { - boolean changed = changed( - locateMapPropertySources(this.secretsPropertySourceLocator, - this.environment), + boolean changed = changed(locateMapPropertySources(this.secretsPropertySourceLocator, this.environment), findPropertySources(SecretsPropertySource.class)); if (changed) { this.log.info("Detected change in secrets"); diff --git a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigurationChangeDetector.java b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigurationChangeDetector.java index d315ef4c..6b61d127 100644 --- a/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigurationChangeDetector.java +++ b/spring-cloud-kubernetes-config/src/main/java/org/springframework/cloud/kubernetes/config/reload/PollingConfigurationChangeDetector.java @@ -47,9 +47,8 @@ public class PollingConfigurationChangeDetector extends ConfigurationChangeDetec private SecretsPropertySourceLocator secretsPropertySourceLocator; - public PollingConfigurationChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties properties, KubernetesClient kubernetesClient, - ConfigurationUpdateStrategy strategy, + public PollingConfigurationChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties, + KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator, SecretsPropertySourceLocator secretsPropertySourceLocator) { super(environment, properties, kubernetesClient, strategy); @@ -74,19 +73,17 @@ public class PollingConfigurationChangeDetector extends ConfigurationChangeDetec if (!currentConfigMapSources.isEmpty()) { changedConfigMap = changed( - locateMapPropertySources(this.configMapPropertySourceLocator, - this.environment), + locateMapPropertySources(this.configMapPropertySourceLocator, this.environment), currentConfigMapSources); } } boolean changedSecrets = false; if (this.properties.isMonitoringSecrets()) { - List currentSecretSources = locateMapPropertySources( - this.secretsPropertySourceLocator, this.environment); + List currentSecretSources = locateMapPropertySources(this.secretsPropertySourceLocator, + this.environment); if (currentSecretSources != null && !currentSecretSources.isEmpty()) { - List propertySources = findPropertySources( - SecretsPropertySource.class); + List propertySources = findPropertySources(SecretsPropertySource.class); changedSecrets = changed(currentSecretSources, propertySources); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java index fdafb7e0..5cb55d99 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapTestUtil.java @@ -31,8 +31,7 @@ final class ConfigMapTestUtil { static String readResourceFile(String file) { String resource; try { - resource = IOHelpers.readFully( - ConfigMapTestUtil.class.getClassLoader().getResourceAsStream(file)); + resource = IOHelpers.readFully(ConfigMapTestUtil.class.getClassLoader().getResourceAsStream(file)); } catch (IOException e) { resource = ""; diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java index 363e6425..a3d33be0 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsFromFilePathsTests.java @@ -39,12 +39,10 @@ import static org.assertj.core.util.Lists.newArrayList; import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.createFileWithContent; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "spring.application.name=configmap-path-example", "spring.cloud.kubernetes.config.enableApi=false", - "spring.cloud.kubernetes.config.paths=" - + ConfigMapsFromFilePathsTests.FIRST_FILE_NAME_FULL_PATH + "," + "spring.cloud.kubernetes.config.paths=" + ConfigMapsFromFilePathsTests.FIRST_FILE_NAME_FULL_PATH + "," + ConfigMapsFromFilePathsTests.SECOND_FILE_NAME_FULL_PATH }) public class ConfigMapsFromFilePathsTests { @@ -56,14 +54,11 @@ public class ConfigMapsFromFilePathsTests { protected static final String UNUSED_FILE_NAME = "unused.properties"; - protected static final String FIRST_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" - + FIRST_FILE_NAME; + protected static final String FIRST_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + FIRST_FILE_NAME; - protected static final String SECOND_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" - + SECOND_FILE_NAME; + 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 UNUSED_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + UNUSED_FILE_NAME; @ClassRule public static KubernetesServer server = new KubernetesServer(); @@ -78,27 +73,23 @@ public class ConfigMapsFromFilePathsTests { mockClient = server.getClient(); // 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_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_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)); - createFileWithContent(FIRST_FILE_NAME_FULL_PATH, - "bean.greeting=Hello from path!"); + createFileWithContent(FIRST_FILE_NAME_FULL_PATH, "bean.greeting=Hello from path!"); createFileWithContent(SECOND_FILE_NAME_FULL_PATH, "bean.farewell=Bye from path!"); - createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, - "bean.morning=Morning from path!"); + createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, "bean.morning=Morning from path!"); } @AfterClass public static void teardownAfterClass() { - newArrayList(FIRST_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH, - SECOND_FILE_NAME_FULL_PATH, FILES_ROOT_PATH).forEach(fn -> { + newArrayList(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)); } @@ -109,20 +100,20 @@ public class ConfigMapsFromFilePathsTests { @Test public void greetingInputShouldReturnPropertyFromFirstFile() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Hello from path!"); + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Hello from path!"); } @Test public void farewellInputShouldReturnPropertyFromSecondFile() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Bye from path!"); + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Bye from path!"); } @Test public void morningInputShouldReturnDefaultValue() { - this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Good morning, World!"); + this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Good morning, World!"); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java index 1f4ea258..08b42808 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsMixedTests.java @@ -41,12 +41,10 @@ import static org.assertj.core.util.Lists.newArrayList; import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "spring.application.name=" + ConfigMapsMixedTests.APPLICATION_NAME, "spring.cloud.kubernetes.config.enableApi=true", - "spring.cloud.kubernetes.config.paths=" - + ConfigMapsMixedTests.FILE_NAME_FULL_PATH }) + "spring.cloud.kubernetes.config.paths=" + ConfigMapsMixedTests.FILE_NAME_FULL_PATH }) public class ConfigMapsMixedTests { protected static final String FILES_ROOT_PATH = "/tmp/scktests"; @@ -70,24 +68,21 @@ public class ConfigMapsMixedTests { mockClient = server.getClient(); // 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_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_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)); - ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH, - readResourceFile("application-path.yaml")); + ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH, readResourceFile("application-path.yaml")); HashMap data = new HashMap<>(); data.put("bean.morning", "Buenos Dias ConfigMap, %s"); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @@ -104,22 +99,19 @@ public class ConfigMapsMixedTests { @Test public void greetingInputShouldReturnPropertyFromFile() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Hello ConfigMap, World from path"); } @Test public void farewellInputShouldReturnPropertyFromFile() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Bye ConfigMap, World from path"); } @Test public void morningInputShouldReturnPropertyFromApi() { - this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Buenos Dias ConfigMap, World"); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java index c77f5784..0997152e 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTest.java @@ -51,11 +51,9 @@ public class ConfigMapsTest { @Test public void testConfigMapGet() { - this.server.expect().withPath("/api/v1/namespaces/ns2/configmaps") - .andReturn(200, - new ConfigMapBuilder().withNewMetadata() - .withName("reload-example").endMetadata() - .addToData("KEY", "123").build()) + this.server + .expect().withPath("/api/v1/namespaces/ns2/configmaps").andReturn(200, new ConfigMapBuilder() + .withNewMetadata().withName("reload-example").endMetadata().addToData("KEY", "123").build()) .once(); KubernetesClient client = this.server.getClient(); @@ -63,8 +61,7 @@ public class ConfigMapsTest { assertThat(configMapList).isNotNull(); assertThat(configMapList.getAdditionalProperties()).containsKey("data"); @SuppressWarnings("unchecked") - Map data = (Map) configMapList - .getAdditionalProperties().get("data"); + Map data = (Map) configMapList.getAdditionalProperties().get("data"); assertThat(data.get("KEY")).isEqualTo("123"); } @@ -72,18 +69,13 @@ public class ConfigMapsTest { public void testConfigMapFromSingleApplicationProperties() { String configMapName = "app-properties-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(configMapName).endMetadata() - .addToData("application.properties", - readResourceFile("application.properties")) - .build()) + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData("application.properties", readResourceFile("application.properties")).build()) .once(); - ConfigMapPropertySource cmps = new ConfigMapPropertySource( - this.server.getClient().inNamespace(namespace), configMapName); + ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), + configMapName); assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a"); assertThat(cmps.getProperty("dummy.property.int1")).isEqualTo("1"); @@ -94,19 +86,13 @@ public class ConfigMapsTest { public void testConfigMapFromSingleApplicationYaml() { String configMapName = "app-yaml-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, - new ConfigMapBuilder().withNewMetadata().withName(configMapName) - .endMetadata() - .addToData("application.yaml", - readResourceFile("application.yaml")) - .build()) + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData("application.yaml", readResourceFile("application.yaml")).build()) .once(); - ConfigMapPropertySource cmps = new ConfigMapPropertySource( - this.server.getClient().inNamespace(namespace), configMapName); + ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), + configMapName); assertThat(cmps.getProperty("dummy.property.string2")).isEqualTo("a"); assertThat(cmps.getProperty("dummy.property.int2")).isEqualTo(1); @@ -117,16 +103,13 @@ public class ConfigMapsTest { public void testConfigMapFromSingleNonStandardFileName() { String configMapName = "single-non-standard-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(configMapName).endMetadata() + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() .addToData("adhoc.yml", readResourceFile("adhoc.yml")).build()) .once(); - ConfigMapPropertySource cmps = new ConfigMapPropertySource( - this.server.getClient().inNamespace(namespace), configMapName); + ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), + configMapName); assertThat(cmps.getProperty("dummy.property.string3")).isEqualTo("a"); assertThat(cmps.getProperty("dummy.property.int3")).isEqualTo(1); @@ -137,17 +120,12 @@ public class ConfigMapsTest { public void testConfigMapFromSingleInvalidPropertiesContent() { String configMapName = "single-unparseable-properties-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, - new ConfigMapBuilder().withNewMetadata().withName(configMapName) - .endMetadata() - .addToData("application.properties", "somevalue").build()) + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData("application.properties", "somevalue").build()) .once(); - new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), - configMapName); + new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName); // no exception is thrown for unparseable content } @@ -156,17 +134,12 @@ public class ConfigMapsTest { public void testConfigMapFromSingleInvalidYamlContent() { String configMapName = "single-unparseable-yaml-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, - new ConfigMapBuilder().withNewMetadata().withName(configMapName) - .endMetadata().addToData("application.yaml", "somevalue") - .build()) + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData("application.yaml", "somevalue").build()) .once(); - new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), - configMapName); + new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName); // no exception is thrown for unparseable content } @@ -175,21 +148,15 @@ public class ConfigMapsTest { public void testConfigMapFromMultipleApplicationProperties() { String configMapName = "app-multiple-properties-test"; String namespace = "app-props"; - this.server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) + this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) .andReturn(200, - new ConfigMapBuilder().withNewMetadata().withName(configMapName) - .endMetadata() - .addToData("application.properties", - readResourceFile("application.properties")) - .addToData("adhoc.properties", - readResourceFile("adhoc.properties")) - .build()) + new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData("application.properties", readResourceFile("application.properties")) + .addToData("adhoc.properties", readResourceFile("adhoc.properties")).build()) .once(); - ConfigMapPropertySource cmps = new ConfigMapPropertySource( - this.server.getClient().inNamespace(namespace), configMapName); + ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), + configMapName); // application.properties should be read correctly assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a"); diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java index 4237a749..dbdbb2eb 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsTests.java @@ -41,9 +41,8 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Charles Moulliard */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, properties = { "spring.application.name=configmap-example", - "spring.cloud.kubernetes.reload.enabled=false" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "spring.application.name=configmap-example", "spring.cloud.kubernetes.reload.enabled=false" }) @AutoConfigureWebTestClient public class ConfigMapsTests { @@ -65,42 +64,38 @@ public class ConfigMapsTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); data.put("bean.greeting", "Hello ConfigMap, %s!"); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @Test public void testConfig() { - assertThat(mockClient.getConfiguration().getMasterUrl()) - .isEqualTo(this.config.getMasterUrl()); + assertThat(mockClient.getConfiguration().getMasterUrl()).isEqualTo(this.config.getMasterUrl()); assertThat(mockClient.getNamespace()).isEqualTo(this.config.getNamespace()); } @Test public void testConfigMap() { - ConfigMap configmap = mockClient.configMaps().inNamespace("test") - .withName(APPLICATION_NAME).get(); + ConfigMap configmap = mockClient.configMaps().inNamespace("test").withName(APPLICATION_NAME).get(); HashMap keys = (HashMap) configmap.getData(); assertThat("Hello ConfigMap, %s!").isEqualTo(keys.get("bean.greeting")); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Hello ConfigMap, World!"); + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Hello ConfigMap, World!"); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java index c9066574..6d57e29a 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithActiveProfilesNameTests.java @@ -43,8 +43,7 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read */ @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = App.class, - properties = { - "spring.application.name=configmap-with-active-profile-name-example", + properties = { "spring.application.name=configmap-with-active-profile-name-example", "spring.cloud.kubernetes.reload.enabled=false" }) @ActiveProfiles("development") @AutoConfigureWebTestClient @@ -68,46 +67,37 @@ public class ConfigMapsWithActiveProfilesNameTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); data.put("application.yml", readResourceFile("application-with-profiles.yaml")); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); HashMap dataWithName = new HashMap<>(); - dataWithName.put("application.yml", - readResourceFile("application-with-active-profiles-name.yaml")); - server.expect() - .withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME - + "-development") - .andReturn(200, - new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME + "-development").endMetadata() - .addToData(dataWithName).build()) + dataWithName.put("application.yml", readResourceFile("application-with-active-profiles-name.yaml")); + server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME + "-development") + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME + "-development") + .endMetadata().addToData(dataWithName).build()) .always(); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Hello ConfigMap Active Profile Name, World!"); } @Test public void testFarewellEndpoint() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Goodbye ConfigMap default, World!"); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java index 490b5e00..ebe1be2e 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfileExpressionTests.java @@ -41,10 +41,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read * Tests reading property from YAML document specified by profile expression. */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, - properties = { "spring.application.name=configmap-with-profile-example", - "spring.cloud.kubernetes.reload.enabled=false" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { + "spring.application.name=configmap-with-profile-example", "spring.cloud.kubernetes.reload.enabled=false" }) @ActiveProfiles({ "production", "us-east" }) @AutoConfigureWebTestClient public class ConfigMapsWithProfileExpressionTests { @@ -62,27 +60,24 @@ public class ConfigMapsWithProfileExpressionTests { KubernetesClient mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); data.put("application.yml", readResourceFile("application-with-profiles.yaml")); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Hello ConfigMap production and us-east, World!"); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java index 7a68d2ac..a0082bc2 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesNoActiveProfileTests.java @@ -40,10 +40,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read * @author Charles Moulliard */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, - properties = { - "spring.application.name=configmap-with-profile-no-active-profiles-example", +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, + properties = { "spring.application.name=configmap-with-profile-no-active-profiles-example", "spring.cloud.kubernetes.reload.enabled=false" }) @AutoConfigureWebTestClient public class ConfigMapsWithProfilesNoActiveProfileTests { @@ -63,34 +61,30 @@ public class ConfigMapsWithProfilesNoActiveProfileTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); data.put("application.yml", readResourceFile("application-with-profiles.yaml")); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Hello ConfigMap default, World!"); } @Test public void testFarewellEndpoint() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Goodbye ConfigMap default, World!"); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java index fe7ce92f..fe26523f 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithProfilesTests.java @@ -41,10 +41,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read * @author Charles Moulliard */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, - properties = { "spring.application.name=configmap-with-profile-example", - "spring.cloud.kubernetes.reload.enabled=false" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { + "spring.application.name=configmap-with-profile-example", "spring.cloud.kubernetes.reload.enabled=false" }) @ActiveProfiles("development") @AutoConfigureWebTestClient public class ConfigMapsWithProfilesTests { @@ -67,34 +65,30 @@ public class ConfigMapsWithProfilesTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); data.put("application.yml", readResourceFile("application-with-profiles.yaml")); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Hello ConfigMap dev, World!"); } @Test public void testFarewellEndpoint() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content") + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") .isEqualTo("Goodbye ConfigMap default, World!"); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java index 96390475..2f0bc98c 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/ConfigMapsWithoutProfilesTests.java @@ -38,10 +38,8 @@ import org.springframework.test.web.reactive.server.WebTestClient; import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, - properties = { "spring.application.name=configmap-without-profile-example", - "spring.cloud.kubernetes.reload.enabled=false" }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { + "spring.application.name=configmap-without-profile-example", "spring.cloud.kubernetes.reload.enabled=false" }) @ActiveProfiles("development") @AutoConfigureWebTestClient public class ConfigMapsWithoutProfilesTests { @@ -61,34 +59,31 @@ public class ConfigMapsWithoutProfilesTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); HashMap data = new HashMap<>(); - data.put("application.yml", - readResourceFile("application-without-profiles.yaml")); + data.put("application.yml", readResourceFile("application-without-profiles.yaml")); server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(APPLICATION_NAME).endMetadata().addToData(data).build()) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata() + .addToData(data).build()) .always(); } @Test public void testGreetingEndpoint() { - this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Hello ConfigMap, World!"); + this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Hello ConfigMap, World!"); } @Test public void testFarewellEndpoint() { - this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk() - .expectBody().jsonPath("content").isEqualTo("Goodbye ConfigMap, World!"); + this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content") + .isEqualTo("Goodbye ConfigMap, World!"); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java index 26192423..e94d87ed 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/CoreTest.java @@ -37,10 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(classes = TestApplication.class, - properties = { "spring.application.name=testapp", - "spring.cloud.kubernetes.client.namespace=testns", - "spring.cloud.kubernetes.client.trustCerts=true", - "spring.cloud.kubernetes.config.namespace=testns", + properties = { "spring.application.name=testapp", "spring.cloud.kubernetes.client.namespace=testns", + "spring.cloud.kubernetes.client.trustCerts=true", "spring.cloud.kubernetes.config.namespace=testns", "spring.cloud.kubernetes.secrets.enableApi=true" }) public class CoreTest { @@ -63,39 +61,32 @@ public class CoreTest { mockClient = mockServer.getClient(); mockServer.expect().get().withPath("/api/v1/namespaces/testns/configmaps/testapp") - .andReturn(200, - new ConfigMapBuilder().withData(new HashMap() { - { - put("spring.kubernetes.test.value", "value1"); - } - }).build()) - .always(); + .andReturn(200, new ConfigMapBuilder().withData(new HashMap() { + { + put("spring.kubernetes.test.value", "value1"); + } + }).build()).always(); mockServer.expect().get().withPath("/api/v1/namespaces/testns/secrets/testapp") - .andReturn(200, - new SecretBuilder().withData(new HashMap() { - { - put("amq.user", "YWRtaW4K"); - put("amq.pwd", "MWYyZDFlMmU2N2Rm"); - } - }).build()) - .always(); + .andReturn(200, new SecretBuilder().withData(new HashMap() { + { + put("amq.user", "YWRtaW4K"); + put("amq.pwd", "MWYyZDFlMmU2N2Rm"); + } + }).build()).always(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @Test public void kubernetesClientConfigBeanShouldBeConfigurableViaSystemProperties() { assertThat(config).isNotNull(); - assertThat(config.getMasterUrl()) - .isEqualTo(mockClient.getConfiguration().getMasterUrl()); + assertThat(config.getMasterUrl()).isEqualTo(mockClient.getConfiguration().getMasterUrl()); assertThat(config.getNamespace()).isEqualTo("testns"); assertThat(config.isTrustCerts()).isTrue(); } @@ -103,14 +94,12 @@ public class CoreTest { @Test public void kubernetesClientBeanShouldBeConfigurableViaSystemProperties() { assertThat(client).isNotNull(); - assertThat(client.getConfiguration().getMasterUrl()) - .isEqualTo(mockClient.getConfiguration().getMasterUrl()); + assertThat(client.getConfiguration().getMasterUrl()).isEqualTo(mockClient.getConfiguration().getMasterUrl()); } @Test public void propertiesShouldBeReadFromConfigMap() { - assertThat(environment.getProperty("spring.kubernetes.test.value")) - .isEqualTo("value1"); + assertThat(environment.getProperty("spring.kubernetes.test.value")).isEqualTo("value1"); } @Test diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java index b022bd85..6384df25 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/HealthIndicatorTest.java @@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; import static org.hamcrest.Matchers.containsString; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "management.endpoint.health.show-details=always" }) public class HealthIndicatorTest { @@ -56,12 +55,10 @@ public class HealthIndicatorTest { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @@ -69,8 +66,8 @@ public class HealthIndicatorTest { @Test public void healthEndpointShouldContainKubernetes() { this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk() - .expectBody(String.class).value(containsString("kubernetes")); + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(containsString("kubernetes")); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java index c3c36f36..ff3031a6 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/KubernetesConfigConfigurationTest.java @@ -52,8 +52,7 @@ public class KubernetesConfigConfigurationTest { @Test public void kubernetesWhenKubernetesConfigDisabled() throws Exception { - setup("spring.cloud.kubernetes.config.enabled=false", - "spring.cloud.kubernetes.secrets.enabled=false"); + setup("spring.cloud.kubernetes.config.enabled=false", "spring.cloud.kubernetes.secrets.enabled=false"); assertThat(this.context.containsBean("configMapPropertySourceLocator")).isFalse(); assertThat(this.context.containsBean("secretsPropertySourceLocator")).isFalse(); } @@ -66,11 +65,9 @@ public class KubernetesConfigConfigurationTest { } private void setup(String... env) { - this.context = new SpringApplicationBuilder( - PropertyPlaceholderAutoConfiguration.class, + this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, KubernetesClientTestConfiguration.class, BootstrapConfiguration.class) - .web(org.springframework.boot.WebApplicationType.NONE) - .properties(env).run(); + .web(org.springframework.boot.WebApplicationType.NONE).properties(env).run(); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java index 250602d5..e0c6c606 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MissingActuatorTest.java @@ -34,26 +34,23 @@ import static org.assertj.core.api.Assertions.assertThat; // inspired by spring-cloud-commons: RefreshAutoConfigurationMoreClassPathTests @RunWith(ModifiedClassPathRunner.class) -@ClassPathExclusions({ "spring-boot-actuator-autoconfigure-*.jar", - "spring-boot-starter-actuator-*.jar" }) +@ClassPathExclusions({ "spring-boot-actuator-autoconfigure-*.jar", "spring-boot-starter-actuator-*.jar" }) public class MissingActuatorTest { @Rule public OutputCaptureRule outputCapture = new OutputCaptureRule(); - private static ConfigurableApplicationContext getApplicationContext( - Class configuration, String... properties) { - return new SpringApplicationBuilder(configuration).web(WebApplicationType.NONE) - .properties(properties).run(); + private static ConfigurableApplicationContext getApplicationContext(Class configuration, String... properties) { + return new SpringApplicationBuilder(configuration).web(WebApplicationType.NONE).properties(properties).run(); } @Test public void unknownClassProtected() { - try (ConfigurableApplicationContext context = getApplicationContext(Config.class, - "debug=true")) { + try (ConfigurableApplicationContext context = getApplicationContext(Config.class, "debug=true")) { String output = this.outputCapture.toString(); - assertThat(output).doesNotContain("Failed to introspect annotations on" - + " [class org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration") + assertThat(output) + .doesNotContain("Failed to introspect annotations on" + + " [class org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration") .doesNotContain("TypeNotPresentExceptionProxy"); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java index bb6ad831..da10be77 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleConfigMapsTests.java @@ -39,8 +39,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; * @author Charles Moulliard */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = ExampleApp.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ExampleApp.class, properties = { "spring.cloud.bootstrap.name=multiplecms" }) @AutoConfigureWebTestClient public class MultipleConfigMapsTests { @@ -58,12 +57,10 @@ public class MultipleConfigMapsTests { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); @@ -81,23 +78,20 @@ public class MultipleConfigMapsTests { } }); - createConfigmap(server, "othername", "othernamespace", - new HashMap() { - { - put("bean.common-message", "c3"); - put("bean.message3", "m3"); - } - }); + createConfigmap(server, "othername", "othernamespace", new HashMap() { + { + put("bean.common-message", "c3"); + put("bean.message3", "m3"); + } + }); } - private static void createConfigmap(KubernetesServer server, String configMapName, - String namespace, Map data) { + private static void createConfigmap(KubernetesServer server, String configMapName, String namespace, + Map data) { - server.expect() - .withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, - configMapName)) - .andReturn(200, new ConfigMapBuilder().withNewMetadata() - .withName(configMapName).endMetadata().addToData(data).build()) + server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName)) + .andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata() + .addToData(data).build()) .always(); } @@ -124,8 +118,8 @@ public class MultipleConfigMapsTests { } private void assertResponse(String path, String expectedMessage) { - this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody() - .jsonPath("message").isEqualTo(expectedMessage); + this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody().jsonPath("message") + .isEqualTo(expectedMessage); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java index f06f8c3c..676129cc 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/MultipleSecretsTests.java @@ -41,8 +41,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; * @author Haytham Mohamed */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = MultiSecretsApp.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = MultiSecretsApp.class, properties = { "spring.cloud.bootstrap.name=multiple-secrets" }) @AutoConfigureWebTestClient public class MultipleSecretsTests { @@ -68,14 +67,11 @@ public class MultipleSecretsTests { KubernetesClient mockClient = server.getClient(); // 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_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, - DEFAULT_NAMESPACE); + System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); + System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, DEFAULT_NAMESPACE); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); Map metadata1 = new HashMap() { @@ -85,11 +81,8 @@ public class MultipleSecretsTests { } }; - Secret secret1 = new SecretBuilder().withNewMetadata().withName("name1") - .withLabels(metadata1).endMetadata() - .addToData("secrets.secret1", - Base64.getEncoder().encodeToString(SECRET_VALUE_1.getBytes())) - .build(); + Secret secret1 = new SecretBuilder().withNewMetadata().withName("name1").withLabels(metadata1).endMetadata() + .addToData("secrets.secret1", Base64.getEncoder().encodeToString(SECRET_VALUE_1.getBytes())).build(); mockClient.secrets().inNamespace(DEFAULT_NAMESPACE).create(secret1); @@ -100,11 +93,8 @@ public class MultipleSecretsTests { } }; - Secret secret2 = new SecretBuilder().withNewMetadata().withName("name2") - .withLabels(metadata2).endMetadata() - .addToData("secrets.secret2", - Base64.getEncoder().encodeToString(SECRET_VALUE_2.getBytes())) - .build(); + Secret secret2 = new SecretBuilder().withNewMetadata().withName("name2").withLabels(metadata2).endMetadata() + .addToData("secrets.secret2", Base64.getEncoder().encodeToString(SECRET_VALUE_2.getBytes())).build(); mockClient.secrets().inNamespace(ANOTHER_NAMESPACE).create(secret2); } @@ -120,8 +110,8 @@ public class MultipleSecretsTests { } private void assertResponse(String path, String expectedMessage) { - this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody() - .jsonPath("secret").isEqualTo(expectedMessage); + this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody().jsonPath("secret") + .isEqualTo(expectedMessage); } } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java index b6b5d719..9e00777b 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/SecretsPropertySourceTest.java @@ -39,8 +39,7 @@ import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class) @TestPropertySource("classpath:/application-secrets.properties") public class SecretsPropertySourceTest { @@ -62,20 +61,15 @@ public class SecretsPropertySourceTest { KubernetesClient mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, NAMESPACE); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); - Secret secret = new SecretBuilder().withNewMetadata() - .withLabels(singletonMap("foo", "bar")).endMetadata() - .addToData("secretName", - Base64.getEncoder().encodeToString(SECRET_VALUE.getBytes())) - .build(); + Secret secret = new SecretBuilder().withNewMetadata().withLabels(singletonMap("foo", "bar")).endMetadata() + .addToData("secretName", Base64.getEncoder().encodeToString(SECRET_VALUE.getBytes())).build(); mockClient.secrets().inNamespace(NAMESPACE).create(secret); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java index d3410409..7574e283 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example/GreetingController.java @@ -35,20 +35,17 @@ public class GreetingController { } @RequestMapping("/api/greeting") - public ResponseMessage greeting( - @RequestParam(value = "name", defaultValue = "World") String name) { + public ResponseMessage greeting(@RequestParam(value = "name", defaultValue = "World") String name) { return new ResponseMessage(String.format(this.properties.getGreeting(), name)); } @RequestMapping("/api/farewell") - public ResponseMessage farewell( - @RequestParam(value = "name", defaultValue = "World") String name) { + public ResponseMessage farewell(@RequestParam(value = "name", defaultValue = "World") String name) { return new ResponseMessage(String.format(this.properties.getFarewell(), name)); } @RequestMapping("/api/morning") - public ResponseMessage morning( - @RequestParam(value = "name", defaultValue = "World") String name) { + public ResponseMessage morning(@RequestParam(value = "name", defaultValue = "World") String name) { return new ResponseMessage(String.format(this.properties.getMorning(), name)); } diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java index 8909fee0..b8932fba 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/example2/ExampleApp.java @@ -27,8 +27,7 @@ import org.springframework.web.bind.annotation.RestController; public class ExampleApp { public static void main(String[] args) { - SpringApplication - .run(org.springframework.cloud.kubernetes.config.example.App.class, args); + SpringApplication.run(org.springframework.cloud.kubernetes.config.example.App.class, args); } @RestController diff --git a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java index d96962ba..49f56c76 100644 --- a/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java +++ b/spring-cloud-kubernetes-config/src/test/java/org/springframework/cloud/kubernetes/config/reload/EventBasedConfigurationChangeDetectorTests.java @@ -60,22 +60,15 @@ public class EventBasedConfigurationChangeDetectorTests { when(mixedOperation.withName(eq("myconfigmap"))).thenReturn(resource); when(k8sClient.configMaps()).thenReturn(mixedOperation); - ConfigMapPropertySource configMapPropertySource = new ConfigMapPropertySource( - k8sClient, "myconfigmap"); - env.getPropertySources() - .addFirst(new BootstrapPropertySource(configMapPropertySource)); + ConfigMapPropertySource configMapPropertySource = new ConfigMapPropertySource(k8sClient, "myconfigmap"); + env.getPropertySources().addFirst(new BootstrapPropertySource(configMapPropertySource)); - ConfigurationUpdateStrategy configurationUpdateStrategy = mock( - ConfigurationUpdateStrategy.class); - ConfigMapPropertySourceLocator configMapLocator = mock( - ConfigMapPropertySourceLocator.class); - SecretsPropertySourceLocator secretsLocator = mock( - SecretsPropertySourceLocator.class); - EventBasedConfigurationChangeDetector detector = new EventBasedConfigurationChangeDetector( - env, configReloadProperties, k8sClient, configurationUpdateStrategy, - configMapLocator, secretsLocator); - List sources = detector - .findPropertySources(ConfigMapPropertySource.class); + ConfigurationUpdateStrategy configurationUpdateStrategy = mock(ConfigurationUpdateStrategy.class); + ConfigMapPropertySourceLocator configMapLocator = mock(ConfigMapPropertySourceLocator.class); + SecretsPropertySourceLocator secretsLocator = mock(SecretsPropertySourceLocator.class); + EventBasedConfigurationChangeDetector detector = new EventBasedConfigurationChangeDetector(env, + configReloadProperties, k8sClient, configurationUpdateStrategy, configMapLocator, secretsLocator); + List sources = detector.findPropertySources(ConfigMapPropertySource.class); assertThat(sources.size()).isEqualTo(1); assertThat(sources.get(0).getProperty("foo")).isEqualTo("bar"); } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetector.java index 9a0485d1..afeb17b6 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetector.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetector.java @@ -35,45 +35,41 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * @author Ryan Baxter */ -public class BusEventBasedConfigurationWatcherChangeDetector extends - ConfigurationWatcherChangeDetector implements ApplicationEventPublisherAware { +public class BusEventBasedConfigurationWatcherChangeDetector extends ConfigurationWatcherChangeDetector + implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; private BusProperties busProperties; - public BusEventBasedConfigurationWatcherChangeDetector( - AbstractEnvironment environment, ConfigReloadProperties properties, - KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, + public BusEventBasedConfigurationWatcherChangeDetector(AbstractEnvironment environment, + ConfigReloadProperties properties, KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator, - SecretsPropertySourceLocator secretsPropertySourceLocator, - BusProperties busProperties, + SecretsPropertySourceLocator secretsPropertySourceLocator, BusProperties busProperties, ConfigurationWatcherConfigurationProperties k8SConfigurationProperties, ThreadPoolTaskExecutor threadPoolTaskExecutor) { - super(environment, properties, kubernetesClient, strategy, - configMapPropertySourceLocator, secretsPropertySourceLocator, - k8SConfigurationProperties, threadPoolTaskExecutor); + super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator, + secretsPropertySourceLocator, k8SConfigurationProperties, threadPoolTaskExecutor); this.busProperties = busProperties; } @Override protected Mono triggerRefresh(Secret secret) { - this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent( - secret, busProperties.getId(), secret.getMetadata().getName())); + this.applicationEventPublisher.publishEvent( + new RefreshRemoteApplicationEvent(secret, busProperties.getId(), secret.getMetadata().getName())); return Mono.empty(); } @Override protected Mono triggerRefresh(ConfigMap configMap) { - this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent( - configMap, busProperties.getId(), configMap.getMetadata().getName())); + this.applicationEventPublisher.publishEvent( + new RefreshRemoteApplicationEvent(configMap, busProperties.getId(), configMap.getMetadata().getName())); return Mono.empty(); } @Override - public void setApplicationEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherApplication.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherApplication.java index e58da7e5..98523c7f 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherApplication.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherApplication.java @@ -26,8 +26,8 @@ import org.springframework.context.annotation.Configuration; * @author Ryan Baxter */ @Configuration(proxyBeanMethods = false) -@SpringBootApplication(exclude = { ContextFunctionCatalogAutoConfiguration.class, - RabbitHealthContributorAutoConfiguration.class }) +@SpringBootApplication( + exclude = { ContextFunctionCatalogAutoConfiguration.class, RabbitHealthContributorAutoConfiguration.class }) public class ConfigurationWatcherApplication { public static void main(String[] args) { diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java index e94429fa..0c8084d7 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherAutoConfiguration.java @@ -55,40 +55,35 @@ public class ConfigurationWatcherAutoConfiguration { @Bean @ConditionalOnMissingBean(ConfigurationWatcherChangeDetector.class) - public ConfigurationWatcherChangeDetector httpBasedConfigurationWatchChangeDetector( - AbstractEnvironment environment, KubernetesClient kubernetesClient, - ConfigMapPropertySourceLocator configMapPropertySourceLocator, - SecretsPropertySourceLocator secretsPropertySourceLocator, - ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy, + public ConfigurationWatcherChangeDetector httpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment, + KubernetesClient kubernetesClient, ConfigMapPropertySourceLocator configMapPropertySourceLocator, + SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties, + ConfigurationUpdateStrategy strategy, ConfigurationWatcherConfigurationProperties k8SConfigurationProperties, ThreadPoolTaskExecutor threadFactory, WebClient webClient, KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) { - return new HttpBasedConfigurationWatchChangeDetector(environment, properties, - kubernetesClient, strategy, configMapPropertySourceLocator, - secretsPropertySourceLocator, k8SConfigurationProperties, threadFactory, + return new HttpBasedConfigurationWatchChangeDetector(environment, properties, kubernetesClient, strategy, + configMapPropertySourceLocator, secretsPropertySourceLocator, k8SConfigurationProperties, threadFactory, webClient, kubernetesReactiveDiscoveryClient); } @Configuration @Profile("bus") - @Import({ ContextFunctionCatalogAutoConfiguration.class, - RabbitHealthContributorAutoConfiguration.class }) + @Import({ ContextFunctionCatalogAutoConfiguration.class, RabbitHealthContributorAutoConfiguration.class }) static class BusConfiguration { @Bean @ConditionalOnMissingBean(ConfigurationWatcherChangeDetector.class) - public ConfigurationWatcherChangeDetector busPropertyChangeWatcher( - BusProperties busProperties, AbstractEnvironment environment, - KubernetesClient kubernetesClient, + public ConfigurationWatcherChangeDetector busPropertyChangeWatcher(BusProperties busProperties, + AbstractEnvironment environment, KubernetesClient kubernetesClient, ConfigMapPropertySourceLocator configMapPropertySourceLocator, - SecretsPropertySourceLocator secretsPropertySourceLocator, - ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy, + SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties, + ConfigurationUpdateStrategy strategy, ConfigurationWatcherConfigurationProperties k8SConfigurationProperties, ThreadPoolTaskExecutor threadFactory) { - return new BusEventBasedConfigurationWatcherChangeDetector(environment, - properties, kubernetesClient, strategy, - configMapPropertySourceLocator, secretsPropertySourceLocator, - busProperties, k8SConfigurationProperties, threadFactory); + return new BusEventBasedConfigurationWatcherChangeDetector(environment, properties, kubernetesClient, + strategy, configMapPropertySourceLocator, secretsPropertySourceLocator, busProperties, + k8SConfigurationProperties, threadFactory); } } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherChangeDetector.java index 2551848e..5b8ed735 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherChangeDetector.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/ConfigurationWatcherChangeDetector.java @@ -36,24 +36,22 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * @author Ryan Baxter */ -public abstract class ConfigurationWatcherChangeDetector - extends EventBasedConfigurationChangeDetector { +public abstract class ConfigurationWatcherChangeDetector extends EventBasedConfigurationChangeDetector { private ScheduledExecutorService executorService; protected ConfigurationWatcherConfigurationProperties k8SConfigurationProperties; - public ConfigurationWatcherChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties properties, KubernetesClient kubernetesClient, - ConfigurationUpdateStrategy strategy, + public ConfigurationWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties, + KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator, SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigurationWatcherConfigurationProperties k8SConfigurationProperties, ThreadPoolTaskExecutor threadPoolTaskExecutor) { - super(environment, properties, kubernetesClient, strategy, - configMapPropertySourceLocator, secretsPropertySourceLocator); - this.executorService = Executors.newScheduledThreadPool( - k8SConfigurationProperties.getThreadPoolSize(), threadPoolTaskExecutor); + super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator, + secretsPropertySourceLocator); + this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(), + threadPoolTaskExecutor); this.k8SConfigurationProperties = k8SConfigurationProperties; } @@ -63,38 +61,33 @@ public abstract class ConfigurationWatcherChangeDetector if (log.isDebugEnabled()) { log.debug("Scheduling remote refresh event to be published for ConfigMap " + configMap.getMetadata().getName() + " to be published in " - + k8SConfigurationProperties.getRefreshDelay().toMillis() - + " milliseconds"); + + k8SConfigurationProperties.getRefreshDelay().toMillis() + " milliseconds"); } executorService.schedule(() -> triggerRefresh(configMap).subscribe(), - k8SConfigurationProperties.getRefreshDelay().toMillis(), - TimeUnit.MILLISECONDS); + k8SConfigurationProperties.getRefreshDelay().toMillis(), TimeUnit.MILLISECONDS); } else { if (log.isDebugEnabled()) { - log.debug("Not publishing event. ConfigMap " - + configMap.getMetadata().getName() - + " does not contain the label " - + k8SConfigurationProperties.getConfigLabel()); + log.debug("Not publishing event. ConfigMap " + configMap.getMetadata().getName() + + " does not contain the label " + k8SConfigurationProperties.getConfigLabel()); } } } protected boolean isSpringCloudKubernetesConfig(ConfigMap configMap) { - if (configMap.getMetadata() == null - || configMap.getMetadata().getLabels() == null) { + if (configMap.getMetadata() == null || configMap.getMetadata().getLabels() == null) { return false; } - return Boolean.parseBoolean(configMap.getMetadata().getLabels() - .getOrDefault(k8SConfigurationProperties.getConfigLabel(), "false")); + return Boolean.parseBoolean( + configMap.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getConfigLabel(), "false")); } protected boolean isSpringCloudKubernetesSecret(Secret secret) { if (secret.getMetadata() == null || secret.getMetadata().getLabels() == null) { return false; } - return Boolean.parseBoolean(secret.getMetadata().getLabels() - .getOrDefault(k8SConfigurationProperties.getSecretLabel(), "false")); + return Boolean.parseBoolean( + secret.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getSecretLabel(), "false")); } protected abstract Mono triggerRefresh(Secret secret); @@ -105,20 +98,17 @@ public abstract class ConfigurationWatcherChangeDetector protected void onEvent(Secret secret) { if (isSpringCloudKubernetesSecret(secret)) { if (log.isDebugEnabled()) { - log.debug("Scheduling remote refresh event to be published for Secret " - + secret.getMetadata().getName() + " to be published in " - + k8SConfigurationProperties.getRefreshDelay().toMillis() + log.debug("Scheduling remote refresh event to be published for Secret " + secret.getMetadata().getName() + + " to be published in " + k8SConfigurationProperties.getRefreshDelay().toMillis() + " milliseconds"); } executorService.schedule(() -> triggerRefresh(secret).subscribe(), - k8SConfigurationProperties.getRefreshDelay().toMillis(), - TimeUnit.MILLISECONDS); + k8SConfigurationProperties.getRefreshDelay().toMillis(), TimeUnit.MILLISECONDS); } else { if (log.isDebugEnabled()) { log.debug("Not publishing event. Secret " + secret.getMetadata().getName() - + " does not contain the label " - + k8SConfigurationProperties.getSecretLabel()); + + " does not contain the label " + k8SConfigurationProperties.getSecretLabel()); } } } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetector.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetector.java index 671d36f7..75c92428 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetector.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/main/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetector.java @@ -41,8 +41,7 @@ import org.springframework.web.util.UriComponentsBuilder; /** * @author Ryan Baxter */ -public class HttpBasedConfigurationWatchChangeDetector - extends ConfigurationWatcherChangeDetector { +public class HttpBasedConfigurationWatchChangeDetector extends ConfigurationWatcherChangeDetector { /** * Annotation key for actuator port and path. @@ -53,17 +52,15 @@ public class HttpBasedConfigurationWatchChangeDetector private KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient; - public HttpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment, - ConfigReloadProperties properties, KubernetesClient kubernetesClient, - ConfigurationUpdateStrategy strategy, + public HttpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties, + KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy, ConfigMapPropertySourceLocator configMapPropertySourceLocator, SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigurationWatcherConfigurationProperties k8SConfigurationProperties, ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient, KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) { - super(environment, properties, kubernetesClient, strategy, - configMapPropertySourceLocator, secretsPropertySourceLocator, - k8SConfigurationProperties, threadPoolTaskExecutor); + super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator, + secretsPropertySourceLocator, k8SConfigurationProperties, threadPoolTaskExecutor); this.webClient = webClient; this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient; } @@ -73,8 +70,7 @@ public class HttpBasedConfigurationWatchChangeDetector return refresh(secret.getMetadata()).then(); } - private void setActuatorUriFromAnnotation(UriComponentsBuilder actuatorUriBuilder, - String metadataUri) { + private void setActuatorUriFromAnnotation(UriComponentsBuilder actuatorUriBuilder, String metadataUri) { URI annotationUri = URI.create(metadataUri); actuatorUriBuilder.path(annotationUri.getPath() + "/refresh"); @@ -84,8 +80,7 @@ public class HttpBasedConfigurationWatchChangeDetector // 9090 in this case if (annotationUri.getPort() < 0) { if (annotationUri.getAuthority() != null) { - actuatorUriBuilder - .port(annotationUri.getAuthority().replaceFirst(":", "")); + actuatorUriBuilder.port(annotationUri.getAuthority().replaceFirst(":", "")); } } else { @@ -99,8 +94,8 @@ public class HttpBasedConfigurationWatchChangeDetector log.debug("Metadata actuator uri is: " + metadataUri); } - UriComponentsBuilder actuatorUriBuilder = UriComponentsBuilder.newInstance() - .scheme(si.getScheme()).host(si.getHost()); + UriComponentsBuilder actuatorUriBuilder = UriComponentsBuilder.newInstance().scheme(si.getScheme()) + .host(si.getHost()); if (!StringUtils.isEmpty(metadataUri)) { if (log.isDebugEnabled()) { @@ -111,8 +106,7 @@ public class HttpBasedConfigurationWatchChangeDetector else { Integer port = k8SConfigurationProperties.getActuatorPort() < 0 ? si.getPort() : k8SConfigurationProperties.getActuatorPort(); - actuatorUriBuilder = actuatorUriBuilder - .path(k8SConfigurationProperties.getActuatorPath() + "/refresh") + actuatorUriBuilder = actuatorUriBuilder.path(k8SConfigurationProperties.getActuatorPath() + "/refresh") .port(port); } @@ -121,28 +115,22 @@ public class HttpBasedConfigurationWatchChangeDetector protected Flux> refresh(ObjectMeta objectMeta) { - return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName()) - .flatMap(si -> { - URI actuatorUri = getActuatorUri(si); - if (log.isDebugEnabled()) { - log.debug("Sending refresh request for " + objectMeta.getName() - + " to URI " + actuatorUri.toString()); - } - Mono> response = webClient.post() - .uri(actuatorUri).retrieve().toBodilessEntity() - .doOnSuccess(re -> { - if (log.isDebugEnabled()) { - log.debug("Refresh sent to " + objectMeta.getName() - + " at URI address " + actuatorUri - + " returned a " - + re.getStatusCode().toString()); - } - }).doOnError(t -> { - log.warn("Refresh sent to " + objectMeta.getName() - + " failed", t); - }); - return response; - }); + return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName()).flatMap(si -> { + URI actuatorUri = getActuatorUri(si); + if (log.isDebugEnabled()) { + log.debug("Sending refresh request for " + objectMeta.getName() + " to URI " + actuatorUri.toString()); + } + Mono> response = webClient.post().uri(actuatorUri).retrieve().toBodilessEntity() + .doOnSuccess(re -> { + if (log.isDebugEnabled()) { + log.debug("Refresh sent to " + objectMeta.getName() + " at URI address " + actuatorUri + + " returned a " + re.getStatusCode().toString()); + } + }).doOnError(t -> { + log.warn("Refresh sent to " + objectMeta.getName() + " failed", t); + }); + return response; + }); } @Override diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetectorTests.java index be8c3c46..5a38e2b0 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetectorTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/BusEventBasedConfigurationWatcherChangeDetectorTests.java @@ -76,11 +76,9 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests { ConfigReloadProperties configReloadProperties = new ConfigReloadProperties(); configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties(); busProperties = new BusProperties(); - changeDetector = new BusEventBasedConfigurationWatcherChangeDetector( - mockEnvironment, configReloadProperties, client, updateStrategy, - configMapPropertySourceLocator, secretsPropertySourceLocator, - busProperties, configurationWatcherConfigurationProperties, - threadPoolTaskExecutor); + changeDetector = new BusEventBasedConfigurationWatcherChangeDetector(mockEnvironment, configReloadProperties, + client, updateStrategy, configMapPropertySourceLocator, secretsPropertySourceLocator, busProperties, + configurationWatcherConfigurationProperties, threadPoolTaskExecutor); changeDetector.setApplicationEventPublisher(applicationEventPublisher); } @@ -95,8 +93,7 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests { .forClass(RefreshRemoteApplicationEvent.class); verify(applicationEventPublisher).publishEvent(argumentCaptor.capture()); assertThat(argumentCaptor.getValue().getSource()).isEqualTo(configMap); - assertThat(argumentCaptor.getValue().getOriginService()) - .isEqualTo(busProperties.getId()); + assertThat(argumentCaptor.getValue().getOriginService()).isEqualTo(busProperties.getId()); assertThat(argumentCaptor.getValue().getDestinationService()).isEqualTo("foo:**"); } @@ -111,8 +108,7 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests { .forClass(RefreshRemoteApplicationEvent.class); verify(applicationEventPublisher).publishEvent(argumentCaptor.capture()); assertThat(argumentCaptor.getValue().getSource()).isEqualTo(secret); - assertThat(argumentCaptor.getValue().getOriginService()) - .isEqualTo(busProperties.getId()); + assertThat(argumentCaptor.getValue().getOriginService()).isEqualTo(busProperties.getId()); assertThat(argumentCaptor.getValue().getDestinationService()).isEqualTo("foo:**"); } diff --git a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetectorTests.java b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetectorTests.java index fc6bbb39..79857387 100644 --- a/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetectorTests.java +++ b/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-configuration-watcher/src/test/java/org/springframework/cloud/kubernetes/configuration/watcher/HttpBasedConfigurationWatchChangeDetectorTests.java @@ -98,21 +98,18 @@ public class HttpBasedConfigurationWatchChangeDetectorTests { EndpointPort fooEndpointPort = new EndpointPort(); fooEndpointPort.setPort(wireMockRule.port()); List instances = new ArrayList<>(); - KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance( - "foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(), - new HashMap<>(), false); + KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo", + fooEndpointAddress.getIp(), fooEndpointPort.getPort(), new HashMap<>(), false); instances.add(fooServiceInstance); - when(reactiveDiscoveryClient.getInstances(eq("foo"))) - .thenReturn(Flux.fromIterable(instances)); + when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances)); MockEnvironment mockEnvironment = new MockEnvironment(); ConfigReloadProperties configReloadProperties = new ConfigReloadProperties(); configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties(); WebClient webClient = WebClient.builder().build(); - changeDetector = new HttpBasedConfigurationWatchChangeDetector(mockEnvironment, - configReloadProperties, client, updateStrategy, - configMapPropertySourceLocator, secretsPropertySourceLocator, - configurationWatcherConfigurationProperties, threadPoolTaskExecutor, - webClient, reactiveDiscoveryClient); + changeDetector = new HttpBasedConfigurationWatchChangeDetector(mockEnvironment, configReloadProperties, client, + updateStrategy, configMapPropertySourceLocator, secretsPropertySourceLocator, + configurationWatcherConfigurationProperties, threadPoolTaskExecutor, webClient, + reactiveDiscoveryClient); } @Test @@ -122,8 +119,7 @@ public class HttpBasedConfigurationWatchChangeDetectorTests { objectMeta.setName("foo"); configMap.setMetadata(objectMeta); WireMock.configureFor("localhost", wireMockRule.port()); - stubFor(post(WireMock.urlEqualTo("/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/actuator/refresh"))); } @@ -135,40 +131,33 @@ public class HttpBasedConfigurationWatchChangeDetectorTests { objectMeta.setName("foo"); secret.setMetadata(objectMeta); WireMock.configureFor("localhost", wireMockRule.port()); - stubFor(post(WireMock.urlEqualTo("/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/actuator/refresh"))); } @Test - public void triggerConfigMapRefreshWithPropertiesBasedActuatorPath() - throws InterruptedException { - configurationWatcherConfigurationProperties - .setActuatorPath("/my/custom/actuator"); + public void triggerConfigMapRefreshWithPropertiesBasedActuatorPath() throws InterruptedException { + configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator"); ConfigMap configMap = new ConfigMap(); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setName("foo"); configMap.setMetadata(objectMeta); WireMock.configureFor("localhost", wireMockRule.port()); - stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh"))); } @Test - public void triggerSecretRefreshWithPropertiesBasedActuatorPath() - throws InterruptedException { - configurationWatcherConfigurationProperties - .setActuatorPath("/my/custom/actuator"); + public void triggerSecretRefreshWithPropertiesBasedActuatorPath() throws InterruptedException { + configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator"); Secret secret = new Secret(); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setName("foo"); secret.setMetadata(objectMeta); WireMock.configureFor("localhost", wireMockRule.port()); - stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh"))); } @@ -176,26 +165,22 @@ public class HttpBasedConfigurationWatchChangeDetectorTests { @Test public void triggerConfigMapRefreshWithAnnotationActuatorPath() { Map metadata = new HashMap<>(); - metadata.put(ANNOTATION_KEY, - "http://:" + wireMockRule.port() + "/my/custom/actuator"); + metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() + "/my/custom/actuator"); EndpointAddress fooEndpointAddress = new EndpointAddress(); fooEndpointAddress.setIp("127.0.0.1"); fooEndpointAddress.setHostname("localhost"); EndpointPort fooEndpointPort = new EndpointPort(); fooEndpointPort.setPort(wireMockRule.port()); List instances = new ArrayList<>(); - KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance( - "foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(), - metadata, false); + KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo", + fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false); instances.add(fooServiceInstance); - when(reactiveDiscoveryClient.getInstances(eq("foo"))) - .thenReturn(Flux.fromIterable(instances)); + when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances)); ConfigMap configMap = new ConfigMap(); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setName("foo"); configMap.setMetadata(objectMeta); - stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh"))); } @@ -203,26 +188,22 @@ public class HttpBasedConfigurationWatchChangeDetectorTests { @Test public void triggerSecretRefreshWithAnnotationActuatorPath() { Map metadata = new HashMap<>(); - metadata.put(ANNOTATION_KEY, - "http://:" + wireMockRule.port() + "/my/custom/actuator"); + metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() + "/my/custom/actuator"); EndpointAddress fooEndpointAddress = new EndpointAddress(); fooEndpointAddress.setIp("127.0.0.1"); fooEndpointAddress.setHostname("localhost"); EndpointPort fooEndpointPort = new EndpointPort(); fooEndpointPort.setPort(wireMockRule.port()); List instances = new ArrayList<>(); - KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance( - "foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(), - metadata, false); + KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo", + fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false); instances.add(fooServiceInstance); - when(reactiveDiscoveryClient.getInstances(eq("foo"))) - .thenReturn(Flux.fromIterable(instances)); + when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances)); Secret secret = new Secret(); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setName("foo"); secret.setMetadata(objectMeta); - stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")) - .willReturn(aResponse().withStatus(200))); + stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200))); StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete(); verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh"))); } diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesAutoConfiguration.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesAutoConfiguration.java index 9ccdacd1..425e6b0f 100644 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesAutoConfiguration.java +++ b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesAutoConfiguration.java @@ -76,65 +76,41 @@ public class KubernetesAutoConfiguration { @Bean @ConditionalOnMissingBean(Config.class) - public Config kubernetesClientConfig( - KubernetesClientProperties kubernetesClientProperties) { + public Config kubernetesClientConfig(KubernetesClientProperties kubernetesClientProperties) { Config base = Config.autoConfigure(null); Config properties = new ConfigBuilder(base) // Only set values that have been explicitly specified - .withMasterUrl(or(kubernetesClientProperties.getMasterUrl(), - base.getMasterUrl())) - .withApiVersion(or(kubernetesClientProperties.getApiVersion(), - base.getApiVersion())) - .withNamespace(or(kubernetesClientProperties.getNamespace(), - base.getNamespace())) - .withUsername( - or(kubernetesClientProperties.getUsername(), base.getUsername())) - .withPassword( - or(kubernetesClientProperties.getPassword(), base.getPassword())) + .withMasterUrl(or(kubernetesClientProperties.getMasterUrl(), base.getMasterUrl())) + .withApiVersion(or(kubernetesClientProperties.getApiVersion(), base.getApiVersion())) + .withNamespace(or(kubernetesClientProperties.getNamespace(), base.getNamespace())) + .withUsername(or(kubernetesClientProperties.getUsername(), base.getUsername())) + .withPassword(or(kubernetesClientProperties.getPassword(), base.getPassword())) - .withCaCertFile(or(kubernetesClientProperties.getCaCertFile(), - base.getCaCertFile())) - .withCaCertData(or(kubernetesClientProperties.getCaCertData(), - base.getCaCertData())) + .withCaCertFile(or(kubernetesClientProperties.getCaCertFile(), base.getCaCertFile())) + .withCaCertData(or(kubernetesClientProperties.getCaCertData(), base.getCaCertData())) - .withClientKeyFile(or(kubernetesClientProperties.getClientKeyFile(), - base.getClientKeyFile())) - .withClientKeyData(or(kubernetesClientProperties.getClientKeyData(), - base.getClientKeyData())) + .withClientKeyFile(or(kubernetesClientProperties.getClientKeyFile(), base.getClientKeyFile())) + .withClientKeyData(or(kubernetesClientProperties.getClientKeyData(), base.getClientKeyData())) - .withClientCertFile(or(kubernetesClientProperties.getClientCertFile(), - base.getClientCertFile())) - .withClientCertData(or(kubernetesClientProperties.getClientCertData(), - base.getClientCertData())) + .withClientCertFile(or(kubernetesClientProperties.getClientCertFile(), base.getClientCertFile())) + .withClientCertData(or(kubernetesClientProperties.getClientCertData(), base.getClientCertData())) // No magic is done for the properties below so we leave them as is. - .withClientKeyAlgo(or(kubernetesClientProperties.getClientKeyAlgo(), - base.getClientKeyAlgo())) + .withClientKeyAlgo(or(kubernetesClientProperties.getClientKeyAlgo(), base.getClientKeyAlgo())) .withClientKeyPassphrase( - or(kubernetesClientProperties.getClientKeyPassphrase(), - base.getClientKeyPassphrase())) + or(kubernetesClientProperties.getClientKeyPassphrase(), base.getClientKeyPassphrase())) .withConnectionTimeout( - orDurationInt(kubernetesClientProperties.getConnectionTimeout(), - base.getConnectionTimeout())) + orDurationInt(kubernetesClientProperties.getConnectionTimeout(), base.getConnectionTimeout())) .withRequestTimeout( - orDurationInt(kubernetesClientProperties.getRequestTimeout(), - base.getRequestTimeout())) + orDurationInt(kubernetesClientProperties.getRequestTimeout(), base.getRequestTimeout())) .withRollingTimeout( - orDurationLong(kubernetesClientProperties.getRollingTimeout(), - base.getRollingTimeout())) - .withTrustCerts(or(kubernetesClientProperties.isTrustCerts(), - base.isTrustCerts())) - .withHttpProxy(or(kubernetesClientProperties.getHttpProxy(), - base.getHttpProxy())) - .withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(), - base.getHttpsProxy())) - .withProxyUsername(or(kubernetesClientProperties.getProxyUsername(), - base.getProxyUsername())) - .withProxyPassword(or(kubernetesClientProperties.getProxyPassword(), - base.getProxyPassword())) - .withNoProxy( - or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())) - .build(); + orDurationLong(kubernetesClientProperties.getRollingTimeout(), base.getRollingTimeout())) + .withTrustCerts(or(kubernetesClientProperties.isTrustCerts(), base.isTrustCerts())) + .withHttpProxy(or(kubernetesClientProperties.getHttpProxy(), base.getHttpProxy())) + .withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(), base.getHttpsProxy())) + .withProxyUsername(or(kubernetesClientProperties.getProxyUsername(), base.getProxyUsername())) + .withProxyPassword(or(kubernetesClientProperties.getProxyPassword(), base.getProxyPassword())) + .withNoProxy(or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())).build(); if (properties.getNamespace() == null || properties.getNamespace().isEmpty()) { LOG.warn("No namespace has been detected. Please specify " diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesHealthIndicator.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesHealthIndicator.java index 85da8fae..8aef880e 100644 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesHealthIndicator.java +++ b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/KubernetesHealthIndicator.java @@ -40,12 +40,10 @@ public class KubernetesHealthIndicator extends AbstractHealthIndicator { try { Pod current = this.utils.currentPod().get(); if (current != null) { - builder.up().withDetail("inside", true) - .withDetail("namespace", current.getMetadata().getNamespace()) + builder.up().withDetail("inside", true).withDetail("namespace", current.getMetadata().getNamespace()) .withDetail("podName", current.getMetadata().getName()) .withDetail("podIp", current.getStatus().getPodIP()) - .withDetail("serviceAccount", - current.getSpec().getServiceAccountName()) + .withDetail("serviceAccount", current.getSpec().getServiceAccountName()) .withDetail("nodeName", current.getSpec().getNodeName()) .withDetail("hostIp", current.getStatus().getHostIP()) .withDetail("labels", current.getMetadata().getLabels()); diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/StandardPodUtils.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/StandardPodUtils.java index 1e68fc35..404283c0 100644 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/StandardPodUtils.java +++ b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/StandardPodUtils.java @@ -47,8 +47,7 @@ public class StandardPodUtils implements PodUtils { public StandardPodUtils(KubernetesClient client) { if (client == null) { - throw new IllegalArgumentException( - "Must provide an instance of KubernetesClient"); + throw new IllegalArgumentException("Must provide an instance of KubernetesClient"); } this.client = client; @@ -76,10 +75,8 @@ public class StandardPodUtils implements PodUtils { } } catch (Throwable t) { - LOG.warn("Failed to get pod with name:[" + this.hostName - + "]. You should look into this if things aren't" - + " working as you expect. Are you missing serviceaccount permissions?", - t); + LOG.warn("Failed to get pod with name:[" + this.hostName + "]. You should look into this if things aren't" + + " working as you expect. Are you missing serviceaccount permissions?", t); return null; } } @@ -90,8 +87,7 @@ public class StandardPodUtils implements PodUtils { private boolean isServiceAccountFound() { return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists() - && Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile() - .exists(); + && Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists(); } } diff --git a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java index e2402e14..8c4070cd 100644 --- a/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java +++ b/spring-cloud-kubernetes-core/src/main/java/org/springframework/cloud/kubernetes/profile/KubernetesProfileEnvironmentPostProcessor.java @@ -28,11 +28,9 @@ import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; -public class KubernetesProfileEnvironmentPostProcessor - implements EnvironmentPostProcessor, Ordered { +public class KubernetesProfileEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { - private static final Log LOG = LogFactory - .getLog(KubernetesProfileEnvironmentPostProcessor.class); + private static final Log LOG = LogFactory.getLog(KubernetesProfileEnvironmentPostProcessor.class); // Before ConfigFileApplicationListener so values there can use these ones private static final int ORDER = ConfigFileApplicationListener.DEFAULT_ORDER - 1; @@ -40,11 +38,10 @@ public class KubernetesProfileEnvironmentPostProcessor private static final String KUBERNETES_PROFILE = "kubernetes"; @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - final boolean kubernetesEnabled = environment - .getProperty("spring.cloud.kubernetes.enabled", Boolean.class, true); + final boolean kubernetesEnabled = environment.getProperty("spring.cloud.kubernetes.enabled", Boolean.class, + true); if (!kubernetesEnabled) { return; } @@ -64,8 +61,7 @@ public class KubernetesProfileEnvironmentPostProcessor } else { if (LOG.isDebugEnabled()) { - LOG.warn( - "Not running inside kubernetes. Skipping 'kubernetes' profile activation."); + LOG.warn("Not running inside kubernetes. Skipping 'kubernetes' profile activation."); } } } diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorDisabledTest.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorDisabledTest.java index b239a497..91f7f11c 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorDisabledTest.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorDisabledTest.java @@ -36,8 +36,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "management.health.kubernetes.enabled=false" }) public class HealthIndicatorDisabledTest { @@ -57,20 +56,18 @@ public class HealthIndicatorDisabledTest { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); } @Test public void healthEndpointShouldContainKubernetes() { this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk() - .expectBody(String.class).value(not(containsString("kubernetes"))); + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(not(containsString("kubernetes"))); } } diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorTest.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorTest.java index 1bfbc4ed..46775655 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorTest.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/HealthIndicatorTest.java @@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; import static org.hamcrest.Matchers.containsString; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "management.endpoint.health.show-details=always" }) public class HealthIndicatorTest { @@ -56,12 +55,10 @@ public class HealthIndicatorTest { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @@ -69,8 +66,8 @@ public class HealthIndicatorTest { @Test public void healthEndpointShouldContainKubernetes() { this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk() - .expectBody(String.class).value(containsString("kubernetes")); + .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class) + .value(containsString("kubernetes")); } } diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/InfoContributorTest.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/InfoContributorTest.java index afd4c2aa..79e7fdfa 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/InfoContributorTest.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/InfoContributorTest.java @@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; import static org.hamcrest.Matchers.containsString; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class) public class InfoContributorTest { @ClassRule @@ -55,21 +54,18 @@ public class InfoContributorTest { mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @Test public void infoEndpointShouldContainKubernetes() { - this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk() - .expectBody(String.class).value(containsString("kubernetes")); + this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON) + .exchange().expectStatus().isOk().expectBody(String.class).value(containsString("kubernetes")); } } diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java index 6edd151a..2f00210a 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/KubernetesAutoConfigurationTests.java @@ -33,8 +33,7 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = App.class, +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = { "spring.cloud.kubernetes.client.password=mypassword", "spring.cloud.kubernetes.client.proxy-password=myproxypassword" }) public class KubernetesAutoConfigurationTests { @@ -50,12 +49,10 @@ public class KubernetesAutoConfigurationTests { KubernetesClient mockClient = server.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @@ -65,10 +62,8 @@ public class KubernetesAutoConfigurationTests { assertThat(context.getBeanNamesForType(Config.class)).hasSize(1); assertThat(context.getBeanNamesForType(KubernetesClient.class)).hasSize(1); assertThat(context.getBeanNamesForType(StandardPodUtils.class)).hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesHealthIndicator.class)) - .hasSize(1); - assertThat(context.getBeanNamesForType(KubernetesInfoContributor.class)) - .hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesHealthIndicator.class)).hasSize(1); + assertThat(context.getBeanNamesForType(KubernetesInfoContributor.class)).hasSize(1); Config config = context.getBean(Config.class); assertThat(config.getPassword()).isEqualTo("mypassword"); diff --git a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/LazilyInstantiateTest.java b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/LazilyInstantiateTest.java index 71a3864c..b9caa520 100644 --- a/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/LazilyInstantiateTest.java +++ b/spring-cloud-kubernetes-core/src/test/java/org/springframework/cloud/kubernetes/LazilyInstantiateTest.java @@ -53,8 +53,7 @@ public class LazilyInstantiateTest { @Test public void factoryReturnsSingletonFromSupplier() { - LazilyInstantiate lazyStringFactory = LazilyInstantiate - .using(this.mockSupplier); + LazilyInstantiate lazyStringFactory = LazilyInstantiate.using(this.mockSupplier); String singletonString = lazyStringFactory.get(); // verify @@ -63,8 +62,7 @@ public class LazilyInstantiateTest { @Test public void factoryOnlyCallsSupplierOnce() { - LazilyInstantiate lazyStringFactory = LazilyInstantiate - .using(this.mockSupplier); + LazilyInstantiate lazyStringFactory = LazilyInstantiate.using(this.mockSupplier); lazyStringFactory.get(); // mock will throw exception if it is called more than once diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConditionalOnKubernetesDiscoveryEnabled.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConditionalOnKubernetesDiscoveryEnabled.java index 0bbdcbbc..3be47732 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConditionalOnKubernetesDiscoveryEnabled.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/ConditionalOnKubernetesDiscoveryEnabled.java @@ -36,8 +36,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@ConditionalOnProperty(value = "spring.cloud.kubernetes.discovery.enabled", - matchIfMissing = true) +@ConditionalOnProperty(value = "spring.cloud.kubernetes.discovery.enabled", matchIfMissing = true) public @interface ConditionalOnKubernetesDiscoveryEnabled { } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolver.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolver.java index 1631ebaf..a8a390fd 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolver.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolver.java @@ -35,8 +35,7 @@ import org.apache.commons.logging.LogFactory; */ class DefaultIsServicePortSecureResolver { - private static final Log log = LogFactory - .getLog(DefaultIsServicePortSecureResolver.class); + private static final Log log = LogFactory.getLog(DefaultIsServicePortSecureResolver.class); private static final Set TRUTHY_STRINGS = new HashSet() { { @@ -54,33 +53,27 @@ class DefaultIsServicePortSecureResolver { } boolean resolve(Input input) { - final String securedLabelValue = input.getServiceLabels().getOrDefault("secured", - "false"); + final String securedLabelValue = input.getServiceLabels().getOrDefault("secured", "false"); if (TRUTHY_STRINGS.contains(securedLabelValue)) { if (log.isDebugEnabled()) { - log.debug("Considering service with name: " + input.getServiceName() - + " and port " + input.getPort() + log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort() + " is secure since the service contains a true value for the 'secured' label"); } return true; } - final String securedAnnotationValue = input.getServiceAnnotations() - .getOrDefault("secured", "false"); + final String securedAnnotationValue = input.getServiceAnnotations().getOrDefault("secured", "false"); if (TRUTHY_STRINGS.contains(securedAnnotationValue)) { if (log.isDebugEnabled()) { - log.debug("Considering service with name: " + input.getServiceName() - + " and port " + input.getPort() + log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort() + " is secure since the service contains a true value for the 'secured' annotation"); } return true; } - if (input.getPort() != null - && this.properties.getKnownSecurePorts().contains(input.getPort())) { + if (input.getPort() != null && this.properties.getKnownSecurePorts().contains(input.getPort())) { if (log.isDebugEnabled()) { - log.debug("Considering service with name: " + input.getServiceName() - + " and port " + input.getPort() + log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort() + " is secure due to the port being a known https port"); } return true; @@ -109,8 +102,7 @@ class DefaultIsServicePortSecureResolver { this.port = port; this.serviceName = serviceName; this.serviceLabels = serviceLabels == null ? new HashMap<>() : serviceLabels; - this.serviceAnnotations = serviceAnnotations == null ? new HashMap<>() - : serviceAnnotations; + this.serviceAnnotations = serviceAnnotations == null ? new HashMap<>() : serviceAnnotations; } public String getServiceName() { diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatch.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatch.java index 416c5371..f3c79372 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatch.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatch.java @@ -40,8 +40,7 @@ import org.springframework.scheduling.annotation.Scheduled; */ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware { - private static final Logger logger = LoggerFactory - .getLogger(KubernetesCatalogWatch.class); + private static final Logger logger = LoggerFactory.getLogger(KubernetesCatalogWatch.class); private final KubernetesClient kubernetesClient; @@ -51,8 +50,7 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware { private ApplicationEventPublisher publisher; - public KubernetesCatalogWatch(KubernetesClient kubernetesClient, - KubernetesDiscoveryProperties properties) { + public KubernetesCatalogWatch(KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties) { this.kubernetesClient = kubernetesClient; this.properties = properties; } @@ -62,8 +60,7 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware { this.publisher = publisher; } - @Scheduled( - fixedDelayString = "${spring.cloud.kubernetes.discovery.catalogServicesWatchDelay:30000}") + @Scheduled(fixedDelayString = "${spring.cloud.kubernetes.discovery.catalogServicesWatchDelay:30000}") public void catalogServicesWatch() { try { List previousState = this.catalogEndpointsState.get(); @@ -71,24 +68,21 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware { // not all pods participate in the service discovery. only those that have // endpoints. List endpoints = this.properties.isAllNamespaces() - ? this.kubernetesClient.endpoints().inAnyNamespace() - .withLabels(properties.getServiceLabels()).list().getItems() - : this.kubernetesClient.endpoints() - .withLabels(properties.getServiceLabels()).list().getItems(); - List endpointsPodNames = endpoints.stream().map(Endpoints::getSubsets) - .filter(Objects::nonNull).flatMap(Collection::stream) - .map(EndpointSubset::getAddresses).filter(Objects::nonNull) - .flatMap(Collection::stream).map(EndpointAddress::getTargetRef) - .filter(Objects::nonNull).map(ObjectReference::getName) // pod name - // unique in - // namespace + ? this.kubernetesClient.endpoints().inAnyNamespace().withLabels(properties.getServiceLabels()) + .list().getItems() + : this.kubernetesClient.endpoints().withLabels(properties.getServiceLabels()).list().getItems(); + List endpointsPodNames = endpoints.stream().map(Endpoints::getSubsets).filter(Objects::nonNull) + .flatMap(Collection::stream).map(EndpointSubset::getAddresses).filter(Objects::nonNull) + .flatMap(Collection::stream).map(EndpointAddress::getTargetRef).filter(Objects::nonNull) + .map(ObjectReference::getName) // pod name + // unique in + // namespace .sorted(String::compareTo).collect(Collectors.toList()); this.catalogEndpointsState.set(endpointsPodNames); if (!endpointsPodNames.equals(previousState)) { - logger.trace("Received endpoints update from kubernetesClient: {}", - endpointsPodNames); + logger.trace("Received endpoints update from kubernetesClient: {}", endpointsPodNames); this.publisher.publishEvent(new HeartbeatEvent(this, endpointsPodNames)); } } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchAutoConfiguration.java index c0cb2a5f..67521677 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchAutoConfiguration.java @@ -39,8 +39,7 @@ public class KubernetesCatalogWatchAutoConfiguration { @Bean @ConditionalOnMissingBean - @ConditionalOnProperty( - name = "spring.cloud.kubernetes.discovery.catalog-services-watch.enabled", + @ConditionalOnProperty(name = "spring.cloud.kubernetes.discovery.catalog-services-watch.enabled", matchIfMissing = true) public KubernetesCatalogWatch kubernetesCatalogWatch(KubernetesClient client, KubernetesDiscoveryProperties properties) { diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java index 3479a602..70db8717 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClient.java @@ -60,8 +60,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { private final SpelExpressionParser parser = new SpelExpressionParser(); - private final SimpleEvaluationContext evalCtxt = SimpleEvaluationContext - .forReadOnlyDataBinding().withInstanceMethods().build(); + private final SimpleEvaluationContext evalCtxt = SimpleEvaluationContext.forReadOnlyDataBinding() + .withInstanceMethods().build(); private KubernetesClient client; @@ -73,8 +73,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { new DefaultIsServicePortSecureResolver(kubernetesDiscoveryProperties)); } - KubernetesDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties kubernetesDiscoveryProperties, + KubernetesDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties kubernetesDiscoveryProperties, KubernetesClientServicesFunction kubernetesClientServicesFunction, DefaultIsServicePortSecureResolver isServicePortSecureResolver) { @@ -99,12 +98,10 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { @Override public List getInstances(String serviceId) { - Assert.notNull(serviceId, - "[Assertion failed] - the object argument must not be null"); + Assert.notNull(serviceId, "[Assertion failed] - the object argument must not be null"); List subsetsNS = this.getEndPointsList(serviceId).stream() - .map(endpoints -> getSubsetsFromEndpoints(endpoints)) - .collect(Collectors.toList()); + .map(endpoints -> getSubsetsFromEndpoints(endpoints)).collect(Collectors.toList()); List instances = new ArrayList<>(); if (!subsetsNS.isEmpty()) { @@ -118,24 +115,20 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { public List getEndPointsList(String serviceId) { return this.properties.isAllNamespaces() - ? this.client.endpoints().inAnyNamespace() - .withField("metadata.name", serviceId) + ? this.client.endpoints().inAnyNamespace().withField("metadata.name", serviceId) .withLabels(properties.getServiceLabels()).list().getItems() : this.client.endpoints().withField("metadata.name", serviceId) .withLabels(properties.getServiceLabels()).list().getItems(); } - private List getNamespaceServiceInstances(EndpointSubsetNS es, - String serviceId) { + private List getNamespaceServiceInstances(EndpointSubsetNS es, String serviceId) { String namespace = es.getNamespace(); List subsets = es.getEndpointSubset(); List instances = new ArrayList<>(); if (!subsets.isEmpty()) { - final Service service = this.client.services().inNamespace(namespace) - .withName(serviceId).get(); + final Service service = this.client.services().inNamespace(namespace).withName(serviceId).get(); final Map serviceMetadata = this.getServiceMetadata(service); - KubernetesDiscoveryProperties.Metadata metadataProps = this.properties - .getMetadata(); + KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.getMetadata(); for (EndpointSubset s : subsets) { // Extend the service metadata map with per-endpoint port information (if @@ -144,10 +137,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { if (metadataProps.isAddPorts()) { Map ports = s.getPorts().stream() .filter(port -> !StringUtils.isEmpty(port.getName())) - .collect(toMap(EndpointPort::getName, - port -> Integer.toString(port.getPort()))); - Map portMetadata = getMapWithPrefixedKeys(ports, - metadataProps.getPortsPrefix()); + .collect(toMap(EndpointPort::getName, port -> Integer.toString(port.getPort()))); + Map portMetadata = getMapWithPrefixedKeys(ports, metadataProps.getPortsPrefix()); if (log.isDebugEnabled()) { log.debug("Adding port metadata: " + portMetadata); } @@ -166,15 +157,11 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { } EndpointPort endpointPort = findEndpointPort(s); - instances.add(new KubernetesServiceInstance(instanceId, serviceId, - endpointAddress.getIp(), endpointPort.getPort(), - endpointMetadata, - this.isServicePortSecureResolver - .resolve(new DefaultIsServicePortSecureResolver.Input( - endpointPort.getPort(), - service.getMetadata().getName(), - service.getMetadata().getLabels(), - service.getMetadata().getAnnotations())))); + instances.add(new KubernetesServiceInstance(instanceId, serviceId, endpointAddress.getIp(), + endpointPort.getPort(), endpointMetadata, + this.isServicePortSecureResolver.resolve(new DefaultIsServicePortSecureResolver.Input( + endpointPort.getPort(), service.getMetadata().getName(), + service.getMetadata().getLabels(), service.getMetadata().getAnnotations())))); } } } @@ -184,19 +171,17 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { private Map getServiceMetadata(Service service) { final Map serviceMetadata = new HashMap<>(); - KubernetesDiscoveryProperties.Metadata metadataProps = this.properties - .getMetadata(); + KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.getMetadata(); if (metadataProps.isAddLabels()) { - Map labelMetadata = getMapWithPrefixedKeys( - service.getMetadata().getLabels(), metadataProps.getLabelsPrefix()); + Map labelMetadata = getMapWithPrefixedKeys(service.getMetadata().getLabels(), + metadataProps.getLabelsPrefix()); if (log.isDebugEnabled()) { log.debug("Adding label metadata: " + labelMetadata); } serviceMetadata.putAll(labelMetadata); } if (metadataProps.isAddAnnotations()) { - Map annotationMetadata = getMapWithPrefixedKeys( - service.getMetadata().getAnnotations(), + Map annotationMetadata = getMapWithPrefixedKeys(service.getMetadata().getAnnotations(), metadataProps.getAnnotationsPrefix()); if (log.isDebugEnabled()) { log.debug("Adding annotation metadata: " + annotationMetadata); @@ -216,14 +201,12 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { else { Predicate portPredicate; if (!StringUtils.isEmpty(properties.getPrimaryPortName())) { - portPredicate = port -> properties.getPrimaryPortName() - .equalsIgnoreCase(port.getName()); + portPredicate = port -> properties.getPrimaryPortName().equalsIgnoreCase(port.getName()); } else { portPredicate = port -> true; } - endpointPort = ports.stream().filter(portPredicate).findAny() - .orElseThrow(IllegalStateException::new); + endpointPort = ports.stream().filter(portPredicate).findAny().orElseThrow(IllegalStateException::new); } return endpointPort; } @@ -244,8 +227,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { // returns a new map that contain all the entries of the original map // but with the keys prefixed // if the prefix is null or empty, the map itself is returned (unchanged of course) - private Map getMapWithPrefixedKeys(Map map, - String prefix) { + private Map getMapWithPrefixedKeys(Map map, String prefix) { if (map == null) { return new HashMap<>(); } @@ -271,8 +253,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { else { Expression filterExpr = this.parser.parseExpression(spelExpression); filteredServices = (Service instance) -> { - Boolean include = filterExpr.getValue(this.evalCtxt, instance, - Boolean.class); + Boolean include = filterExpr.getValue(this.evalCtxt, instance, Boolean.class); if (include == null) { return false; } @@ -283,9 +264,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient { } public List getServices(Predicate filter) { - return this.kubernetesClientServicesFunction.apply(this.client).list().getItems() - .stream().filter(filter).map(s -> s.getMetadata().getName()) - .collect(Collectors.toList()); + return this.kubernetesClientServicesFunction.apply(this.client).list().getItems().stream().filter(filter) + .map(s -> s.getMetadata().getName()).collect(Collectors.toList()); } @Override diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java index c6a4b774..6bc15592 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfiguration.java @@ -41,21 +41,18 @@ import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) @ConditionalOnDiscoveryEnabled @ConditionalOnKubernetesEnabled -@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, - CommonsClientAutoConfiguration.class }) +@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) @AutoConfigureAfter({ KubernetesAutoConfiguration.class }) public class KubernetesDiscoveryClientAutoConfiguration { @Bean @ConditionalOnMissingBean - public DefaultIsServicePortSecureResolver isServicePortSecureResolver( - KubernetesDiscoveryProperties properties) { + public DefaultIsServicePortSecureResolver isServicePortSecureResolver(KubernetesDiscoveryProperties properties) { return new DefaultIsServicePortSecureResolver(properties); } @Bean - public KubernetesClientServicesFunction servicesFunction( - KubernetesDiscoveryProperties properties) { + public KubernetesClientServicesFunction servicesFunction(KubernetesDiscoveryProperties properties) { if (properties.getServiceLabels().isEmpty()) { if (properties.isAllNamespaces()) { return (client) -> client.services().inAnyNamespace(); @@ -66,12 +63,10 @@ public class KubernetesDiscoveryClientAutoConfiguration { } else { if (properties.isAllNamespaces()) { - return (client) -> client.services().inAnyNamespace() - .withLabels(properties.getServiceLabels()); + return (client) -> client.services().inAnyNamespace().withLabels(properties.getServiceLabels()); } else { - return (client) -> client.services() - .withLabels(properties.getServiceLabels()); + return (client) -> client.services().withLabels(properties.getServiceLabels()); } } } @@ -82,8 +77,7 @@ public class KubernetesDiscoveryClientAutoConfiguration { } @Bean - public KubernetesRegistration getRegistration(KubernetesClient client, - KubernetesDiscoveryProperties properties) { + public KubernetesRegistration getRegistration(KubernetesClient client, KubernetesDiscoveryProperties properties) { return new KubernetesRegistration(client, properties); } @@ -99,12 +93,12 @@ public class KubernetesDiscoveryClientAutoConfiguration { @Bean @ConditionalOnMissingBean - public KubernetesDiscoveryClient kubernetesDiscoveryClient( - KubernetesClient client, KubernetesDiscoveryProperties properties, + public KubernetesDiscoveryClient kubernetesDiscoveryClient(KubernetesClient client, + KubernetesDiscoveryProperties properties, KubernetesClientServicesFunction kubernetesClientServicesFunction, DefaultIsServicePortSecureResolver isServicePortSecureResolver) { - return new KubernetesDiscoveryClient(client, properties, - kubernetesClientServicesFunction, isServicePortSecureResolver); + return new KubernetesDiscoveryClient(client, properties, kubernetesClientServicesFunction, + isServicePortSecureResolver); } } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java index 16d20225..c3a9044a 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfiguration.java @@ -28,8 +28,7 @@ import org.springframework.context.annotation.Import; */ @Configuration(proxyBeanMethods = false) @ConditionalOnProperty("spring.cloud.config.discovery.enabled") -@Import({ KubernetesAutoConfiguration.class, - KubernetesDiscoveryClientAutoConfiguration.class }) +@Import({ KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class }) public class KubernetesDiscoveryClientConfigClientBootstrapConfiguration { } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryProperties.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryProperties.java index 6d7a2f20..c3d2bf4a 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryProperties.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryProperties.java @@ -148,11 +148,9 @@ public class KubernetesDiscoveryProperties { @Override public String toString() { - return new ToStringCreator(this).append("enabled", this.enabled) - .append("serviceName", this.serviceName).append("filter", this.filter) - .append("knownSecurePorts", this.knownSecurePorts) - .append("serviceLabels", this.serviceLabels) - .append("metadata", this.metadata).toString(); + return new ToStringCreator(this).append("enabled", this.enabled).append("serviceName", this.serviceName) + .append("filter", this.filter).append("knownSecurePorts", this.knownSecurePorts) + .append("serviceLabels", this.serviceLabels).append("metadata", this.metadata).toString(); } /** @@ -247,10 +245,8 @@ public class KubernetesDiscoveryProperties { @Override public String toString() { return new ToStringCreator(this).append("addLabels", this.addLabels) - .append("labelsPrefix", this.labelsPrefix) - .append("addAnnotations", this.addAnnotations) - .append("annotationsPrefix", this.annotationsPrefix) - .append("addPorts", this.addPorts) + .append("labelsPrefix", this.labelsPrefix).append("addAnnotations", this.addAnnotations) + .append("annotationsPrefix", this.annotationsPrefix).append("addPorts", this.addPorts) .append("portsPrefix", this.portsPrefix).toString(); } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstance.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstance.java index 28043269..c48b8316 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstance.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstance.java @@ -63,8 +63,8 @@ public class KubernetesServiceInstance implements ServiceInstance { * @param metadata a map containing metadata. * @param secure indicates whether or not the connection needs to be secure. */ - public KubernetesServiceInstance(String instanceId, String serviceId, String host, - int port, Map metadata, Boolean secure) { + public KubernetesServiceInstance(String instanceId, String serviceId, String host, int port, + Map metadata, Boolean secure) { this.instanceId = instanceId; this.serviceId = serviceId; this.host = host; @@ -115,8 +115,7 @@ public class KubernetesServiceInstance implements ServiceInstance { private URI createUri(String scheme, String host, int port) { StringBuilder sb = new StringBuilder(); - sb.append(scheme).append(COLON).append(DSL).append(host).append(COLON) - .append(port); + sb.append(scheme).append(COLON).append(DSL).append(host).append(COLON).append(port); return URI.create(sb.toString()); } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClient.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClient.java index 039ca1ee..c3f9f8ab 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClient.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClient.java @@ -37,8 +37,7 @@ public class KubernetesReactiveDiscoveryClient implements ReactiveDiscoveryClien private final KubernetesDiscoveryClient kubernetesDiscoveryClient; - public KubernetesReactiveDiscoveryClient(KubernetesClient client, - KubernetesDiscoveryProperties properties, + public KubernetesReactiveDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties properties, KubernetesClientServicesFunction kubernetesClientServicesFunction) { this.kubernetesDiscoveryClient = new KubernetesDiscoveryClient(client, properties, kubernetesClientServicesFunction); @@ -51,18 +50,14 @@ public class KubernetesReactiveDiscoveryClient implements ReactiveDiscoveryClien @Override public Flux getInstances(String serviceId) { - Assert.notNull(serviceId, - "[Assertion failed] - the object argument must not be null"); - return Flux - .defer(() -> Flux - .fromIterable(kubernetesDiscoveryClient.getInstances(serviceId))) + Assert.notNull(serviceId, "[Assertion failed] - the object argument must not be null"); + return Flux.defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getInstances(serviceId))) .subscribeOn(Schedulers.boundedElastic()); } @Override public Flux getServices() { - return Flux - .defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getServices())) + return Flux.defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getServices())) .subscribeOn(Schedulers.boundedElastic()); } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java index 55eba6e4..7546c000 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfiguration.java @@ -56,20 +56,17 @@ public class KubernetesReactiveDiscoveryClientAutoConfiguration { @Bean @ConditionalOnMissingBean - public KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient( - KubernetesClient client, KubernetesDiscoveryProperties properties, + public KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(KubernetesClient client, + KubernetesDiscoveryProperties properties, KubernetesClientServicesFunction kubernetesClientServicesFunction) { - return new KubernetesReactiveDiscoveryClient(client, properties, - kubernetesClientServicesFunction); + return new KubernetesReactiveDiscoveryClient(client, properties, kubernetesClientServicesFunction); } @Bean - @ConditionalOnClass( - name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator") + @ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator") @ConditionalOnDiscoveryHealthIndicatorEnabled public ReactiveDiscoveryClientHealthIndicator kubernetesReactiveDiscoveryClientHealthIndicator( - KubernetesReactiveDiscoveryClient client, - DiscoveryClientHealthIndicatorProperties properties) { + KubernetesReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties) { return new ReactiveDiscoveryClientHealthIndicator(client, properties); } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesAutoServiceRegistration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesAutoServiceRegistration.java index fc89dc75..24388eec 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesAutoServiceRegistration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesAutoServiceRegistration.java @@ -38,11 +38,9 @@ import org.springframework.core.Ordered; */ @Deprecated // TODO Remove this class in 2.x as it is not used or necessary in Kubernetes -public class KubernetesAutoServiceRegistration - implements AutoServiceRegistration, SmartLifecycle, Ordered { +public class KubernetesAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered { - private static final Log log = LogFactory - .getLog(KubernetesAutoServiceRegistration.class); + private static final Log log = LogFactory.getLog(KubernetesAutoServiceRegistration.class); private AtomicBoolean running = new AtomicBoolean(false); @@ -56,8 +54,7 @@ public class KubernetesAutoServiceRegistration private KubernetesRegistration registration; - public KubernetesAutoServiceRegistration(ApplicationContext context, - KubernetesServiceRegistry serviceRegistry, + public KubernetesAutoServiceRegistration(ApplicationContext context, KubernetesServiceRegistry serviceRegistry, KubernetesRegistration registration) { this.context = context; this.serviceRegistry = serviceRegistry; @@ -79,8 +76,7 @@ public class KubernetesAutoServiceRegistration public void start() { this.serviceRegistry.register(this.registration); - this.context.publishEvent( - new InstanceRegisteredEvent<>(this, this.registration.getProperties())); + this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.registration.getProperties())); this.running.set(true); } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesRegistration.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesRegistration.java index ef677725..aef1bb19 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesRegistration.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesRegistration.java @@ -41,8 +41,7 @@ public class KubernetesRegistration implements Registration, Closeable { private AtomicBoolean running = new AtomicBoolean(false); - public KubernetesRegistration(KubernetesClient client, - KubernetesDiscoveryProperties properties) { + public KubernetesRegistration(KubernetesClient client, KubernetesDiscoveryProperties properties) { this.client = client; this.properties = properties; } @@ -94,8 +93,8 @@ public class KubernetesRegistration implements Registration, Closeable { @Override public String toString() { - return "KubernetesRegistration{" + "client=" + this.client + ", properties=" - + this.properties + ", running=" + this.running + '}'; + return "KubernetesRegistration{" + "client=" + this.client + ", properties=" + this.properties + ", running=" + + this.running + '}'; } } diff --git a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesServiceRegistry.java b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesServiceRegistry.java index 1bc5c8aa..d2266953 100644 --- a/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesServiceRegistry.java +++ b/spring-cloud-kubernetes-discovery/src/main/java/org/springframework/cloud/kubernetes/registry/KubernetesServiceRegistry.java @@ -26,8 +26,7 @@ import org.springframework.cloud.client.serviceregistry.ServiceRegistry; * * @author Mauricio Salatino */ -public class KubernetesServiceRegistry - implements ServiceRegistry { +public class KubernetesServiceRegistry implements ServiceRegistry { private static final Log log = LogFactory.getLog(KubernetesServiceRegistry.class); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolverTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolverTest.java index 49e939b8..aa77c28c 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolverTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/DefaultIsServicePortSecureResolverTest.java @@ -29,28 +29,15 @@ public class DefaultIsServicePortSecureResolverTest { final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.getKnownSecurePorts().add(12345); - final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver( - properties); + final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver(properties); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(null, "dummy"))) - .isFalse(); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy"))) - .isFalse(); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy"))) - .isFalse(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(null, "dummy"))).isFalse(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy"))).isFalse(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy"))).isFalse(); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(443, "dummy"))) - .isTrue(); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(8443, "dummy"))) - .isTrue(); - assertThat( - sut.resolve(new DefaultIsServicePortSecureResolver.Input(12345, "dummy"))) - .isTrue(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(443, "dummy"))).isTrue(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8443, "dummy"))).isTrue(); + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(12345, "dummy"))).isTrue(); } @Test @@ -58,22 +45,22 @@ public class DefaultIsServicePortSecureResolverTest { final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver( new KubernetesDiscoveryProperties()); - assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy", - new HashMap() { + assertThat( + sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy", new HashMap() { { put("secured", "true"); put("other", "value"); } }, new HashMap<>()))).isTrue(); - assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy", - new HashMap() { + assertThat( + sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy", new HashMap() { { put("other", "value"); put("secured", "1"); } }, new HashMap<>()))).isTrue(); - assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(4321, "dummy", - new HashMap<>(), new HashMap() { + assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(4321, "dummy", new HashMap<>(), + new HashMap() { { put("other1", "value1"); put("secured", "yes"); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java index 20fa5725..9c86adc4 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogServicesWatchConfigurationTest.java @@ -70,12 +70,9 @@ public class KubernetesCatalogServicesWatchConfigurationTest { } private void setup(String... env) { - this.context = new SpringApplicationBuilder( - PropertyPlaceholderAutoConfiguration.class, - KubernetesClientTestConfiguration.class, - KubernetesCatalogWatchAutoConfiguration.class, - KubernetesDiscoveryClientAutoConfiguration.class) - .web(WebApplicationType.NONE).properties(env).run(); + this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, + KubernetesClientTestConfiguration.class, KubernetesCatalogWatchAutoConfiguration.class, + KubernetesDiscoveryClientAutoConfiguration.class).web(WebApplicationType.NONE).properties(env).run(); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchTest.java index 19075075..b97bad97 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesCatalogWatchTest.java @@ -84,13 +84,10 @@ public class KubernetesCatalogWatchTest { @Test public void testRandomOrderChangePods() throws Exception { when(this.endpointsOperation.list()) - .thenReturn( - createSingleEndpointEndpointListByPodName("api-pod", "other-pod")) - .thenReturn(createSingleEndpointEndpointListByPodName("other-pod", - "api-pod")); + .thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod")) + .thenReturn(createSingleEndpointEndpointListByPodName("other-pod", "api-pod")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); // second execution on shuffleServices @@ -102,13 +99,10 @@ public class KubernetesCatalogWatchTest { @Test public void testRandomOrderChangePodsAllNamespaces() throws Exception { when(this.endpointsOperation.list()) - .thenReturn( - createSingleEndpointEndpointListByPodName("api-pod", "other-pod")) - .thenReturn(createSingleEndpointEndpointListByPodName("other-pod", - "api-pod")); + .thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod")) + .thenReturn(createSingleEndpointEndpointListByPodName("other-pod", "api-pod")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); @@ -122,13 +116,10 @@ public class KubernetesCatalogWatchTest { @Test public void testRandomOrderChangeServices() throws Exception { when(this.endpointsOperation.list()) - .thenReturn( - createEndpointsListByServiceName("api-service", "other-service")) - .thenReturn( - createEndpointsListByServiceName("other-service", "api-service")); + .thenReturn(createEndpointsListByServiceName("api-service", "other-service")) + .thenReturn(createEndpointsListByServiceName("other-service", "api-service")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); // second execution on shuffleServices @@ -140,13 +131,10 @@ public class KubernetesCatalogWatchTest { @Test public void testRandomOrderChangeServicesAllNamespaces() throws Exception { when(this.endpointsOperation.list()) - .thenReturn( - createEndpointsListByServiceName("api-service", "other-service")) - .thenReturn( - createEndpointsListByServiceName("other-service", "api-service")); + .thenReturn(createEndpointsListByServiceName("api-service", "other-service")) + .thenReturn(createEndpointsListByServiceName("other-service", "api-service")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); @@ -159,16 +147,14 @@ public class KubernetesCatalogWatchTest { @Test public void testEventBody() throws Exception { - when(this.endpointsOperation.list()).thenReturn( - createSingleEndpointEndpointListByPodName("api-pod", "other-pod")); + when(this.endpointsOperation.list()) + .thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); - verify(this.applicationEventPublisher) - .publishEvent(this.heartbeatEventArgumentCaptor.capture()); + verify(this.applicationEventPublisher).publishEvent(this.heartbeatEventArgumentCaptor.capture()); HeartbeatEvent event = this.heartbeatEventArgumentCaptor.getValue(); assertThat(event.getValue()).isInstanceOf(List.class); @@ -179,18 +165,16 @@ public class KubernetesCatalogWatchTest { @Test public void testEventBodyAllNamespaces() throws Exception { - when(this.endpointsOperation.list()).thenReturn( - createSingleEndpointEndpointListByPodName("api-pod", "other-pod")); + when(this.endpointsOperation.list()) + .thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod")); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); - verify(this.applicationEventPublisher) - .publishEvent(this.heartbeatEventArgumentCaptor.capture()); + verify(this.applicationEventPublisher).publishEvent(this.heartbeatEventArgumentCaptor.capture()); HeartbeatEvent event = this.heartbeatEventArgumentCaptor.getValue(); assertThat(event.getValue()).isInstanceOf(List.class); @@ -206,8 +190,7 @@ public class KubernetesCatalogWatchTest { when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); // second execution on shuffleServices @@ -223,8 +206,7 @@ public class KubernetesCatalogWatchTest { when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); @@ -243,8 +225,7 @@ public class KubernetesCatalogWatchTest { when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); // second execution on shuffleServices @@ -261,8 +242,7 @@ public class KubernetesCatalogWatchTest { when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); @@ -277,13 +257,11 @@ public class KubernetesCatalogWatchTest { public void testEndpointsWithoutTargetRefs() { EndpointsList endpoints = createSingleEndpointEndpointListByPodName("api-pod"); - endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0) - .setTargetRef(null); + endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0).setTargetRef(null); when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().withLabels(anyMap())) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation); this.underTest.catalogServicesWatch(); // second execution on shuffleServices @@ -296,13 +274,11 @@ public class KubernetesCatalogWatchTest { public void testEndpointsWithoutTargetRefsAllNamespaces() { EndpointsList endpoints = createSingleEndpointEndpointListByPodName("api-pod"); - endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0) - .setTargetRef(null); + endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0).setTargetRef(null); when(this.endpointsOperation.list()).thenReturn(endpoints); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - when(this.kubernetesClient.endpoints().inAnyNamespace()) - .thenReturn(this.endpointsOperation); + when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation); when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap())) .thenReturn(this.endpointsOperation); @@ -314,8 +290,7 @@ public class KubernetesCatalogWatchTest { } private EndpointsList createEndpointsListByServiceName(String... serviceNames) { - List endpoints = stream(serviceNames) - .map(s -> createEndpointsByPodName(s + "-singlePodUniqueId")) + List endpoints = stream(serviceNames).map(s -> createEndpointsByPodName(s + "-singlePodUniqueId")) .collect(Collectors.toList()); EndpointsList endpointsList = new EndpointsList(); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java index c3732d60..b74559be 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationPropertiesTests.java @@ -48,38 +48,31 @@ public class KubernetesDiscoveryClientAutoConfigurationPropertiesTests { public void kubernetesDiscoveryDisabled() throws Exception { setup("spring.cloud.kubernetes.discovery.enabled=false", "spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false"); - assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)) - .isEmpty(); + assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty(); } @Test public void kubernetesDiscoveryWhenKubernetesDisabled() throws Exception { setup("spring.cloud.kubernetes.enabled=false"); - assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)) - .isEmpty(); + assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty(); } @Test public void kubernetesDiscoveryWhenDiscoveryDisabled() throws Exception { setup("spring.cloud.discovery.enabled=false"); - assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)) - .isEmpty(); + assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty(); } @Test public void kubernetesDiscoveryDefaultEnabled() throws Exception { setup("spring.cloud.kubernetes.enabled=true"); - assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)) - .hasSize(1); + assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).hasSize(1); } private void setup(String... env) { - this.context = new SpringApplicationBuilder( - PropertyPlaceholderAutoConfiguration.class, - KubernetesClientTestConfiguration.class, - KubernetesDiscoveryClientAutoConfiguration.class) - .web(org.springframework.boot.WebApplicationType.NONE) - .properties(env).run(); + this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class, + KubernetesClientTestConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class) + .web(org.springframework.boot.WebApplicationType.NONE).properties(env).run(); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java index 1f8a1b3b..1bbb4af5 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientAutoConfigurationTests.java @@ -39,12 +39,11 @@ public class KubernetesDiscoveryClientAutoConfigurationTests { @Test public void kubernetesDiscoveryClientCreated() { - assertThat(this.discoveryClient).isNotNull() - .isInstanceOf(CompositeDiscoveryClient.class); + assertThat(this.discoveryClient).isNotNull().isInstanceOf(CompositeDiscoveryClient.class); CompositeDiscoveryClient composite = (CompositeDiscoveryClient) this.discoveryClient; - assertThat(composite.getDiscoveryClients().stream() - .anyMatch(dc -> dc instanceof KubernetesDiscoveryClient)).isTrue(); + assertThat(composite.getDiscoveryClients().stream().anyMatch(dc -> dc instanceof KubernetesDiscoveryClient)) + .isTrue(); } @SpringBootConfiguration diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java index 61ef0d99..dbf8ce6d 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests.java @@ -60,31 +60,25 @@ public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests { @Test public void onWhenRequested() throws Exception { setup("server.port=7000", "spring.cloud.config.discovery.enabled=true", - "spring.cloud.kubernetes.discovery.enabled:true", - "spring.cloud.kubernetes.enabled:true", "spring.application.name:test", - "spring.cloud.config.discovery.service-id:configserver"); - assertEquals(1, this.context.getParent() - .getBeanNamesForType(DiscoveryClient.class).length); + "spring.cloud.kubernetes.discovery.enabled:true", "spring.cloud.kubernetes.enabled:true", + "spring.application.name:test", "spring.cloud.config.discovery.service-id:configserver"); + assertEquals(1, this.context.getParent().getBeanNamesForType(DiscoveryClient.class).length); DiscoveryClient client = this.context.getParent().getBean(DiscoveryClient.class); verify(client, atLeast(2)).getInstances("configserver"); - ConfigClientProperties locator = this.context - .getBean(ConfigClientProperties.class); + ConfigClientProperties locator = this.context.getBean(ConfigClientProperties.class); assertEquals("http://fake:8888/", locator.getUri()[0]); } private void setup(String... env) { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); TestPropertyValues.of(env).applyTo(parent); - parent.register(UtilAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, EnvironmentKnobbler.class, - KubernetesDiscoveryClientConfigClientBootstrapConfiguration.class, - DiscoveryClientConfigServiceBootstrapConfiguration.class, - ConfigClientProperties.class); + parent.register(UtilAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, + EnvironmentKnobbler.class, KubernetesDiscoveryClientConfigClientBootstrapConfiguration.class, + DiscoveryClientConfigServiceBootstrapConfiguration.class, ConfigClientProperties.class); parent.refresh(); this.context = new AnnotationConfigApplicationContext(); this.context.setParent(parent); - this.context.register(PropertyPlaceholderAutoConfiguration.class, - KubernetesAutoConfiguration.class, + this.context.register(PropertyPlaceholderAutoConfiguration.class, KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class); this.context.refresh(); } @@ -95,10 +89,8 @@ public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests { @Bean public KubernetesDiscoveryClient kubernetesDiscoveryClient() { KubernetesDiscoveryClient client = mock(KubernetesDiscoveryClient.class); - ServiceInstance instance = new DefaultServiceInstance("configserver1", - "configserver", "fake", 8888, false); - given(client.getInstances("configserver")) - .willReturn(Collections.singletonList(instance)); + ServiceInstance instance = new DefaultServiceInstance("configserver1", "configserver", "fake", 8888, false); + given(client.getInstances("configserver")).willReturn(Collections.singletonList(instance)); return client; } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterMetadataTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterMetadataTest.java index c001699b..6f9c7fae 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterMetadataTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterMetadataTest.java @@ -100,21 +100,20 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddAnnotations()).thenReturn(false); when(this.metadata.isAddPorts()).thenReturn(false); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "lab"); - } - }, new HashMap() { - { - put("l1", "lab"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "lab"); + } + }, new HashMap() { + { + put("l1", "lab"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -130,27 +129,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddAnnotations()).thenReturn(false); when(this.metadata.isAddPorts()).thenReturn(false); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - put("l2", "v2"); - } - }, new HashMap() { - { - put("l1", "lab"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + put("l2", "v2"); + } + }, new HashMap() { + { + put("l1", "lab"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("l1", "v1"), - entry("l2", "v2")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("l1", "v1"), entry("l2", "v2")); } @Test @@ -163,27 +160,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddAnnotations()).thenReturn(false); when(this.metadata.isAddPorts()).thenReturn(false); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - put("l2", "v2"); - } - }, new HashMap() { - { - put("l1", "lab"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + put("l2", "v2"); + } + }, new HashMap() { + { + put("l1", "lab"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_l1", "v1"), - entry("l_l2", "v2")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_l1", "v1"), entry("l_l2", "v2")); } @Test @@ -195,27 +190,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddAnnotations()).thenReturn(true); when(this.metadata.isAddPorts()).thenReturn(false); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - } - }, new HashMap() { - { - put("a1", "v1"); - put("a2", "v2"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + } + }, new HashMap() { + { + put("a1", "v1"); + put("a2", "v2"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("a1", "v1"), - entry("a2", "v2")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("a1", "v1"), entry("a2", "v2")); } @Test @@ -228,27 +221,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.getAnnotationsPrefix()).thenReturn("a_"); when(this.metadata.isAddPorts()).thenReturn(false); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - } - }, new HashMap() { - { - put("a1", "v1"); - put("a2", "v2"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + } + }, new HashMap() { + { + put("a1", "v1"); + put("a2", "v2"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "v1"), - entry("a_a2", "v2")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "v1"), entry("a_a2", "v2")); } @Test @@ -260,22 +251,21 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddAnnotations()).thenReturn(false); when(this.metadata.isAddPorts()).thenReturn(true); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - } - }, new HashMap() { - { - put("a1", "v1"); - put("a2", "v2"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + } + }, new HashMap() { + { + put("a1", "v1"); + put("a2", "v2"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -292,22 +282,21 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddPorts()).thenReturn(true); when(this.metadata.getPortsPrefix()).thenReturn("p_"); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "v1"); - } - }, new HashMap() { - { - put("a1", "v1"); - put("a2", "v2"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "v1"); + } + }, new HashMap() { + { + put("a1", "v1"); + put("a2", "v2"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); @@ -326,58 +315,51 @@ public class KubernetesDiscoveryClientFilterMetadataTest { when(this.metadata.isAddPorts()).thenReturn(true); when(this.metadata.getPortsPrefix()).thenReturn("p_"); - setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", - new HashMap() { - { - put("l1", "la1"); - } - }, new HashMap() { - { - put("a1", "an1"); - put("a2", "an2"); - } - }, new HashMap() { - { - put(80, "http"); - put(5555, ""); - } - }); + setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap() { + { + put("l1", "la1"); + } + }, new HashMap() { + { + put("a1", "an1"); + put("a2", "an2"); + } + }, new HashMap() { + { + put(80, "http"); + put(5555, ""); + } + }); final List instances = this.underTest.getInstances(serviceId); assertThat(instances).hasSize(1); - assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"), - entry("a_a2", "an2"), entry("l_l1", "la1"), entry("p_http", "80")); + assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"), entry("a_a2", "an2"), + entry("l_l1", "la1"), entry("p_http", "80")); } - private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, - String namespace, Map labels, Map annotations, - Map ports) { - final Service service = new ServiceBuilder().withNewMetadata() - .withNamespace(namespace).withLabels(labels).withAnnotations(annotations) - .endMetadata().withNewSpec().withPorts(getServicePorts(ports)).endSpec() + private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, String namespace, + Map labels, Map annotations, Map ports) { + final Service service = new ServiceBuilder().withNewMetadata().withNamespace(namespace).withLabels(labels) + .withAnnotations(annotations).endMetadata().withNewSpec().withPorts(getServicePorts(ports)).endSpec() .build(); when(this.serviceOperation.withName(serviceId)).thenReturn(this.serviceResource); when(this.serviceResource.get()).thenReturn(service); when(this.kubernetesClient.services()).thenReturn(this.serviceOperation); - when(this.kubernetesClient.services().inNamespace(anyString())) - .thenReturn(this.serviceOperation); + when(this.kubernetesClient.services().inNamespace(anyString())).thenReturn(this.serviceOperation); ObjectMeta objectMeta = new ObjectMeta(); objectMeta.setNamespace(namespace); - final Endpoints endpoints = new EndpointsBuilder().withMetadata(objectMeta) - .addNewSubset().addAllToPorts(getEndpointPorts(ports)).addNewAddress() - .endAddress().endSubset().build(); + final Endpoints endpoints = new EndpointsBuilder().withMetadata(objectMeta).addNewSubset() + .addAllToPorts(getEndpointPorts(ports)).addNewAddress().endAddress().endSubset().build(); when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation); - EndpointsList endpointsList = new EndpointsList(null, - Collections.singletonList(endpoints), null, null); + EndpointsList endpointsList = new EndpointsList(null, Collections.singletonList(endpoints), null, null); when(filter.list()).thenReturn(endpointsList); when(filter.withLabels(anyMap())).thenReturn(filter); - when(this.kubernetesClient.endpoints().withField(eq("metadata.name"), - eq(serviceId))).thenReturn(filter); + when(this.kubernetesClient.endpoints().withField(eq("metadata.name"), eq(serviceId))).thenReturn(filter); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterTest.java index 7f4e80c9..a2870d95 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientFilterTest.java @@ -54,8 +54,8 @@ public class KubernetesDiscoveryClientFilterTest { @Before public void setUp() { - this.underTest = new KubernetesDiscoveryClient(this.kubernetesClient, - this.properties, this.kubernetesClientServicesFunction); + this.underTest = new KubernetesDiscoveryClient(this.kubernetesClient, this.properties, + this.kubernetesClientServicesFunction); } @Test @@ -75,8 +75,7 @@ public class KubernetesDiscoveryClientFilterTest { when(this.serviceOperation.list()).thenReturn(serviceList); when(this.kubernetesClient.services()).thenReturn(this.serviceOperation); - when(this.properties.getFilter()) - .thenReturn("metadata.additionalProperties['spring-boot']"); + when(this.properties.getFilter()).thenReturn("metadata.additionalProperties['spring-boot']"); List filteredServices = this.underTest.getServices(); @@ -87,8 +86,7 @@ public class KubernetesDiscoveryClientFilterTest { @Test public void testFilteredServicesByPrefix() { - List springBootServiceNames = Arrays.asList("serviceA", "serviceB", - "serviceC"); + List springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC"); List services = createSpringBootServiceByName(springBootServiceNames); // Add non spring boot service @@ -103,8 +101,7 @@ public class KubernetesDiscoveryClientFilterTest { when(this.serviceOperation.list()).thenReturn(serviceList); when(this.kubernetesClient.services()).thenReturn(this.serviceOperation); - when(this.properties.getFilter()) - .thenReturn("metadata.name.startsWith('service')"); + when(this.properties.getFilter()).thenReturn("metadata.name.startsWith('service')"); List filteredServices = this.underTest.getServices(); @@ -115,8 +112,7 @@ public class KubernetesDiscoveryClientFilterTest { @Test public void testNoExpression() { - List springBootServiceNames = Arrays.asList("serviceA", "serviceB", - "serviceC"); + List springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC"); List services = createSpringBootServiceByName(springBootServiceNames); ServiceList serviceList = new ServiceList(); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTest.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTest.java index a70aa292..f3032795 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTest.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesDiscoveryClientTest.java @@ -52,12 +52,10 @@ public class KubernetesDiscoveryClientTest { mockClient = mockServer.getClient(); // 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @@ -66,11 +64,10 @@ public class KubernetesDiscoveryClientTest { Map labels = new HashMap(); labels.put("l", "v"); - Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("10") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef() + .withUid("10").endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset() + .build(); List endpointsList = new ArrayList<>(); endpointsList.add(endPoint); @@ -78,37 +75,34 @@ public class KubernetesDiscoveryClientTest { EndpointsList endpoints = new EndpointsList(); endpoints.setItems(endpointsList); - mockServer.expect().get().withPath( - "/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint") - .andReturn(200, endpoints).once(); - mockServer.expect().get() - .withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint") + .withPath( + "/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - mockServer.expect().get().withPath( - "/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - Service service = new ServiceBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).endMetadata().build(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") + .andReturn(200, endpoints).once(); - mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint") - .andReturn(200, service).always(); + Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().build(); + + mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service) + .always(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setServiceLabels(labels); properties.getMetadata().setAddLabels(false); properties.getMetadata().setAddAnnotations(false); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); final List instances = discoveryClient.getInstances("endpoint"); - assertThat(instances).hasSize(1) - .filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) .filteredOn(s -> s.getInstanceId().equals("10")).hasSize(1); } @@ -117,11 +111,9 @@ public class KubernetesDiscoveryClientTest { Map labels = new HashMap(); labels.put("l2", "v2"); - Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").withLabels(labels) - .endMetadata().addNewSubset().addNewAddress().withIp("ip1") - .withNewTargetRef().withUid("20").endTargetRef().endAddress() - .addNewPort("mgmt", "mgmt_tcp", 900, "TCP") + Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef() + .withUid("20").endTargetRef().endAddress().addNewPort("mgmt", "mgmt_tcp", 900, "TCP") .addNewPort("http", "http_tcp", 80, "TCP").endSubset().build(); List endpointsList = new ArrayList<>(); @@ -134,30 +126,26 @@ public class KubernetesDiscoveryClientTest { "/api/v1/namespaces/test/endpoints?labelSelector=l2%3Dv2&fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - mockServer.expect().get().withPath( - "/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - Service service = new ServiceBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).withAnnotations(labels) - .endMetadata().build(); + Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).withAnnotations(labels).endMetadata().build(); - mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint") - .andReturn(200, service).always(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service) + .always(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setPrimaryPortName("http_tcp"); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); final List instances = discoveryClient.getInstances("endpoint"); - assertThat(instances).hasSize(1) - .filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) - .filteredOn(s -> s.getInstanceId().equals("20")).hasSize(1) - .filteredOn(s -> 80 == s.getPort()).hasSize(1); + assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1) + .filteredOn(s -> s.getInstanceId().equals("20")).hasSize(1).filteredOn(s -> 80 == s.getPort()) + .hasSize(1); } @Test @@ -165,11 +153,10 @@ public class KubernetesDiscoveryClientTest { Map labels = new HashMap(); labels.put("l", "v"); - Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("30") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef() + .withUid("30").endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset() + .build(); List endpointsList = new ArrayList<>(); endpointsList.add(endPoint); @@ -177,19 +164,18 @@ public class KubernetesDiscoveryClientTest { EndpointsList endpoints = new EndpointsList(); endpoints.setItems(endpointsList); - mockServer.expect().get().withPath( - "/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get() + .withPath( + "/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setServiceLabels(labels); - final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient( - mockClient, properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); - final List result_endpoints = discoveryClient - .getEndPointsList("endpoint"); + final List result_endpoints = discoveryClient.getEndPointsList("endpoint"); assertThat(result_endpoints).hasSize(1); } @@ -199,12 +185,11 @@ public class KubernetesDiscoveryClientTest { Map labels = new HashMap(); labels.put("l1", "v1"); - Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("40") - .endTargetRef().endAddress().addNewAddress().withIp("ip2") - .withNewTargetRef().withUid("50").endTargetRef().endAddress() - .addNewPort("https", "https_tcp", 443, "TCP").endSubset().build(); + Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef() + .withUid("40").endTargetRef().endAddress().addNewAddress().withIp("ip2").withNewTargetRef() + .withUid("50").endTargetRef().endAddress().addNewPort("https", "https_tcp", 443, "TCP").endSubset() + .build(); List endpointsList = new ArrayList<>(); endpointsList.add(endPoint); @@ -216,53 +201,48 @@ public class KubernetesDiscoveryClientTest { "/api/v1/namespaces/test/endpoints?labelSelector=l1%3Dv1&fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - mockServer.expect().get().withPath( - "/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - Service service = new ServiceBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(labels).endMetadata().build(); + Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(labels).endMetadata().build(); - mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint") - .andReturn(200, service).always(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service) + .always(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setServiceLabels(labels); properties.getMetadata().setAddAnnotations(false); properties.getMetadata().setAddLabels(false); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); final List instances = discoveryClient.getInstances("endpoint"); - assertThat(instances).hasSize(2).filteredOn(ServiceInstance::isSecure) - .extracting(ServiceInstance::getHost).containsOnly("ip1", "ip2"); + assertThat(instances).hasSize(2).filteredOn(ServiceInstance::isSecure).extracting(ServiceInstance::getHost) + .containsOnly("ip1", "ip2"); } @Test public void getServicesShouldReturnAllServicesWhenNoLabelsAreAppliedToTheClient() { - mockServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("s1").withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().addNewItem().withNewMetadata() - .withName("s2").withLabels(new HashMap() { - { - put("label", "value"); - put("label2", "value2"); - } - }).endMetadata().endItem().addNewItem().withNewMetadata() - .withName("s3").endMetadata().endItem().build()) - .once(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/services").andReturn(200, new ServiceListBuilder() + .addNewItem().withNewMetadata().withName("s1").withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().addNewItem().withNewMetadata().withName("s2") + .withLabels(new HashMap() { + { + put("label", "value"); + put("label2", "value2"); + } + }).endMetadata().endItem().addNewItem().withNewMetadata().withName("s3").endMetadata().endItem() + .build()).once(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); final List services = discoveryClient.getServices(); @@ -271,15 +251,14 @@ public class KubernetesDiscoveryClientTest { @Test public void getServicesShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient() { - mockServer.expect().get() - .withPath("/api/v1/namespaces/test/services?labelSelector=label%3Dvalue") - .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("s1").withLabels(new HashMap() { + mockServer.expect().get().withPath("/api/v1/namespaces/test/services?labelSelector=label%3Dvalue") + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("s1") + .withLabels(new HashMap() { { put("label", "value"); } - }).endMetadata().endItem().addNewItem().withNewMetadata() - .withName("s2").withLabels(new HashMap() { + }).endMetadata().endItem().addNewItem().withNewMetadata().withName("s2") + .withLabels(new HashMap() { { put("label", "value"); put("label2", "value2"); @@ -288,8 +267,7 @@ public class KubernetesDiscoveryClientTest { .once(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, client -> client.services().withLabels(new HashMap() { { put("label", "value"); @@ -303,17 +281,13 @@ public class KubernetesDiscoveryClientTest { @Test public void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() { - Endpoints endPoints1 = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("60") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endPoints1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("60") + .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build(); - Endpoints endpoints2 = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test2").endMetadata().addNewSubset() - .addNewAddress().withIp("ip2").withNewTargetRef().withUid("70") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endpoints2 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test2") + .endMetadata().addNewSubset().addNewAddress().withIp("ip2").withNewTargetRef().withUid("70") + .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build(); List endpointsList = new ArrayList<>(); endpointsList.add(endPoints1); @@ -322,25 +296,24 @@ public class KubernetesDiscoveryClientTest { EndpointsList endpoints = new EndpointsList(); endpoints.setItems(endpointsList); - mockServer.expect().get() - .withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint") .andReturn(200, endpoints).once(); - mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint") - .andReturn(200, endPoints1).once(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint").andReturn(200, endPoints1) + .once(); - mockServer.expect().get().withPath("/api/v1/namespaces/test2/endpoints/endpoint") - .andReturn(200, endpoints2).once(); + mockServer.expect().get().withPath("/api/v1/namespaces/test2/endpoints/endpoint").andReturn(200, endpoints2) + .once(); - Service service1 = new ServiceBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test").withLabels(new HashMap() { + Service service1 = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .withLabels(new HashMap() { { put("l", "v"); } }).endMetadata().build(); - Service service2 = new ServiceBuilder().withNewMetadata().withName("endpoint") - .withNamespace("test2").withLabels(new HashMap() { + Service service2 = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test2") + .withLabels(new HashMap() { { put("l", "v"); } @@ -353,38 +326,30 @@ public class KubernetesDiscoveryClientTest { ServiceList services = new ServiceList(); services.setItems(servicesList); - mockServer.expect().get() - .withPath("/api/v1/services?fieldSelector=metadata.name%3Dendpoint") + mockServer.expect().get().withPath("/api/v1/services?fieldSelector=metadata.name%3Dendpoint") .andReturn(200, services).once(); - mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint") - .andReturn(200, service1).always(); + mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service1) + .always(); - mockServer.expect().get().withPath("/api/v1/namespaces/test2/services/endpoint") - .andReturn(200, service2).always(); + mockServer.expect().get().withPath("/api/v1/namespaces/test2/services/endpoint").andReturn(200, service2) + .always(); final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setAllNamespaces(true); - final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, - properties, KubernetesClient::services, - new DefaultIsServicePortSecureResolver(properties)); + final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties, + KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties)); final List instances = discoveryClient.getInstances("endpoint"); assertThat(instances).hasSize(2); - assertThat(instances).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()) - .hasSize(1); - assertThat(instances).filteredOn(s -> s.getHost().equals("ip2") && !s.isSecure()) - .hasSize(1); - assertThat(instances) - .filteredOn(s -> s.getServiceId().contains("endpoint") - && ((KubernetesServiceInstance) s).getNamespace().equals("test")) - .hasSize(1); - assertThat(instances) - .filteredOn(s -> s.getServiceId().contains("endpoint") - && ((KubernetesServiceInstance) s).getNamespace().equals("test2")) - .hasSize(1); + assertThat(instances).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1); + assertThat(instances).filteredOn(s -> s.getHost().equals("ip2") && !s.isSecure()).hasSize(1); + assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint") + && ((KubernetesServiceInstance) s).getNamespace().equals("test")).hasSize(1); + assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint") + && ((KubernetesServiceInstance) s).getNamespace().equals("test2")).hasSize(1); assertThat(instances).filteredOn(s -> s.getInstanceId().equals("60")).hasSize(1); assertThat(instances).filteredOn(s -> s.getInstanceId().equals("70")).hasSize(1); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstanceTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstanceTests.java index 8cf648c6..94737610 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstanceTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/KubernetesServiceInstanceTests.java @@ -36,9 +36,8 @@ public class KubernetesServiceInstanceTests { address.setIp("1.2.3.4"); EndpointPort port = new EndpointPort(); port.setPort(8080); - KubernetesServiceInstance instance = new KubernetesServiceInstance("123", - "myservice", address.getIp(), port.getPort(), Collections.emptyMap(), - secure); + KubernetesServiceInstance instance = new KubernetesServiceInstance("123", "myservice", address.getIp(), + port.getPort(), Collections.emptyMap(), secure); assertThat(instance.getInstanceId()).isEqualTo("123"); assertThat(instance.getServiceId()).isEqualTo("myservice"); diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfigurationTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfigurationTests.java index 9a2c7e62..338bc737 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientAutoConfigurationTests.java @@ -35,93 +35,69 @@ import static org.assertj.core.api.Assertions.assertThat; */ class KubernetesReactiveDiscoveryClientAutoConfigurationTests { - private ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class, - ReactiveCommonsClientAutoConfiguration.class, - KubernetesAutoConfiguration.class, - KubernetesDiscoveryClientAutoConfiguration.class, + private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( + AutoConfigurations.of(UtilAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class, + KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class, KubernetesReactiveDiscoveryClientAutoConfiguration.class)); @Test public void shouldWorkWithDefaults() { contextRunner.run(context -> { assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class); - assertThat(context) - .hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class); + assertThat(context).hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class); }); } @Test public void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() { - contextRunner.withPropertyValues("spring.cloud.discovery.enabled=false") - .run(context -> { - assertThat(context) - .doesNotHaveBean("kubernetesReactiveDiscoveryClient"); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withPropertyValues("spring.cloud.discovery.enabled=false").run(context -> { + assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient"); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } @Test public void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() { - contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false") - .run(context -> { - assertThat(context) - .doesNotHaveBean("kubernetesReactiveDiscoveryClient"); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false").run(context -> { + assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient"); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } @Test public void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() { - contextRunner.withPropertyValues("spring.cloud.kubernetes.enabled=false") - .run(context -> { - assertThat(context) - .doesNotHaveBean("kubernetesReactiveDiscoveryClient"); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withPropertyValues("spring.cloud.kubernetes.enabled=false").run(context -> { + assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient"); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } @Test public void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() { - contextRunner - .withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false") - .run(context -> { - assertThat(context) - .doesNotHaveBean("kubernetesReactiveDiscoveryClient"); - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false").run(context -> { + assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient"); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } @Test public void worksWithoutWebflux() { - contextRunner - .withClassLoader( - new FilteredClassLoader("org.springframework.web.reactive")) - .run(context -> { - assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.web.reactive")).run(context -> { + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } @Test public void worksWithoutActuator() { - contextRunner - .withClassLoader( - new FilteredClassLoader("org.springframework.boot.actuate")) - .run(context -> { - assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class); - assertThat(context).doesNotHaveBean( - ReactiveDiscoveryClientHealthIndicator.class); - }); + contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.boot.actuate")).run(context -> { + assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class); + assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class); + }); } } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientTests.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientTests.java index 6c89ba81..80f45d12 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientTests.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/reactive/KubernetesReactiveDiscoveryClientTests.java @@ -56,18 +56,16 @@ class KubernetesReactiveDiscoveryClientTests { kubernetesClient.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); } @Test public void verifyDefaults(@Client KubernetesClient kubernetesClient) { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); - assertThat(client.description()) - .isEqualTo("Kubernetes Reactive Discovery Client"); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); + assertThat(client.description()).isEqualTo("Kubernetes Reactive Discovery Client"); assertThat(client.getOrder()).isEqualTo(ReactiveDiscoveryClient.DEFAULT_ORDER); } @@ -75,165 +73,141 @@ class KubernetesReactiveDiscoveryClientTests { public void shouldReturnFluxOfServices(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("s1").withLabels(new HashMap() { + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("s1") + .withLabels(new HashMap() { { put("label", "value"); } - }).endMetadata().endItem().addNewItem().withNewMetadata() - .withName("s2").withLabels(new HashMap() { + }).endMetadata().endItem().addNewItem().withNewMetadata().withName("s2") + .withLabels(new HashMap() { { put("label", "value"); put("label2", "value2"); } - }).endMetadata().endItem().addNewItem().withNewMetadata() - .withName("s3").endMetadata().endItem().build()) + }).endMetadata().endItem().addNewItem().withNewMetadata().withName("s3").endMetadata().endItem() + .build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux services = client.getServices(); - StepVerifier.create(services).expectNext("s1", "s2", "s3").expectComplete() - .verify(); + StepVerifier.create(services).expectNext("s1", "s2", "s3").expectComplete().verify(); } @Test - public void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound( - @Client KubernetesClient kubernetesClient, + public void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") .andReturn(200, new ServiceListBuilder().build()).once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux services = client.getServices(); StepVerifier.create(services).expectNextCount(0).expectComplete().verify(); } @Test @Disabled // see gh-603 - public void shouldReturnEmptyFluxForNonExistingService( - @Client KubernetesClient kubernetesClient) { + public void shouldReturnEmptyFluxForNonExistingService(@Client KubernetesClient kubernetesClient) { KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("nonexistent-service"); StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); } @Test @Disabled // see gh-603 - public void shouldReturnEmptyFluxWhenServiceHasNoSubsets( - @Client KubernetesClient kubernetesClient, + public void shouldReturnEmptyFluxWhenServiceHasNoSubsets(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().build()) + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("existing-service"); StepVerifier.create(instances).expectNextCount(0).expectComplete().verify(); } @Test @Disabled // see gh-603 - public void shouldReturnFlux(@Client KubernetesClient kubernetesClient, - @Server KubernetesServer kubernetesServer) { + public void shouldReturnFlux(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().build()) + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().build()) .once(); - Endpoints endPoints = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") + .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/endpoints/existing-service") + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service") .andReturn(200, endPoints).once(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().build()) + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service") + .andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("existing-service"); StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); } @Test @Disabled // see gh-603 - public void shouldReturnFluxWithPrefixedMetadata( - @Client KubernetesClient kubernetesClient, + public void shouldReturnFluxWithPrefixedMetadata(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().build()) + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().build()) .once(); - Endpoints endPoints = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") - .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") - .endSubset().build(); + Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") + .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/endpoints/existing-service") + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service") .andReturn(200, endPoints).once(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().build()) + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service") + .andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.getMetadata().setAnnotationsPrefix("annotation."); properties.getMetadata().setLabelsPrefix("label."); properties.getMetadata().setPortsPrefix("port."); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("existing-service"); StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); } @@ -241,93 +215,77 @@ class KubernetesReactiveDiscoveryClientTests { @Test @Disabled // see gh-603 public void shouldReturnFluxWhenServiceHasMultiplePortsAndPrimaryPortNameIsSet( - @Client KubernetesClient kubernetesClient, - @Server KubernetesServer kubernetesServer) { + @Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().build()) + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().build()) .once(); - Endpoints endPoints = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") + Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") .addNewPort("https", "https_tcp", 443, "TCP").endSubset().build(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/endpoints/existing-service") + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service") .andReturn(200, endPoints).once(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().build()) + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service") + .andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setPrimaryPortName("https"); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("existing-service"); StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); } @Test - public void shouldReturnFluxOfServicesAcrossAllNamespaces( - @Client KubernetesClient kubernetesClient, + public void shouldReturnFluxOfServicesAcrossAllNamespaces(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) { kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services") - .andReturn(200, - new ServiceListBuilder().addNewItem().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().endItem().build()) + .andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().endItem().build()) .once(); - Endpoints endpoints = new EndpointsBuilder().withNewMetadata() - .withName("endpoint").withNamespace("test").endMetadata().addNewSubset() - .addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") + Endpoints endpoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test") + .endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1") .endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP") .addNewPort("https", "https_tcp", 443, "TCP").endSubset().build(); EndpointsList endpointsList = new EndpointsList(); endpointsList.setItems(singletonList(endpoints)); - kubernetesServer.expect().get().withPath( - "/api/v1/endpoints?fieldSelector=metadata.name%3Dexisting-service") + kubernetesServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dexisting-service") .andReturn(200, endpointsList).once(); - kubernetesServer.expect().get() - .withPath("/api/v1/namespaces/test/services/existing-service") - .andReturn(200, - new ServiceBuilder().withNewMetadata() - .withName("existing-service") - .withLabels(new HashMap() { - { - put("label", "value"); - } - }).endMetadata().build()) + kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service") + .andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service") + .withLabels(new HashMap() { + { + put("label", "value"); + } + }).endMetadata().build()) .once(); KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(); properties.setAllNamespaces(true); - ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient( - kubernetesClient, properties, KubernetesClient::services); + ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties, + KubernetesClient::services); Flux instances = client.getInstances("existing-service"); StepVerifier.create(instances).expectNextCount(1).expectComplete().verify(); } diff --git a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/support/KubernetesExtension.java b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/support/KubernetesExtension.java index 4ef954be..e03d31da 100644 --- a/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/support/KubernetesExtension.java +++ b/spring-cloud-kubernetes-discovery/src/test/java/org/springframework/cloud/kubernetes/discovery/support/KubernetesExtension.java @@ -33,20 +33,16 @@ import org.junit.jupiter.api.extension.ParameterResolver; /** * @author Tim Ysewyn */ -public class KubernetesExtension - implements ParameterResolver, BeforeEachCallback, AfterEachCallback { +public class KubernetesExtension implements ParameterResolver, BeforeEachCallback, AfterEachCallback { private final KubernetesServer mockServer = new KubernetesServer(); @Override - public boolean supportsParameter(ParameterContext parameterContext, - ExtensionContext context) { + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext context) { return (parameterContext.getParameter().isAnnotationPresent(Server.class) - && KubernetesServer.class - .isAssignableFrom(parameterContext.getParameter().getType())) + && KubernetesServer.class.isAssignableFrom(parameterContext.getParameter().getType())) || (parameterContext.getParameter().isAnnotationPresent(Client.class) - && KubernetesClient.class.isAssignableFrom( - parameterContext.getParameter().getType())); + && KubernetesClient.class.isAssignableFrom(parameterContext.getParameter().getType())); } @Override @@ -60,8 +56,8 @@ public class KubernetesExtension } @Override - public Object resolveParameter(ParameterContext parameterContext, - ExtensionContext extensionContext) throws ParameterResolutionException { + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { if (parameterContext.getParameter().isAnnotationPresent(Client.class)) { return mockServer.getClient(); } diff --git a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/main/java/org/springframework/cloud/kubernetes/examples/LeaderController.java b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/main/java/org/springframework/cloud/kubernetes/examples/LeaderController.java index 267ae488..39b142ac 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/main/java/org/springframework/cloud/kubernetes/examples/LeaderController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/main/java/org/springframework/cloud/kubernetes/examples/LeaderController.java @@ -50,12 +50,10 @@ public class LeaderController { @GetMapping public String getInfo() { if (this.context == null) { - return String.format("I am '%s' but I am not a leader of the '%s'", this.host, - this.role); + return String.format("I am '%s' but I am not a leader of the '%s'", this.host, this.role); } - return String.format("I am '%s' and I am the leader of the '%s'", this.host, - this.role); + return String.format("I am '%s' and I am the leader of the '%s'", this.host, this.role); } /** @@ -68,8 +66,7 @@ public class LeaderController { @PutMapping public ResponseEntity revokeLeadership() { if (this.context == null) { - String message = String.format( - "Cannot revoke leadership because '%s' is not a leader", this.host); + String message = String.format("Cannot revoke leadership because '%s' is not a leader", this.host); return ResponseEntity.badRequest().body(message); } diff --git a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/test/java/org/springframework/cloud/kubernetes/examples/LeaderControllerTest.java b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/test/java/org/springframework/cloud/kubernetes/examples/LeaderControllerTest.java index 686cbcf2..63ed3143 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/test/java/org/springframework/cloud/kubernetes/examples/LeaderControllerTest.java +++ b/spring-cloud-kubernetes-examples/kubernetes-leader-election-example/src/test/java/org/springframework/cloud/kubernetes/examples/LeaderControllerTest.java @@ -60,8 +60,7 @@ public class LeaderControllerTest { @Test public void shouldGetNonLeaderInfo() { - String message = String.format("I am '%s' but I am not a leader of the 'null'", - this.host); + String message = String.format("I am '%s' but I am not a leader of the 'null'", this.host); assertThat(this.leaderController.getInfo()).isEqualTo(message); } @@ -71,8 +70,7 @@ public class LeaderControllerTest { this.leaderController.handleEvent(this.mockOnGrantedEvent); - String message = String.format("I am '%s' and I am the leader of the 'null'", - this.host); + String message = String.format("I am '%s' and I am the leader of the 'null'", this.host); assertThat(this.leaderController.getInfo()).isEqualTo(message); } @@ -83,8 +81,7 @@ public class LeaderControllerTest { this.leaderController.handleEvent(this.mockOnGrantedEvent); this.leaderController.handleEvent(this.mockOnRevokedEvent); - String message = String.format("I am '%s' but I am not a leader of the 'null'", - this.host); + String message = String.format("I am '%s' but I am not a leader of the 'null'", this.host); assertThat(this.leaderController.getInfo()).isEqualTo(message); } @@ -105,8 +102,7 @@ public class LeaderControllerTest { public void shouldNotRevokeLeadershipIfNotLeader() { ResponseEntity responseEntity = this.leaderController.revokeLeadership(); - String message = String.format( - "Cannot revoke leadership because '%s' is not a leader", this.host); + String message = String.format("Cannot revoke leadership because '%s' is not a leader", this.host); assertThat(responseEntity.getBody()).isEqualTo(message); assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); verify(this.mockContext, times(0)).yield(); diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java index 4ec2844f..b3f13ae3 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/GreetingController.java @@ -50,10 +50,8 @@ public class GreetingController { * @return Greeting string. */ @GetMapping("/greeting") - public Mono getGreeting( - @RequestParam(value = "delay", defaultValue = "0") int delay) { - return nameService.getName(delay) - .map(name -> String.format("Hello from %s!", name)); + public Mono getGreeting(@RequestParam(value = "delay", defaultValue = "0") int delay) { + return nameService.getName(delay).map(name -> String.format("Hello from %s!", name)); } } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java index 7d479e32..333b1e38 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/greeting-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameService.java @@ -37,8 +37,7 @@ public class NameService { } public Mono getName(int delay) { - return webClient.get() - .uri(String.format("http://name-service/name?delay=%d", delay)).retrieve() + return webClient.get().uri(String.format("http://name-service/name?delay=%d", delay)).retrieve() .bodyToMono(String.class); } diff --git a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java index cad79b6a..a0887a2b 100644 --- a/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java +++ b/spring-cloud-kubernetes-examples/kubernetes-loadbalancer-example/name-service/src/main/java/org/springframework/cloud/kubernetes/examples/NameController.java @@ -50,10 +50,8 @@ public class NameController { * @return Host name. */ @GetMapping("/name") - public Mono getName( - @RequestParam(value = "delay", defaultValue = "0") int delayValue) { - LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName, - delayValue)); + public Mono getName(@RequestParam(value = "delay", defaultValue = "0") int delayValue) { + LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName, delayValue)); delay(delayValue); return Mono.just(hostName); } diff --git a/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java b/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java index 2523c081..a30ca00b 100644 --- a/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java +++ b/spring-cloud-kubernetes-integration-tests/discovery/tests/src/test/java/org/springframework/cloud/kubernetes/it/ServicesIT.java @@ -32,16 +32,15 @@ public class ServicesIT { private static final String HOST = System.getProperty("service.host"); - private static final Integer PORT = Integer - .valueOf(System.getProperty("service.port")); + private static final Integer PORT = Integer.valueOf(System.getProperty("service.port")); - private static final String PROTOCOL = "true" - .equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http"; + private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https" + : "http"; @Test public void testServicesEndpoint() { - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services") - .then().statusCode(200).body(new StringContains(false, "service-a") { + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services").then().statusCode(200) + .body(new StringContains(false, "service-a") { @Override protected boolean evalSubstringOf(String s) { return s.contains("service-a") && s.contains("service-b"); @@ -51,9 +50,8 @@ public class ServicesIT { @Test public void testInstancesEndpoint() { - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)) - .get("services/discovery-service-a/instances").then().statusCode(200) - .body("instanceId", hasSize(1)) + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services/discovery-service-a/instances") + .then().statusCode(200).body("instanceId", hasSize(1)) .body("serviceId", hasItems("discovery-service-a")); } diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerAllNamespacesTests.java b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerAllNamespacesTests.java index 29e87c79..8b7bd7fe 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerAllNamespacesTests.java +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerAllNamespacesTests.java @@ -46,12 +46,10 @@ class LoadBalancerAllNamespacesTests { @BeforeAll static void setup() { - System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, - client.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); } @@ -59,23 +57,21 @@ class LoadBalancerAllNamespacesTests { @Test void testLoadBalancerDifferentNamespace() { createTestData("service-b", "b"); - String response = restTemplate.getForObject("http://service-b/greeting", - String.class); + String response = restTemplate.getForObject("http://service-b/greeting", String.class); Assertions.assertNotNull(response); Assertions.assertEquals("greeting", response); } private void createTestData(String name, String namespace) { - client.services().inNamespace(namespace).createNew().withNewMetadata() - .withName(name).withNamespace(namespace).endMetadata() - .withSpec(new ServiceSpecBuilder().withPorts(new ServicePortBuilder() - .withProtocol("TCP").withPort(randomServerPort).build()).build()) + client.services().inNamespace(namespace).createNew().withNewMetadata().withName(name).withNamespace(namespace) + .endMetadata() + .withSpec(new ServiceSpecBuilder() + .withPorts(new ServicePortBuilder().withProtocol("TCP").withPort(randomServerPort).build()) + .build()) .done(); - client.endpoints().inNamespace(namespace).createNew().withNewMetadata() - .withName("service-a").withNamespace(namespace).endMetadata() - .addNewSubset().addNewAddress().withIp("localhost").endAddress() - .addNewPort().withName("http").withPort(randomServerPort).endPort() - .endSubset().done(); + client.endpoints().inNamespace(namespace).createNew().withNewMetadata().withName("service-a") + .withNamespace(namespace).endMetadata().addNewSubset().addNewAddress().withIp("localhost").endAddress() + .addNewPort().withName("http").withPort(randomServerPort).endPort().endSubset().done(); } } diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerTests.java b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerTests.java index 41b01f68..e21c3fa6 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerTests.java +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerTests.java @@ -44,12 +44,10 @@ class LoadBalancerTests { @BeforeAll static void setup() { - System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, - client.getConfiguration().getMasterUrl()); + System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); } @@ -57,8 +55,7 @@ class LoadBalancerTests { @Test void testLoadBalancerSameNamespace() { createTestData("service-a", "test"); - String response = restTemplate.getForObject("http://service-a/greeting", - String.class); + String response = restTemplate.getForObject("http://service-a/greeting", String.class); Assertions.assertNotNull(response); Assertions.assertEquals("greeting", response); } @@ -66,19 +63,18 @@ class LoadBalancerTests { @Test void testLoadBalancerDifferentNamespace() { createTestData("service-b", "b"); - Assertions.assertThrows(IllegalStateException.class, () -> restTemplate - .getForObject("http://service-b/greeting", String.class)); + Assertions.assertThrows(IllegalStateException.class, + () -> restTemplate.getForObject("http://service-b/greeting", String.class)); } private void createTestData(String name, String namespace) { - client.services().inNamespace(namespace).createNew().withNewMetadata() - .withName(name).endMetadata() - .withSpec(new ServiceSpecBuilder().withPorts(new ServicePortBuilder() - .withProtocol("TCP").withPort(randomServerPort).build()).build()) + client.services().inNamespace(namespace).createNew().withNewMetadata().withName(name).endMetadata() + .withSpec(new ServiceSpecBuilder() + .withPorts(new ServicePortBuilder().withProtocol("TCP").withPort(randomServerPort).build()) + .build()) .done(); - client.endpoints().inNamespace(namespace).createNew().withNewMetadata() - .withName("service-a").endMetadata().addNewSubset().addNewAddress() - .withIp("localhost").endAddress().addNewPort().withName("http") + client.endpoints().inNamespace(namespace).createNew().withNewMetadata().withName("service-a").endMetadata() + .addNewSubset().addNewAddress().withIp("localhost").endAddress().addNewPort().withName("http") .withPort(randomServerPort).endPort().endSubset().done(); } diff --git a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerWithServiceTests.java b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerWithServiceTests.java index 44a49670..8fc5b1a0 100644 --- a/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerWithServiceTests.java +++ b/spring-cloud-kubernetes-integration-tests/load-balancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/LoadBalancerWithServiceTests.java @@ -47,8 +47,7 @@ import static io.specto.hoverfly.junit.dsl.ResponseCreators.success; @ExtendWith(HoverflyExtension.class) class LoadBalancerWithServiceTests { - private static final Logger LOGGER = LoggerFactory - .getLogger(LoadBalancerWithServiceTests.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalancerWithServiceTests.class); @Autowired RestTemplate restTemplate; @@ -60,8 +59,7 @@ class LoadBalancerWithServiceTests { static void setup() { 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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false"); System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true"); System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test"); } @@ -70,23 +68,19 @@ class LoadBalancerWithServiceTests { void testLoadBalancerInServiceMode(Hoverfly hoverfly) { LOGGER.info("Master URL: {}", client.getConfiguration().getMasterUrl()); hoverfly.simulate( - dsl(service("http://service-a.test.svc.cluster.local:8080") - .get("/greeting").willReturn(success().body("greeting"))), - dsl(service(client.getConfiguration().getMasterUrl().replace("/", "") - .replace("https:", "")) - .get("/api/v1/namespaces/test/services/service-a") - .willReturn(success().body( - json(buildService("service-a", 8080, "test")))))); - String response = restTemplate.getForObject("http://service-a/greeting", - String.class); + dsl(service("http://service-a.test.svc.cluster.local:8080").get("/greeting") + .willReturn(success().body("greeting"))), + dsl(service(client.getConfiguration().getMasterUrl().replace("/", "").replace("https:", "")) + .get("/api/v1/namespaces/test/services/service-a") + .willReturn(success().body(json(buildService("service-a", 8080, "test")))))); + String response = restTemplate.getForObject("http://service-a/greeting", String.class); Assertions.assertNotNull(response); Assertions.assertEquals("greeting", response); } private Service buildService(String name, int port, String namespace) { - return new ServiceBuilder().withNewMetadata().withName(name) - .withNamespace(namespace).withLabels(new HashMap<>()) - .withAnnotations(new HashMap<>()).endMetadata().withNewSpec().addNewPort() + return new ServiceBuilder().withNewMetadata().withName(name).withNamespace(namespace) + .withLabels(new HashMap<>()).withAnnotations(new HashMap<>()).endMetadata().withNewSpec().addNewPort() .withPort(port).endPort().endSpec().build(); } diff --git a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java index 64daf954..69d85ca8 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java +++ b/spring-cloud-kubernetes-integration-tests/simple-configmap/src/test/java/org/springframework/cloud/kubernetes/it/GreetingIT.java @@ -34,16 +34,15 @@ public class GreetingIT { private static final String HOST = System.getProperty("service.host"); - private static final Integer PORT = Integer - .valueOf(System.getProperty("service.port")); + private static final Integer PORT = Integer.valueOf(System.getProperty("service.port")); - private static final String PROTOCOL = "true" - .equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http"; + private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https" + : "http"; @Test public void firstTestThatTheDefaultMessageIsReturned() { - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting") - .then().statusCode(200).body("message", is("This is a dummy message")); + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200) + .body("message", is("This is a dummy message")); } @Test @@ -51,8 +50,7 @@ public class GreetingIT { public void thenApplyAConfigMapAndEnsureThatTheMessageIsUpdated() { waitForApplicationToReload(); - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting") - .then().statusCode(200) + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200) .body("message", is("Hello from Spring Cloud Kubernetes!")); } diff --git a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java index c21a1377..aae8a8f6 100644 --- a/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java +++ b/spring-cloud-kubernetes-integration-tests/simple-core/src/test/java/org/springframework/cloud/kubernetes/it/GreetingAndHealthIT.java @@ -30,23 +30,21 @@ public class GreetingAndHealthIT { private static final String HOST = System.getProperty("service.host"); - private static final Integer PORT = Integer - .valueOf(System.getProperty("service.port")); + private static final Integer PORT = Integer.valueOf(System.getProperty("service.port")); - private static final String PROTOCOL = "true" - .equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http"; + private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https" + : "http"; @Test public void testGreetingEndpoint() { - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting") - .then().statusCode(200).body("message", is("Hello from k8s")); + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200) + .body("message", is("Hello from k8s")); } @Test public void testHealthEndpoint() { - given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)) - .contentType("application/json").get("actuator/health").then() - .statusCode(200).body("components.kubernetes.details.inside", is(true)); + given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).contentType("application/json") + .get("actuator/health").then().statusCode(200).body("components.kubernetes.details.inside", is(true)); } } diff --git a/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/IstioBootstrapConfiguration.java b/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/IstioBootstrapConfiguration.java index 3754cfac..8600a25d 100644 --- a/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/IstioBootstrapConfiguration.java +++ b/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/IstioBootstrapConfiguration.java @@ -59,8 +59,7 @@ public class IstioBootstrapConfiguration { private final ConfigurableEnvironment environment; - public IstioDetectionConfiguration(MeshUtils utils, - ConfigurableEnvironment environment) { + public IstioDetectionConfiguration(MeshUtils utils, ConfigurableEnvironment environment) { this.utils = utils; this.environment = environment; } @@ -86,15 +85,13 @@ public class IstioBootstrapConfiguration { } else { if (LOG.isDebugEnabled()) { - LOG.debug( - "Not running inside kubernetes with istio enabled. Skipping 'istio' profile activation."); + LOG.debug("Not running inside kubernetes with istio enabled. Skipping 'istio' profile activation."); } } } private boolean hasIstioProfile(Environment environment) { - return Arrays.stream(environment.getActiveProfiles()) - .anyMatch(ISTIO_PROFILE::equalsIgnoreCase); + return Arrays.stream(environment.getActiveProfiles()).anyMatch(ISTIO_PROFILE::equalsIgnoreCase); } } diff --git a/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/utils/MeshUtils.java b/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/utils/MeshUtils.java index 5f615f93..2325ee9a 100644 --- a/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/utils/MeshUtils.java +++ b/spring-cloud-kubernetes-istio/src/main/java/org/springframework/cloud/kubernetes/istio/utils/MeshUtils.java @@ -50,26 +50,21 @@ public class MeshUtils { // Check if Istio Envoy proxy is installed. Notice that the check is done to // localhost. // TODO: We can improve this initial detection if better methods are found. - String resource = "http://localhost:" - + this.istioClientProperties.getEnvoyPort(); - ResponseEntity response = this.restTemplate.getForEntity( - resource + "/" + this.istioClientProperties.getTestPath(), - String.class); + String resource = "http://localhost:" + this.istioClientProperties.getEnvoyPort(); + ResponseEntity response = this.restTemplate + .getForEntity(resource + "/" + this.istioClientProperties.getTestPath(), String.class); if (response.getStatusCode().is2xxSuccessful()) { LOG.info("Istio Resources Found."); return true; } - LOG.warn("Although Envoy proxy did respond at port" - + this.istioClientProperties.getEnvoyPort() - + ", it did not respond with HTTP 200 to path: " - + this.istioClientProperties.getTestPath() + LOG.warn("Although Envoy proxy did respond at port" + this.istioClientProperties.getEnvoyPort() + + ", it did not respond with HTTP 200 to path: " + this.istioClientProperties.getTestPath() + ". You may need to tweak the test path in order to get proper Istio support"); return false; } catch (Throwable t) { if (LOG.isDebugEnabled()) { - LOG.debug("Envoy proxy could not be located at port: " - + this.istioClientProperties.getEnvoyPort() + LOG.debug("Envoy proxy could not be located at port: " + this.istioClientProperties.getEnvoyPort() + ". Assuming that the application is not running inside the Istio Service Mesh"); } return false; diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/Leader.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/Leader.java index 8257f8cb..736878fc 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/Leader.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/Leader.java @@ -47,8 +47,7 @@ public class Leader { return false; } - return Objects.equals(this.role, candidate.getRole()) - && Objects.equals(this.id, candidate.getId()); + return Objects.equals(this.role, candidate.getRole()) && Objects.equals(this.id, candidate.getId()); } @Override @@ -63,8 +62,7 @@ public class Leader { Leader leader = (Leader) o; - return Objects.equals(this.role, leader.role) - && Objects.equals(this.id, leader.id); + return Objects.equals(this.role, leader.role) && Objects.equals(this.id, leader.id); } @Override diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfiguration.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfiguration.java index 05cf01f0..bc1fc504 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfiguration.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfiguration.java @@ -41,20 +41,17 @@ import org.springframework.integration.leader.event.LeaderEventPublisher; @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(LeaderProperties.class) @ConditionalOnBean(KubernetesClient.class) -@ConditionalOnProperty(value = "spring.cloud.kubernetes.leader.enabled", - matchIfMissing = true) +@ConditionalOnProperty(value = "spring.cloud.kubernetes.leader.enabled", matchIfMissing = true) public class LeaderAutoConfiguration { @Bean @ConditionalOnMissingBean(LeaderEventPublisher.class) - public LeaderEventPublisher defaultLeaderEventPublisher( - ApplicationEventPublisher applicationEventPublisher) { + public LeaderEventPublisher defaultLeaderEventPublisher(ApplicationEventPublisher applicationEventPublisher) { return new DefaultLeaderEventPublisher(applicationEventPublisher); } @Bean - public Candidate candidate(LeaderProperties leaderProperties) - throws UnknownHostException { + public Candidate candidate(LeaderProperties leaderProperties) throws UnknownHostException { String id = Inet4Address.getLocalHost().getHostName(); String role = leaderProperties.getRole(); @@ -62,41 +59,32 @@ public class LeaderAutoConfiguration { } @Bean - public LeadershipController leadershipController(Candidate candidate, - LeaderProperties leaderProperties, LeaderEventPublisher leaderEventPublisher, - KubernetesClient kubernetesClient) { - return new LeadershipController(candidate, leaderProperties, leaderEventPublisher, - kubernetesClient); + public LeadershipController leadershipController(Candidate candidate, LeaderProperties leaderProperties, + LeaderEventPublisher leaderEventPublisher, KubernetesClient kubernetesClient) { + return new LeadershipController(candidate, leaderProperties, leaderEventPublisher, kubernetesClient); } @Bean public LeaderRecordWatcher leaderRecordWatcher(LeaderProperties leaderProperties, - LeadershipController leadershipController, - KubernetesClient kubernetesClient) { - return new LeaderRecordWatcher(leaderProperties, leadershipController, - kubernetesClient); + LeadershipController leadershipController, KubernetesClient kubernetesClient) { + return new LeaderRecordWatcher(leaderProperties, leadershipController, kubernetesClient); } @Bean - public PodReadinessWatcher hostPodWatcher(Candidate candidate, - KubernetesClient kubernetesClient, + public PodReadinessWatcher hostPodWatcher(Candidate candidate, KubernetesClient kubernetesClient, LeadershipController leadershipController) { - return new PodReadinessWatcher(candidate.getId(), kubernetesClient, - leadershipController); + return new PodReadinessWatcher(candidate.getId(), kubernetesClient, leadershipController); } @Bean(destroyMethod = "stop") - public LeaderInitiator leaderInitiator(LeaderProperties leaderProperties, - LeadershipController leadershipController, + public LeaderInitiator leaderInitiator(LeaderProperties leaderProperties, LeadershipController leadershipController, LeaderRecordWatcher leaderRecordWatcher, PodReadinessWatcher hostPodWatcher) { - return new LeaderInitiator(leaderProperties, leadershipController, - leaderRecordWatcher, hostPodWatcher); + return new LeaderInitiator(leaderProperties, leadershipController, leaderRecordWatcher, hostPodWatcher); } @Bean @ConditionalOnClass(InfoContributor.class) - public LeaderInfoContributor leaderInfoContributor( - LeadershipController leadershipController, Candidate candidate) { + public LeaderInfoContributor leaderInfoContributor(LeadershipController leadershipController, Candidate candidate) { return new LeaderInfoContributor(leadershipController, candidate); } diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderContext.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderContext.java index 3106fd67..64457abf 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderContext.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderContext.java @@ -35,8 +35,7 @@ public class LeaderContext implements Context { @Override public boolean isLeader() { - return this.leadershipController.getLocalLeader() - .filter(l -> l.isCandidate(this.candidate)).isPresent(); + return this.leadershipController.getLocalLeader().filter(l -> l.isCandidate(this.candidate)).isPresent(); } @Override diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributor.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributor.java index fa14d39c..66cd3753 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributor.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributor.java @@ -30,8 +30,7 @@ public class LeaderInfoContributor implements InfoContributor { private final Candidate candidate; - public LeaderInfoContributor(LeadershipController leadershipController, - Candidate candidate) { + public LeaderInfoContributor(LeadershipController leadershipController, Candidate candidate) { this.leadershipController = leadershipController; this.candidate = candidate; } diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInitiator.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInitiator.java index c79880ac..a1f2bbf1 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInitiator.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderInitiator.java @@ -44,8 +44,7 @@ public class LeaderInitiator implements SmartLifecycle { private boolean isRunning; - public LeaderInitiator(LeaderProperties leaderProperties, - LeadershipController leadershipController, + public LeaderInitiator(LeaderProperties leaderProperties, LeadershipController leadershipController, LeaderRecordWatcher leaderRecordWatcher, PodReadinessWatcher hostPodWatcher) { this.leaderProperties = leaderProperties; this.leadershipController = leadershipController; @@ -65,11 +64,9 @@ public class LeaderInitiator implements SmartLifecycle { this.leaderRecordWatcher.start(); this.hostPodWatcher.start(); this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); - this.scheduledExecutorService.scheduleAtFixedRate( - this.leadershipController::update, + this.scheduledExecutorService.scheduleAtFixedRate(this.leadershipController::update, this.leaderProperties.getUpdatePeriod().toMillis(), - this.leaderProperties.getUpdatePeriod().toMillis(), - TimeUnit.MILLISECONDS); + this.leaderProperties.getUpdatePeriod().toMillis(), TimeUnit.MILLISECONDS); this.isRunning = true; } } diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcher.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcher.java index c0d3d663..69fc14fc 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcher.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcher.java @@ -29,8 +29,7 @@ import org.slf4j.LoggerFactory; */ public class LeaderRecordWatcher implements Watcher { - private static final Logger LOGGER = LoggerFactory - .getLogger(LeaderRecordWatcher.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LeaderRecordWatcher.class); private final Object lock = new Object(); @@ -42,8 +41,7 @@ public class LeaderRecordWatcher implements Watcher { private Watch watch; - public LeaderRecordWatcher(LeaderProperties leaderProperties, - LeadershipController leadershipController, + public LeaderRecordWatcher(LeaderProperties leaderProperties, LeadershipController leadershipController, KubernetesClient kubernetesClient) { this.leadershipController = leadershipController; this.leaderProperties = leaderProperties; @@ -56,10 +54,8 @@ public class LeaderRecordWatcher implements Watcher { if (this.watch == null) { LOGGER.debug("Starting leader record watcher"); this.watch = this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties - .getNamespace(this.kubernetesClient.getNamespace())) - .withName(this.leaderProperties.getConfigMapName()) - .watch(this); + .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) + .withName(this.leaderProperties.getConfigMapName()).watch(this); } } } diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeadershipController.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeadershipController.java index 898aeb18..c8982bc6 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeadershipController.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/LeadershipController.java @@ -45,8 +45,7 @@ public class LeadershipController { private static final String KIND = "leaders"; - private static final Logger LOGGER = LoggerFactory - .getLogger(LeadershipController.class); + private static final Logger LOGGER = LoggerFactory.getLogger(LeadershipController.class); private final Candidate candidate; @@ -61,8 +60,7 @@ public class LeadershipController { private PodReadinessWatcher leaderReadinessWatcher; public LeadershipController(Candidate candidate, LeaderProperties leaderProperties, - LeaderEventPublisher leaderEventPublisher, - KubernetesClient kubernetesClient) { + LeaderEventPublisher leaderEventPublisher, KubernetesClient kubernetesClient) { this.candidate = candidate; this.leaderProperties = leaderProperties; this.leaderEventPublisher = leaderEventPublisher; @@ -109,8 +107,7 @@ public class LeadershipController { handleLeaderChange(null); } catch (KubernetesClientException e) { - LOGGER.warn("Failure when revoking leadership for '{}': {}", this.candidate, - e.getMessage()); + LOGGER.warn("Failure when revoking leadership for '{}': {}", this.candidate, e.getMessage()); } } @@ -118,9 +115,7 @@ public class LeadershipController { LOGGER.debug("Trying to acquire leadership for '{}'", this.candidate); if (!isPodReady(this.candidate.getId())) { - LOGGER.debug( - "Pod of '{}' is not ready at the moment, cannot acquire leadership", - this.candidate); + LOGGER.debug("Pod of '{}' is not ready at the moment, cannot acquire leadership", this.candidate); return; } @@ -133,13 +128,11 @@ public class LeadershipController { updateConfigMapEntry(configMap, data); } - Leader newLeader = new Leader(this.candidate.getRole(), - this.candidate.getId()); + Leader newLeader = new Leader(this.candidate.getRole(), this.candidate.getId()); handleLeaderChange(newLeader); } catch (KubernetesClientException e) { - LOGGER.warn("Failure when acquiring leadership for '{}': {}", this.candidate, - e.getMessage()); + LOGGER.warn("Failure when acquiring leadership for '{}': {}", this.candidate, e.getMessage()); notifyOnFailedToAcquire(); } } @@ -169,8 +162,7 @@ public class LeadershipController { LOGGER.debug("Leadership has been granted for '{}'", this.candidate); Context context = new LeaderContext(this.candidate, this); - this.leaderEventPublisher.publishOnGranted(this, context, - this.candidate.getRole()); + this.leaderEventPublisher.publishOnGranted(this, context, this.candidate.getRole()); try { this.candidate.onGranted(context); } @@ -184,16 +176,14 @@ public class LeadershipController { LOGGER.debug("Leadership has been revoked for '{}'", this.candidate); Context context = new LeaderContext(this.candidate, this); - this.leaderEventPublisher.publishOnRevoked(this, context, - this.candidate.getRole()); + this.leaderEventPublisher.publishOnRevoked(this, context, this.candidate.getRole()); this.candidate.onRevoked(context); } private void notifyOnFailedToAcquire() { if (this.leaderProperties.isPublishFailedEvents()) { Context context = new LeaderContext(this.candidate, this); - this.leaderEventPublisher.publishOnFailedToAcquire(this, context, - this.candidate.getRole()); + this.leaderEventPublisher.publishOnFailedToAcquire(this, context, this.candidate.getRole()); } } @@ -204,8 +194,8 @@ public class LeadershipController { } if (this.localLeader != null && !this.localLeader.isCandidate(this.candidate)) { - this.leaderReadinessWatcher = new PodReadinessWatcher( - this.localLeader.getId(), this.kubernetesClient, this); + this.leaderReadinessWatcher = new PodReadinessWatcher(this.localLeader.getId(), this.kubernetesClient, + this); this.leaderReadinessWatcher.start(); } } @@ -240,8 +230,7 @@ public class LeadershipController { private ConfigMap getConfigMap() { return this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties - .getNamespace(this.kubernetesClient.getNamespace())) + .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) .withName(this.leaderProperties.getConfigMapName()).get(); } @@ -249,21 +238,18 @@ public class LeadershipController { LOGGER.debug("Creating new config map with data: {}", data); ConfigMap newConfigMap = new ConfigMapBuilder().withNewMetadata() - .withName(this.leaderProperties.getConfigMapName()) - .addToLabels(PROVIDER_KEY, PROVIDER).addToLabels(KIND_KEY, KIND) - .endMetadata().addToData(data).build(); + .withName(this.leaderProperties.getConfigMapName()).addToLabels(PROVIDER_KEY, PROVIDER) + .addToLabels(KIND_KEY, KIND).endMetadata().addToData(data).build(); this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties - .getNamespace(this.kubernetesClient.getNamespace())) + .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) .create(newConfigMap); } private void updateConfigMapEntry(ConfigMap configMap, Map newData) { LOGGER.debug("Adding new data to config map: {}", newData); - ConfigMap newConfigMap = new ConfigMapBuilder(configMap).addToData(newData) - .build(); + ConfigMap newConfigMap = new ConfigMapBuilder(configMap).addToData(newData).build(); updateConfigMap(configMap, newConfigMap); } @@ -271,19 +257,16 @@ public class LeadershipController { private void removeConfigMapEntry(ConfigMap configMap, String key) { LOGGER.debug("Removing config map entry '{}'", key); - ConfigMap newConfigMap = new ConfigMapBuilder(configMap).removeFromData(key) - .build(); + ConfigMap newConfigMap = new ConfigMapBuilder(configMap).removeFromData(key).build(); updateConfigMap(configMap, newConfigMap); } private void updateConfigMap(ConfigMap oldConfigMap, ConfigMap newConfigMap) { this.kubernetesClient.configMaps() - .inNamespace(this.leaderProperties - .getNamespace(this.kubernetesClient.getNamespace())) + .inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace())) .withName(this.leaderProperties.getConfigMapName()) - .lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion()) - .replace(newConfigMap); + .lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion()).replace(newConfigMap); } } diff --git a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcher.java b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcher.java index 4295c824..233edce4 100644 --- a/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcher.java +++ b/spring-cloud-kubernetes-leader/src/main/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcher.java @@ -32,8 +32,7 @@ import org.slf4j.LoggerFactory; */ public class PodReadinessWatcher implements Watcher { - private static final Logger LOGGER = LoggerFactory - .getLogger(PodReadinessWatcher.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PodReadinessWatcher.class); private final Object lock = new Object(); @@ -59,8 +58,7 @@ public class PodReadinessWatcher implements Watcher { synchronized (this.lock) { if (this.watch == null) { LOGGER.debug("Starting pod readiness watcher for '{}'", this.podName); - PodResource podResource = this.kubernetesClient - .pods().withName(this.podName); + PodResource podResource = this.kubernetesClient.pods().withName(this.podName); this.previousState = podResource.isReady(); this.watch = podResource.watch(this); } @@ -86,9 +84,8 @@ public class PodReadinessWatcher implements Watcher { if (this.previousState != currentState) { synchronized (this.lock) { if (this.previousState != currentState) { - LOGGER.debug( - "'{}' readiness status changed to '{}', triggering leadership update", - this.podName, currentState); + LOGGER.debug("'{}' readiness status changed to '{}', triggering leadership update", this.podName, + currentState); this.previousState = currentState; this.leadershipController.update(); } diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfigurationTests.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfigurationTests.java index fee60341..a56b1472 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfigurationTests.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderAutoConfigurationTests.java @@ -48,9 +48,8 @@ public class LeaderAutoConfigurationTests { @Test public void infoEndpointShouldContainLeaderElection() { - this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port) - .accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk() - .expectBody(String.class).value(containsString("kubernetes")); + this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON) + .exchange().expectStatus().isOk().expectBody(String.class).value(containsString("kubernetes")); } @SpringBootConfiguration diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderContextTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderContextTest.java index cb291fed..09247e5c 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderContextTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderContextTest.java @@ -49,14 +49,12 @@ public class LeaderContextTest { @BeforeEach public void before() { - this.leaderContext = new LeaderContext(this.mockCandidate, - this.mockLeadershipController); + this.leaderContext = new LeaderContext(this.mockCandidate, this.mockLeadershipController); } @Test public void testIsLeaderWithoutLeader() { - given(this.mockLeadershipController.getLocalLeader()) - .willReturn(Optional.empty()); + given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.empty()); boolean result = this.leaderContext.isLeader(); @@ -65,8 +63,7 @@ public class LeaderContextTest { @Test public void testIsLeaderWithAnotherLeader() { - given(this.mockLeadershipController.getLocalLeader()) - .willReturn(Optional.of(this.mockLeader)); + given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader)); boolean result = this.leaderContext.isLeader(); @@ -75,8 +72,7 @@ public class LeaderContextTest { @Test public void testIsLeaderWhenLeader() { - given(this.mockLeadershipController.getLocalLeader()) - .willReturn(Optional.of(this.mockLeader)); + given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader)); given(this.mockLeader.isCandidate(this.mockCandidate)).willReturn(true); boolean result = this.leaderContext.isLeader(); diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributorTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributorTest.java index 97de1bb3..d37de39b 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributorTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInfoContributorTest.java @@ -47,8 +47,7 @@ public class LeaderInfoContributorTest { @BeforeEach public void before() { - this.leaderInfoContributor = new LeaderInfoContributor( - this.mockLeadershipController, this.mockCandidate); + this.leaderInfoContributor = new LeaderInfoContributor(this.mockLeadershipController, this.mockCandidate); } @SuppressWarnings("unchecked") @@ -58,16 +57,14 @@ public class LeaderInfoContributorTest { leaderInfoContributor.contribute(builder); - Map details = (Map) builder.build() - .get("leaderElection"); + Map details = (Map) builder.build().get("leaderElection"); assertThat(details).containsEntry("leaderId", "Unknown"); } @SuppressWarnings("unchecked") @Test public void infoWhenLeader() { - given(this.mockLeadershipController.getLocalLeader()) - .willReturn(Optional.of(this.mockLeader)); + given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader)); given(this.mockLeader.isCandidate(this.mockCandidate)).willReturn(true); given(this.mockLeader.getRole()).willReturn("testRole"); given(this.mockLeader.getId()).willReturn("id"); @@ -75,8 +72,7 @@ public class LeaderInfoContributorTest { leaderInfoContributor.contribute(builder); - Map details = (Map) builder.build() - .get("leaderElection"); + Map details = (Map) builder.build().get("leaderElection"); assertThat(details).containsEntry("isLeader", true); assertThat(details).containsEntry("leaderId", "id"); assertThat(details).containsEntry("role", "testRole"); @@ -85,16 +81,14 @@ public class LeaderInfoContributorTest { @SuppressWarnings("unchecked") @Test public void infoWhenAnotherIsLeader() { - given(this.mockLeadershipController.getLocalLeader()) - .willReturn(Optional.of(this.mockLeader)); + given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader)); given(this.mockLeader.getRole()).willReturn("testRole"); given(this.mockLeader.getId()).willReturn("id"); Info.Builder builder = new Info.Builder(); leaderInfoContributor.contribute(builder); - Map details = (Map) builder.build() - .get("leaderElection"); + Map details = (Map) builder.build().get("leaderElection"); assertThat(details).containsEntry("isLeader", false); assertThat(details).containsEntry("leaderId", "id"); assertThat(details).containsEntry("role", "testRole"); diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInitiatorTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInitiatorTest.java index 844e66b2..b7afbe57 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInitiatorTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderInitiatorTest.java @@ -55,9 +55,8 @@ public class LeaderInitiatorTest { @BeforeEach public void before() { - this.leaderInitiator = new LeaderInitiator(this.mockLeaderProperties, - this.mockLeadershipController, this.mockLeaderRecordWatcher, - this.mockPodReadinessWatcher); + this.leaderInitiator = new LeaderInitiator(this.mockLeaderProperties, this.mockLeadershipController, + this.mockLeaderRecordWatcher, this.mockPodReadinessWatcher); } @AfterEach @@ -74,8 +73,7 @@ public class LeaderInitiatorTest { @Test public void shouldStart() throws InterruptedException { - given(this.mockLeaderProperties.getUpdatePeriod()) - .willReturn(Duration.ofMillis(1L)); + given(this.mockLeaderProperties.getUpdatePeriod()).willReturn(Duration.ofMillis(1L)); this.leaderInitiator.start(); @@ -88,8 +86,7 @@ public class LeaderInitiatorTest { @Test public void shouldStartOnlyOnce() { - given(this.mockLeaderProperties.getUpdatePeriod()) - .willReturn(Duration.ofMillis(10000L)); + given(this.mockLeaderProperties.getUpdatePeriod()).willReturn(Duration.ofMillis(10000L)); this.leaderInitiator.start(); this.leaderInitiator.start(); @@ -99,8 +96,7 @@ public class LeaderInitiatorTest { @Test public void shouldStop() { - given(this.mockLeaderProperties.getUpdatePeriod()) - .willReturn(Duration.ofMillis(10000L)); + given(this.mockLeaderProperties.getUpdatePeriod()).willReturn(Duration.ofMillis(10000L)); this.leaderInitiator.start(); this.leaderInitiator.stop(); @@ -113,8 +109,7 @@ public class LeaderInitiatorTest { @Test public void shouldStopOnlyOnce() { - given(this.mockLeaderProperties.getUpdatePeriod()) - .willReturn(Duration.ofMillis(10000L)); + given(this.mockLeaderProperties.getUpdatePeriod()).willReturn(Duration.ofMillis(10000L)); this.leaderInitiator.start(); this.leaderInitiator.stop(); @@ -125,8 +120,7 @@ public class LeaderInitiatorTest { @Test public void shouldStopAndExecuteCallback() { - given(this.mockLeaderProperties.getUpdatePeriod()) - .willReturn(Duration.ofMillis(10000L)); + given(this.mockLeaderProperties.getUpdatePeriod()).willReturn(Duration.ofMillis(10000L)); this.leaderInitiator.start(); this.leaderInitiator.stop(this.mockRunnable); diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcherTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcherTest.java index a609ee43..690608f0 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcherTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeaderRecordWatcherTest.java @@ -73,8 +73,8 @@ public class LeaderRecordWatcherTest { @BeforeEach public void before() { - this.watcher = new LeaderRecordWatcher(this.mockLeaderProperties, - this.mockLeadershipController, this.mockKubernetesClient); + this.watcher = new LeaderRecordWatcher(this.mockLeaderProperties, this.mockLeadershipController, + this.mockKubernetesClient); } @Test @@ -128,12 +128,9 @@ public class LeaderRecordWatcherTest { } private void initStubs() { - given(this.mockKubernetesClient.configMaps()) - .willReturn(this.mockConfigMapsOperation); - given(this.mockConfigMapsOperation.inNamespace(null)) - .willReturn(this.mockInNamespaceOperation); - given(this.mockInNamespaceOperation.withName(null)) - .willReturn(this.mockWithNameResource); + given(this.mockKubernetesClient.configMaps()).willReturn(this.mockConfigMapsOperation); + given(this.mockConfigMapsOperation.inNamespace(null)).willReturn(this.mockInNamespaceOperation); + given(this.mockInNamespaceOperation.withName(null)).willReturn(this.mockWithNameResource); given(this.mockWithNameResource.watch(this.watcher)).willReturn(this.mockWatch); } diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeadershipControllerTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeadershipControllerTest.java index 68eb61c8..6de7ed25 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeadershipControllerTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/LeadershipControllerTest.java @@ -50,9 +50,8 @@ public class LeadershipControllerTest { @BeforeEach public void before() { - this.leadershipController = new LeadershipController(this.mockCandidate, - this.mockLeaderProperties, this.mockLeaderEventPublisher, - this.mockKubernetesClient); + this.leadershipController = new LeadershipController(this.mockCandidate, this.mockLeaderProperties, + this.mockLeaderEventPublisher, this.mockKubernetesClient); } @Test diff --git a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcherTest.java b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcherTest.java index 4e8b308d..cc98056d 100644 --- a/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcherTest.java +++ b/spring-cloud-kubernetes-leader/src/test/java/org/springframework/cloud/kubernetes/leader/PodReadinessWatcherTest.java @@ -72,8 +72,7 @@ public class PodReadinessWatcherTest { @BeforeEach public void before() { - this.watcher = new PodReadinessWatcher(POD_NAME, this.mockKubernetesClient, - this.mockLeadershipController); + this.watcher = new PodReadinessWatcher(POD_NAME, this.mockKubernetesClient, this.mockLeadershipController); } @Test diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerAutoConfiguration.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerAutoConfiguration.java index df6f0eb1..fdd78224 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerAutoConfiguration.java +++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerAutoConfiguration.java @@ -30,10 +30,8 @@ import org.springframework.context.annotation.Configuration; */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(KubernetesLoadBalancerProperties.class) -@ConditionalOnProperty(value = "spring.cloud.kubernetes.loadbalancer.enabled", - matchIfMissing = true) -@LoadBalancerClients( - defaultConfiguration = KubernetesLoadBalancerClientConfiguration.class) +@ConditionalOnProperty(value = "spring.cloud.kubernetes.loadbalancer.enabled", matchIfMissing = true) +@LoadBalancerClients(defaultConfiguration = KubernetesLoadBalancerClientConfiguration.class) public class KubernetesLoadBalancerAutoConfiguration { @Bean diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerClientConfiguration.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerClientConfiguration.java index 4201f4c8..8a6e1af6 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerClientConfiguration.java +++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesLoadBalancerClientConfiguration.java @@ -31,13 +31,11 @@ import org.springframework.core.env.Environment; public class KubernetesLoadBalancerClientConfiguration { @Bean - @ConditionalOnProperty(name = "spring.cloud.kubernetes.loadbalancer.mode", - havingValue = "SERVICE") + @ConditionalOnProperty(name = "spring.cloud.kubernetes.loadbalancer.mode", havingValue = "SERVICE") KubernetesServicesListSupplier kubernetesServicesListSupplier(Environment environment, KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper, KubernetesDiscoveryProperties discoveryProperties) { - return new KubernetesServicesListSupplier(environment, kubernetesClient, mapper, - discoveryProperties); + return new KubernetesServicesListSupplier(environment, kubernetesClient, mapper, discoveryProperties); } } diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapper.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapper.java index cfe7bcef..32f43266 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapper.java +++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapper.java @@ -54,10 +54,8 @@ public class KubernetesServiceInstanceMapper { if (ports.size() == 1) { port = ports.get(0); } - else if (ports.size() > 1 - && Utils.isNotNullOrEmpty(this.properties.getPortName())) { - Optional optPort = ports.stream() - .filter(it -> properties.getPortName().endsWith(it.getName())) + else if (ports.size() > 1 && Utils.isNotNullOrEmpty(this.properties.getPortName())) { + Optional optPort = ports.stream().filter(it -> properties.getPortName().endsWith(it.getName())) .findAny(); if (optPort.isPresent()) { port = optPort.get(); @@ -68,22 +66,20 @@ public class KubernetesServiceInstanceMapper { } final String host = createHost(service); final boolean secure = isSecure(service, port); - return new KubernetesServiceInstance(meta.getUid(), meta.getName(), host, - port.getPort(), getServiceMetadata(service), secure); + return new KubernetesServiceInstance(meta.getUid(), meta.getName(), host, port.getPort(), + getServiceMetadata(service), secure); } private Map getServiceMetadata(Service service) { final Map serviceMetadata = new HashMap<>(); - KubernetesDiscoveryProperties.Metadata metadataProps = this.discoveryProperties - .getMetadata(); + KubernetesDiscoveryProperties.Metadata metadataProps = this.discoveryProperties.getMetadata(); if (metadataProps.isAddLabels()) { - Map labelMetadata = getMapWithPrefixedKeys( - service.getMetadata().getLabels(), metadataProps.getLabelsPrefix()); + Map labelMetadata = getMapWithPrefixedKeys(service.getMetadata().getLabels(), + metadataProps.getLabelsPrefix()); serviceMetadata.putAll(labelMetadata); } if (metadataProps.isAddAnnotations()) { - Map annotationMetadata = getMapWithPrefixedKeys( - service.getMetadata().getAnnotations(), + Map annotationMetadata = getMapWithPrefixedKeys(service.getMetadata().getAnnotations(), metadataProps.getAnnotationsPrefix()); serviceMetadata.putAll(annotationMetadata); } @@ -91,8 +87,7 @@ public class KubernetesServiceInstanceMapper { return serviceMetadata; } - private Map getMapWithPrefixedKeys(Map map, - String prefix) { + private Map getMapWithPrefixedKeys(Map map, String prefix) { if (map == null) { return new HashMap<>(); } @@ -105,13 +100,11 @@ public class KubernetesServiceInstanceMapper { } private boolean isSecure(Service service, ServicePort port) { - final String securedLabelValue = service.getMetadata().getLabels() - .getOrDefault("secured", "false"); + final String securedLabelValue = service.getMetadata().getLabels().getOrDefault("secured", "false"); if (securedLabelValue.equals("true")) { return true; } - final String securedAnnotationValue = service.getMetadata().getAnnotations() - .getOrDefault("secured", "false"); + final String securedAnnotationValue = service.getMetadata().getAnnotations().getOrDefault("secured", "false"); if (securedAnnotationValue.equals("true")) { return true; } @@ -121,8 +114,8 @@ public class KubernetesServiceInstanceMapper { private String createHost(Service service) { return String.format("%s.%s.svc.%s", service.getMetadata().getName(), - StringUtils.isNotBlank(service.getMetadata().getNamespace()) - ? service.getMetadata().getNamespace() : "default", + StringUtils.isNotBlank(service.getMetadata().getNamespace()) ? service.getMetadata().getNamespace() + : "default", properties.getClusterDomain()); } diff --git a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java index 63447b91..9cb289a6 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java +++ b/spring-cloud-kubernetes-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServicesListSupplier.java @@ -46,9 +46,8 @@ public class KubernetesServicesListSupplier implements ServiceInstanceListSuppli private final KubernetesServiceInstanceMapper mapper; - KubernetesServicesListSupplier(Environment environment, - KubernetesClient kubernetesClient, KubernetesServiceInstanceMapper mapper, - KubernetesDiscoveryProperties discoveryProperties) { + KubernetesServicesListSupplier(Environment environment, KubernetesClient kubernetesClient, + KubernetesServiceInstanceMapper mapper, KubernetesDiscoveryProperties discoveryProperties) { this.environment = environment; this.kubernetesClient = kubernetesClient; this.discoveryProperties = discoveryProperties; @@ -70,11 +69,9 @@ public class KubernetesServicesListSupplier implements ServiceInstanceListSuppli } else { Service service = StringUtils.isNotBlank(this.kubernetesClient.getNamespace()) - ? this.kubernetesClient.services() - .inNamespace(this.kubernetesClient.getNamespace()) + ? this.kubernetesClient.services().inNamespace(this.kubernetesClient.getNamespace()) .withName(this.getServiceId()).get() - : this.kubernetesClient.services().withName(this.getServiceId()) - .get(); + : this.kubernetesClient.services().withName(this.getServiceId()).get(); if (service != null) { result.add(mapper.map(service)); } diff --git a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTests.java b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTests.java index c49d5187..5fb1368b 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTests.java +++ b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceInstanceMapperTests.java @@ -39,8 +39,8 @@ class KubernetesServiceInstanceMapperTests { KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties(); KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(); Service service = buildService("test", "abc", 8080, null, new HashMap<>()); - KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper( - properties, discoveryProperties).map(service); + KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(properties, discoveryProperties) + .map(service); Assertions.assertNotNull(instance); Assertions.assertEquals("test", instance.getServiceId()); Assertions.assertEquals("abc", instance.getInstanceId()); @@ -55,8 +55,8 @@ class KubernetesServiceInstanceMapperTests { ports.add(new ServicePortBuilder().withPort(8080).withName("web").build()); ports.add(new ServicePortBuilder().withPort(9000).withName("http").build()); Service service = buildService("test", "abc", ports, new HashMap<>()); - KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper( - properties, discoveryProperties).map(service); + KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(properties, discoveryProperties) + .map(service); Assertions.assertNotNull(instance); Assertions.assertEquals("test", instance.getServiceId()); Assertions.assertEquals("abc", instance.getInstanceId()); @@ -68,8 +68,8 @@ class KubernetesServiceInstanceMapperTests { KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties(); KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(); Service service = buildService("test", "abc", 443, null, new HashMap<>()); - KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper( - properties, discoveryProperties).map(service); + KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(properties, discoveryProperties) + .map(service); Assertions.assertNotNull(instance); Assertions.assertEquals("test", instance.getServiceId()); Assertions.assertEquals("abc", instance.getInstanceId()); @@ -84,8 +84,8 @@ class KubernetesServiceInstanceMapperTests { labels.put("secured", "true"); labels.put("label1", "123"); Service service = buildService("test", "abc", 8080, null, labels); - KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper( - properties, discoveryProperties).map(service); + KubernetesServiceInstance instance = new KubernetesServiceInstanceMapper(properties, discoveryProperties) + .map(service); Assertions.assertNotNull(instance); Assertions.assertEquals("test", instance.getServiceId()); Assertions.assertEquals("abc", instance.getInstanceId()); @@ -93,17 +93,13 @@ class KubernetesServiceInstanceMapperTests { Assertions.assertEquals(2, instance.getMetadata().keySet().size()); } - private Service buildService(String name, String uid, List ports, - Map labels) { - return new ServiceBuilder().withNewMetadata().withName(name).withNewUid(uid) - .addToLabels(labels).addToAnnotations(new HashMap<>(0)).endMetadata() - .withNewSpec().addAllToPorts(ports).endSpec().build(); + private Service buildService(String name, String uid, List ports, Map labels) { + return new ServiceBuilder().withNewMetadata().withName(name).withNewUid(uid).addToLabels(labels) + .addToAnnotations(new HashMap<>(0)).endMetadata().withNewSpec().addAllToPorts(ports).endSpec().build(); } - private Service buildService(String name, String uid, int port, String portName, - Map labels) { - ServicePort servicePort = new ServicePortBuilder().withPort(port) - .withName(portName).build(); + private Service buildService(String name, String uid, int port, String portName, Map labels) { + ServicePort servicePort = new ServicePortBuilder().withPort(port).withName(portName).build(); return buildService(name, uid, Collections.singletonList(servicePort), labels); } diff --git a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTests.java b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTests.java index 9dd9c0ad..d1799cea 100644 --- a/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTests.java +++ b/spring-cloud-kubernetes-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/loadbalancer/KubernetesServiceListSupplierTests.java @@ -69,18 +69,15 @@ class KubernetesServiceListSupplierTests { @Test void testPositiveMatch() { - when(environment.getProperty("loadbalancer.client.name")) - .thenReturn("test-service"); - when(mapper.map(any(Service.class))) - .thenReturn(new KubernetesServiceInstance("", "", "", 0, null, false)); + when(environment.getProperty("loadbalancer.client.name")).thenReturn("test-service"); + when(mapper.map(any(Service.class))).thenReturn(new KubernetesServiceInstance("", "", "", 0, null, false)); when(this.client.getNamespace()).thenReturn("test"); when(this.client.services()).thenReturn(this.serviceOperation); when(this.serviceOperation.inNamespace("test")).thenReturn(namespaceOperation); - when(this.namespaceOperation.withName("test-service")) - .thenReturn(this.serviceResource); + when(this.namespaceOperation.withName("test-service")).thenReturn(this.serviceResource); when(this.serviceResource.get()).thenReturn(buildService("test-service", 8080)); - KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier( - environment, client, mapper, new KubernetesDiscoveryProperties()); + KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier(environment, client, mapper, + new KubernetesDiscoveryProperties()); List instances = supplier.get().blockFirst(); assert instances != null; Assertions.assertEquals(1, instances.size()); @@ -88,29 +85,26 @@ class KubernetesServiceListSupplierTests { @Test void testPositiveMatchAllNamespaces() { - when(environment.getProperty("loadbalancer.client.name")) - .thenReturn("test-service"); - when(mapper.map(any(Service.class))) - .thenReturn(new KubernetesServiceInstance("", "", "", 0, null, false)); + when(environment.getProperty("loadbalancer.client.name")).thenReturn("test-service"); + when(mapper.map(any(Service.class))).thenReturn(new KubernetesServiceInstance("", "", "", 0, null, false)); when(this.client.services()).thenReturn(this.serviceOperation); when(this.serviceOperation.inAnyNamespace()).thenReturn(this.multiDeletable); - when(this.multiDeletable.withField("metadata.name", "test-service")) - .thenReturn(this.multiDeletable); + when(this.multiDeletable.withField("metadata.name", "test-service")).thenReturn(this.multiDeletable); ServiceList serviceList = new ServiceList(); serviceList.getItems().add(buildService("test-service", 8080)); when(this.multiDeletable.list()).thenReturn(serviceList); KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(); discoveryProperties.setAllNamespaces(true); - KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier( - environment, client, mapper, discoveryProperties); + KubernetesServicesListSupplier supplier = new KubernetesServicesListSupplier(environment, client, mapper, + discoveryProperties); List instances = supplier.get().blockFirst(); assert instances != null; Assertions.assertEquals(1, instances.size()); } private Service buildService(String name, int port) { - return new ServiceBuilder().withNewMetadata().withName(name).endMetadata() - .withNewSpec().addNewPort().withPort(port).endPort().endSpec().build(); + return new ServiceBuilder().withNewMetadata().withName(name).endMetadata().withNewSpec().addNewPort() + .withPort(port).endPort().endSpec().build(); } }