From ffc2cff8de850ced28b131620ebf1ea0effac5f7 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Thu, 2 Apr 2020 20:23:41 +0200 Subject: [PATCH] Override CloudPlatform auto-detection with configuration property This commit adds the new "`spring.main.cloud-platform`" configuration property. This allows applications to override the auto-detection and force a specific Cloud Platform. This is useful for testing behavior on a local machine or force the detection of a particular platform. This commit also adds a new `CloudPlatform.NONE` value that allows applications to disable the auto-detection of the Cloud Platform, thus avoiding issues with false positives. Closes gh-20553 --- .../boot/cloud/CloudPlatform.java | 62 +++++++++++++++---- ...itional-spring-configuration-metadata.json | 5 ++ .../boot/cloud/CloudPlatformTests.java | 8 +++ 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java index 03ff6ef59f..8827ba02ad 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/cloud/CloudPlatform.java @@ -23,22 +23,36 @@ import org.springframework.core.env.PropertySource; import org.springframework.core.env.StandardEnvironment; /** - * Simple detection for well known cloud platforms. For more advanced cloud provider - * integration consider the Spring Cloud project. + * Simple detection for well known cloud platforms. Detection can be forced using the + * {@code "spring.main.cloud-platform"} configuration property. For more advanced cloud + * provider integration consider the Spring Cloud project. * * @author Phillip Webb + * @author Brian Clozel * @since 1.3.0 - * @see "https://cloud.spring.io" + * @see "https://spring.io/projects/spring-cloud" */ public enum CloudPlatform { + /** + * No Cloud platform. Useful when false-positives are detected. + */ + NONE { + + @Override + public boolean isAutoDetected(Environment environment) { + return false; + } + + }, + /** * Cloud Foundry platform. */ CLOUD_FOUNDRY { @Override - public boolean isActive(Environment environment) { + public boolean isAutoDetected(Environment environment) { return environment.containsProperty("VCAP_APPLICATION") || environment.containsProperty("VCAP_SERVICES"); } @@ -50,7 +64,7 @@ public enum CloudPlatform { HEROKU { @Override - public boolean isActive(Environment environment) { + public boolean isAutoDetected(Environment environment) { return environment.containsProperty("DYNO"); } @@ -62,7 +76,7 @@ public enum CloudPlatform { SAP { @Override - public boolean isActive(Environment environment) { + public boolean isAutoDetected(Environment environment) { return environment.containsProperty("HC_LANDSCAPE"); } @@ -82,14 +96,14 @@ public enum CloudPlatform { private static final String SERVICE_PORT_SUFFIX = "_SERVICE_PORT"; @Override - public boolean isActive(Environment environment) { + public boolean isAutoDetected(Environment environment) { if (environment instanceof ConfigurableEnvironment) { - return isActive((ConfigurableEnvironment) environment); + return isAutoDetected((ConfigurableEnvironment) environment); } return false; } - private boolean isActive(ConfigurableEnvironment environment) { + private boolean isAutoDetected(ConfigurableEnvironment environment) { PropertySource environmentPropertySource = environment.getPropertySources() .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); if (environmentPropertySource != null) { @@ -98,13 +112,13 @@ public enum CloudPlatform { return true; } if (environmentPropertySource instanceof EnumerablePropertySource) { - return isActive((EnumerablePropertySource) environmentPropertySource); + return isAutoDetected((EnumerablePropertySource) environmentPropertySource); } } return false; } - private boolean isActive(EnumerablePropertySource environmentPropertySource) { + private boolean isAutoDetected(EnumerablePropertySource environmentPropertySource) { for (String propertyName : environmentPropertySource.getPropertyNames()) { if (propertyName.endsWith(SERVICE_HOST_SUFFIX)) { String serviceName = propertyName.substring(0, @@ -124,7 +138,31 @@ public enum CloudPlatform { * @param environment the environment * @return if the platform is active. */ - public abstract boolean isActive(Environment environment); + public boolean isActive(Environment environment) { + return isEnforced(environment) || isAutoDetected(environment); + } + + /** + * Detemines if the platform is enforced by looking at the + * {@code "spring.main.cloud-platform"} configuration property. + * @param environment the environment + * @return if the platform is enforced + */ + public boolean isEnforced(Environment environment) { + String platform = environment.getProperty("spring.main.cloud-platform"); + if (platform != null) { + return this.name().equalsIgnoreCase(platform); + } + return false; + } + + /** + * Determines if the platform is auto-detected by looking for platform-specific + * environment variables. + * @param environment the environment + * @return if the platform is auto-detected. + */ + public abstract boolean isAutoDetected(Environment environment); /** * Returns if the platform is behind a load balancer and uses diff --git a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 06d811582a..603d0ceb80 100644 --- a/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -640,6 +640,11 @@ "description": "Mode used to display the banner when the application runs.", "defaultValue": "console" }, + { + "name": "spring.main.cloud-platform", + "type": "org.springframework.boot.cloud.CloudPlatform", + "description": "Override the Cloud Platform auto-detection." + }, { "name": "spring.main.lazy-initialization", "type": "java.lang.Boolean", diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/CloudPlatformTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/CloudPlatformTests.java index 9787259337..c308c057d2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/CloudPlatformTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/cloud/CloudPlatformTests.java @@ -129,6 +129,14 @@ class CloudPlatformTests { assertThat(platform).isNull(); } + @Test + void getActiveWhenHasEnforcedCloudPlatform() { + Environment environment = getEnvironmentWithEnvVariables( + Collections.singletonMap("spring.main.cloud-platform", "kubernetes")); + CloudPlatform platform = CloudPlatform.getActive(environment); + assertThat(platform).isEqualTo(CloudPlatform.KUBERNETES); + } + private Environment getEnvironmentWithEnvVariables(Map environmentVariables) { MockEnvironment environment = new MockEnvironment(); PropertySource propertySource = new SystemEnvironmentPropertySource(