diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index cb2cbf674..10e6cd681 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -1269,6 +1269,15 @@ spring: The above example will result in a merged health-check `@ConfigurationProperties` object with `initial-delay=1s` and `interval=30s`. +The per-client configuration properties work for most of the properties, apart from the following global ones: + +- `spring.cloud.loadbalancer.enabled` - globally enables or disables load-balancing +- `spring.cloud.loadbalancer.retry.enabled` - globally enables or disables load-balanced retries. If you enable it globally, you can still disable retries for specific clients using the `client`-prefixed properties, but not the other way round +- `spring.cloud.loadbalancer.cache.enabled` - globally enables or disables LoadBalancer caching. If you enable it globally, you can still disable caching for specific clients by creating a <> that does not include the `CachingServiceInstanceListSupplier` in the `ServiceInstanceListSupplier` delegates hierarchy, but not the other way round. +- `spring.cloud.loadbalancer.stats.micrometer.enabled` - globally enables or disables LoadBalancer Micrometer metrics + +NOTE: For the properties where maps where already used, where you could specify a different value per-client without using the `clients` keyword (for example, `hints`, `health-check.path`), we have kept that behaviour in order to keep the library backwards compatible. It will be modified in the next major release. + == Spring Cloud Circuit Breaker include::spring-cloud-circuitbreaker.adoc[leveloffset=+1] diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java index a820f6ec3..158248fbb 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/annotation/LoadBalancerClientConfiguration.java @@ -30,19 +30,24 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient; +import org.springframework.cloud.loadbalancer.config.XForwardedConfigurationCondition; import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; import org.springframework.cloud.loadbalancer.core.RetryAwareServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.core.XForwardedHeadersTransformer; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.loadbalancer.support.LoadBalancerEnvironmentPropertyUtils; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; +import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.retry.support.RetryTemplate; import org.springframework.web.client.RestTemplate; import org.springframework.web.reactive.function.client.WebClient; @@ -76,8 +81,7 @@ public static class ReactiveSupportConfiguration { @Bean @ConditionalOnBean(ReactiveDiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", - matchIfMissing = true) + @Conditional(DefaultConfigurationCondition.class) public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().build(context); @@ -86,7 +90,7 @@ public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier( @Bean @ConditionalOnBean(ReactiveDiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference") + @Conditional(ZonePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withDiscoveryClient().withZonePreference().withCaching() @@ -96,7 +100,7 @@ public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceL @Bean @ConditionalOnBean({ XForwardedHeadersTransformer.class, LoadBalancerClientFactory.class }) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.xForwarded.enabledXforwarded", havingValue = "true") + @Conditional(XForwardedConfigurationCondition.class) public XForwardedHeadersTransformer xForwarderHeadersTransformer(LoadBalancerClientFactory clientFactory) { return new XForwardedHeadersTransformer(clientFactory); } @@ -104,7 +108,7 @@ public XForwardedHeadersTransformer xForwarderHeadersTransformer(LoadBalancerCli @Bean @ConditionalOnBean({ ReactiveDiscoveryClient.class, WebClient.Builder.class }) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "health-check") + @Conditional(HealthCheckConfigurationCondition.class) public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withDiscoveryClient().withHealthChecks().build(context); @@ -113,8 +117,7 @@ public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceList @Bean @ConditionalOnBean(ReactiveDiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", - havingValue = "request-based-sticky-session") + @Conditional(RequestBasedStickySessionConfigurationCondition.class) public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withDiscoveryClient().withRequestBasedStickySession() @@ -124,8 +127,7 @@ public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServi @Bean @ConditionalOnBean(ReactiveDiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", - havingValue = "same-instance-preference") + @Conditional(SameInstancePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier sameInstancePreferenceServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withDiscoveryClient().withSameInstancePreference() @@ -142,8 +144,7 @@ public static class BlockingSupportConfiguration { @Bean @ConditionalOnBean(DiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "default", - matchIfMissing = true) + @Conditional(DefaultConfigurationCondition.class) public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context); @@ -152,7 +153,7 @@ public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier( @Bean @ConditionalOnBean(DiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "zone-preference") + @Conditional(ZonePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withZonePreference() @@ -162,7 +163,7 @@ public ServiceInstanceListSupplier zonePreferenceDiscoveryClientServiceInstanceL @Bean @ConditionalOnBean({ DiscoveryClient.class, RestTemplate.class }) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", havingValue = "health-check") + @Conditional(HealthCheckConfigurationCondition.class) public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withBlockingHealthChecks() @@ -172,8 +173,7 @@ public ServiceInstanceListSupplier healthCheckDiscoveryClientServiceInstanceList @Bean @ConditionalOnBean(DiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", - havingValue = "request-based-sticky-session") + @Conditional(RequestBasedStickySessionConfigurationCondition.class) public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withRequestBasedStickySession() @@ -183,8 +183,7 @@ public ServiceInstanceListSupplier requestBasedStickySessionDiscoveryClientServi @Bean @ConditionalOnBean(DiscoveryClient.class) @ConditionalOnMissingBean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.configurations", - havingValue = "same-instance-preference") + @Conditional(SameInstancePreferenceConfigurationCondition.class) public ServiceInstanceListSupplier sameInstancePreferenceServiceInstanceListSupplier( ConfigurableApplicationContext context) { return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withSameInstancePreference() @@ -241,8 +240,7 @@ static class LoadBalancerRetryEnabled { } - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.avoid-previous-instance", havingValue = "true", - matchIfMissing = true) + @Conditional(AvoidPreviousInstanceEnabledCondition.class) static class AvoidPreviousInstanceEnabled { } @@ -260,12 +258,71 @@ static class LoadBalancerRetryEnabled { } - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.avoid-previous-instance", havingValue = "true", - matchIfMissing = true) + @Conditional(AvoidPreviousInstanceEnabledCondition.class) static class AvoidPreviousInstanceEnabled { } } + static class AvoidPreviousInstanceEnabledCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.trueOrMissingForClientOrDefault(context.getEnvironment(), + "retry.avoid-previous-instance"); + } + + } + + static class DefaultConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.equalToOrMissingForClientOrDefault(context.getEnvironment(), + "configurations", "default"); + } + + } + + static class ZonePreferenceConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(context.getEnvironment(), + "configurations", "zone-preference"); + } + + } + + static class HealthCheckConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(context.getEnvironment(), + "configurations", "health-check"); + } + + } + + static class RequestBasedStickySessionConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(context.getEnvironment(), + "configurations", "request-based-sticky-session"); + } + + } + + static class SameInstancePreferenceConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(context.getEnvironment(), + "configurations", "same-instance-preference"); + } + + } + } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/BlockingLoadBalancerClientAutoConfiguration.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/BlockingLoadBalancerClientAutoConfiguration.java index fd8a3663c..9b6587205 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/BlockingLoadBalancerClientAutoConfiguration.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/BlockingLoadBalancerClientAutoConfiguration.java @@ -21,7 +21,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration; @@ -36,8 +35,13 @@ import org.springframework.cloud.loadbalancer.blocking.retry.BlockingLoadBalancedRetryFactory; import org.springframework.cloud.loadbalancer.core.LoadBalancerServiceInstanceCookieTransformer; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.loadbalancer.support.LoadBalancerEnvironmentPropertyUtils; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.retry.support.RetryTemplate; import org.springframework.web.client.RestTemplate; @@ -64,8 +68,7 @@ public LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory l } @Bean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie", - havingValue = "true") + @Conditional(AddServiceInstanceCookieCondition.class) @ConditionalOnMissingBean(LoadBalancerServiceInstanceCookieTransformer.class) public LoadBalancerServiceInstanceCookieTransformer loadBalancerServiceInstanceCookieTransformer( LoadBalancerProperties properties) { @@ -73,7 +76,7 @@ public LoadBalancerServiceInstanceCookieTransformer loadBalancerServiceInstanceC } @Bean - @ConditionalOnProperty(value = "spring.cloud.loadbalancer.xforwarded.enabledXforwarded", havingValue = "true") + @Conditional(XForwardedConfigurationCondition.class) @ConditionalOnMissingBean(XForwardedHeadersTransformer.class) @ConditionalOnBean(LoadBalancerClientFactory.class) public XForwardedHeadersTransformer xForwarderHeadersTransformer( @@ -95,4 +98,14 @@ LoadBalancedRetryFactory loadBalancedRetryFactory( } + static class AddServiceInstanceCookieCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.trueForClientOrDefault(context.getEnvironment(), + "sticky-session.add-service-instance-cookie"); + } + + } + } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/XForwardedConfigurationCondition.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/XForwardedConfigurationCondition.java new file mode 100644 index 000000000..f82cb0692 --- /dev/null +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/XForwardedConfigurationCondition.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012-2021 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.loadbalancer.config; + +import org.springframework.cloud.loadbalancer.support.LoadBalancerEnvironmentPropertyUtils; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * Condition matched when x-forwarded headers are enabled via properties. + * + * @author Olga Maciaszek-Sharma + * @since 3.1.0 + */ +public class XForwardedConfigurationCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return LoadBalancerEnvironmentPropertyUtils.trueForClientOrDefault(context.getEnvironment(), + "spring.cloud.loadbalancer.x-forwarded.enabled"); + } + +} diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerClientFactory.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerClientFactory.java index 3596352b8..e8b4db64a 100644 --- a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerClientFactory.java +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerClientFactory.java @@ -69,7 +69,7 @@ public LoadBalancerClientFactory(LoadBalancerClientsProperties properties) { this.properties = properties; } - public String getName(Environment environment) { + public static String getName(Environment environment) { return environment.getProperty(PROPERTY_NAME); } diff --git a/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtils.java b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtils.java new file mode 100644 index 000000000..3856dc674 --- /dev/null +++ b/spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-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.loadbalancer.support; + +import org.springframework.core.env.Environment; + +/** + * @author Olga Maciaszek-Sharma + */ +public final class LoadBalancerEnvironmentPropertyUtils { + + private LoadBalancerEnvironmentPropertyUtils() { + throw new IllegalStateException("Should not instantiate a utility class"); + } + + public static boolean trueForClientOrDefault(Environment environment, String propertySuffix) { + return equalToForClientOrDefault(environment, propertySuffix, Boolean.TRUE.toString()); + } + + public static boolean equalToForClientOrDefault(Environment environment, String propertySuffix, + String expectedPropertyValue) { + String defaultValue = getDefaultPropertyValue(environment, propertySuffix); + String clientValue = getClientPropertyValue(environment, propertySuffix); + if (clientValue != null && clientValue.equalsIgnoreCase(expectedPropertyValue)) { + return true; + } + return clientValue == null && defaultValue != null && defaultValue.equalsIgnoreCase(expectedPropertyValue); + } + + public static boolean equalToOrMissingForClientOrDefault(Environment environment, String propertySuffix, + String expectedPropertyValue) { + String defaultValue = getDefaultPropertyValue(environment, propertySuffix); + String clientValue = getClientPropertyValue(environment, propertySuffix); + if (clientValue != null && clientValue.equalsIgnoreCase(expectedPropertyValue)) { + return true; + } + if (clientValue == null && defaultValue != null && defaultValue.equalsIgnoreCase(expectedPropertyValue)) { + return true; + } + return clientValue == null && defaultValue == null; + } + + public static boolean trueOrMissingForClientOrDefault(Environment environment, String propertySuffix) { + return equalToOrMissingForClientOrDefault(environment, propertySuffix, Boolean.TRUE.toString()); + } + + private static String getClientPropertyValue(Environment environment, String propertySuffix) { + return environment.getProperty("spring.cloud.loadbalancer.clients." + + LoadBalancerClientFactory.getName(environment) + "." + propertySuffix); + } + + private static String getDefaultPropertyValue(Environment environment, String propertySuffix) { + return environment.getProperty("spring.cloud.loadbalancer." + propertySuffix); + } + +} diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/LoadBalancerTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/LoadBalancerTests.java index d2081cbe2..df648106d 100644 --- a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/LoadBalancerTests.java +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/core/LoadBalancerTests.java @@ -188,7 +188,7 @@ protected static class MyServiceConfig { @Bean public RoundRobinLoadBalancer roundRobinContextLoadBalancer(LoadBalancerClientFactory clientFactory, Environment env) { - String serviceId = clientFactory.getName(env); + String serviceId = LoadBalancerClientFactory.getName(env); return new RoundRobinLoadBalancer( clientFactory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class), serviceId, -1); } diff --git a/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtilsTests.java b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtilsTests.java new file mode 100644 index 000000000..6e8105b1c --- /dev/null +++ b/spring-cloud-loadbalancer/src/test/java/org/springframework/cloud/loadbalancer/support/LoadBalancerEnvironmentPropertyUtilsTests.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-2021 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.loadbalancer.support; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link LoadBalancerEnvironmentPropertyUtils}. + * + * @author Olga Maciaszek-Sharma + */ +class LoadBalancerEnvironmentPropertyUtilsTests { + + MockEnvironment environment = new MockEnvironment(); + + @BeforeEach + void setUp() { + environment.setProperty("loadbalancer.client.name", "x"); + } + + @Test + void shouldReturnTrueWhenTrueForClient() { + environment.setProperty("spring.cloud.loadbalancer.clients.x.test", "true"); + environment.setProperty("spring.cloud.loadbalancer.test", "false"); + + assertThat(LoadBalancerEnvironmentPropertyUtils.trueForClientOrDefault(environment, "test")).isTrue(); + assertThat(LoadBalancerEnvironmentPropertyUtils.trueOrMissingForClientOrDefault(environment, "test")).isTrue(); + } + + @Test + void shouldReturnTrueWhenTrueForDefault() { + environment.setProperty("spring.cloud.loadbalancer.test", "true"); + + assertThat(LoadBalancerEnvironmentPropertyUtils.trueForClientOrDefault(environment, "test")).isTrue(); + assertThat(LoadBalancerEnvironmentPropertyUtils.trueOrMissingForClientOrDefault(environment, "test")).isTrue(); + } + + @Test + void shouldReturnTrueWhenEqualForClient() { + environment.setProperty("spring.cloud.loadbalancer.clients.x.test", "true"); + environment.setProperty("spring.cloud.loadbalancer.test", "false"); + + assertThat(LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(environment, "test", "true")) + .isTrue(); + assertThat(LoadBalancerEnvironmentPropertyUtils.equalToOrMissingForClientOrDefault(environment, "test", "true")) + .isTrue(); + } + + @Test + void shouldReturnTrueWhenEqualForDefault() { + environment.setProperty("spring.cloud.loadbalancer.test", "true"); + + assertThat(LoadBalancerEnvironmentPropertyUtils.equalToForClientOrDefault(environment, "test", "true")) + .isTrue(); + assertThat(LoadBalancerEnvironmentPropertyUtils.equalToOrMissingForClientOrDefault(environment, "test", "true")) + .isTrue(); + } + + @Test + void shouldReturnTrueWhenMissingForClientAndDefault() { + assertThat(LoadBalancerEnvironmentPropertyUtils.trueOrMissingForClientOrDefault(environment, "test")).isTrue(); + assertThat(LoadBalancerEnvironmentPropertyUtils.equalToOrMissingForClientOrDefault(environment, "test", "true")) + .isTrue(); + } + +}