Commit ffc2cff8 authored by Brian Clozel's avatar Brian Clozel

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
parent f4c68dbc
...@@ -23,22 +23,36 @@ import org.springframework.core.env.PropertySource; ...@@ -23,22 +23,36 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
/** /**
* Simple detection for well known cloud platforms. For more advanced cloud provider * Simple detection for well known cloud platforms. Detection can be forced using the
* integration consider the Spring Cloud project. * {@code "spring.main.cloud-platform"} configuration property. For more advanced cloud
* provider integration consider the Spring Cloud project.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Brian Clozel
* @since 1.3.0 * @since 1.3.0
* @see "https://cloud.spring.io" * @see "https://spring.io/projects/spring-cloud"
*/ */
public enum CloudPlatform { 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 platform.
*/ */
CLOUD_FOUNDRY { CLOUD_FOUNDRY {
@Override @Override
public boolean isActive(Environment environment) { public boolean isAutoDetected(Environment environment) {
return environment.containsProperty("VCAP_APPLICATION") || environment.containsProperty("VCAP_SERVICES"); return environment.containsProperty("VCAP_APPLICATION") || environment.containsProperty("VCAP_SERVICES");
} }
...@@ -50,7 +64,7 @@ public enum CloudPlatform { ...@@ -50,7 +64,7 @@ public enum CloudPlatform {
HEROKU { HEROKU {
@Override @Override
public boolean isActive(Environment environment) { public boolean isAutoDetected(Environment environment) {
return environment.containsProperty("DYNO"); return environment.containsProperty("DYNO");
} }
...@@ -62,7 +76,7 @@ public enum CloudPlatform { ...@@ -62,7 +76,7 @@ public enum CloudPlatform {
SAP { SAP {
@Override @Override
public boolean isActive(Environment environment) { public boolean isAutoDetected(Environment environment) {
return environment.containsProperty("HC_LANDSCAPE"); return environment.containsProperty("HC_LANDSCAPE");
} }
...@@ -82,14 +96,14 @@ public enum CloudPlatform { ...@@ -82,14 +96,14 @@ public enum CloudPlatform {
private static final String SERVICE_PORT_SUFFIX = "_SERVICE_PORT"; private static final String SERVICE_PORT_SUFFIX = "_SERVICE_PORT";
@Override @Override
public boolean isActive(Environment environment) { public boolean isAutoDetected(Environment environment) {
if (environment instanceof ConfigurableEnvironment) { if (environment instanceof ConfigurableEnvironment) {
return isActive((ConfigurableEnvironment) environment); return isAutoDetected((ConfigurableEnvironment) environment);
} }
return false; return false;
} }
private boolean isActive(ConfigurableEnvironment environment) { private boolean isAutoDetected(ConfigurableEnvironment environment) {
PropertySource<?> environmentPropertySource = environment.getPropertySources() PropertySource<?> environmentPropertySource = environment.getPropertySources()
.get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
if (environmentPropertySource != null) { if (environmentPropertySource != null) {
...@@ -98,13 +112,13 @@ public enum CloudPlatform { ...@@ -98,13 +112,13 @@ public enum CloudPlatform {
return true; return true;
} }
if (environmentPropertySource instanceof EnumerablePropertySource) { if (environmentPropertySource instanceof EnumerablePropertySource) {
return isActive((EnumerablePropertySource<?>) environmentPropertySource); return isAutoDetected((EnumerablePropertySource<?>) environmentPropertySource);
} }
} }
return false; return false;
} }
private boolean isActive(EnumerablePropertySource<?> environmentPropertySource) { private boolean isAutoDetected(EnumerablePropertySource<?> environmentPropertySource) {
for (String propertyName : environmentPropertySource.getPropertyNames()) { for (String propertyName : environmentPropertySource.getPropertyNames()) {
if (propertyName.endsWith(SERVICE_HOST_SUFFIX)) { if (propertyName.endsWith(SERVICE_HOST_SUFFIX)) {
String serviceName = propertyName.substring(0, String serviceName = propertyName.substring(0,
...@@ -124,7 +138,31 @@ public enum CloudPlatform { ...@@ -124,7 +138,31 @@ public enum CloudPlatform {
* @param environment the environment * @param environment the environment
* @return if the platform is active. * @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 * Returns if the platform is behind a load balancer and uses
......
...@@ -640,6 +640,11 @@ ...@@ -640,6 +640,11 @@
"description": "Mode used to display the banner when the application runs.", "description": "Mode used to display the banner when the application runs.",
"defaultValue": "console" "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", "name": "spring.main.lazy-initialization",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",
......
...@@ -129,6 +129,14 @@ class CloudPlatformTests { ...@@ -129,6 +129,14 @@ class CloudPlatformTests {
assertThat(platform).isNull(); 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<String, Object> environmentVariables) { private Environment getEnvironmentWithEnvVariables(Map<String, Object> environmentVariables) {
MockEnvironment environment = new MockEnvironment(); MockEnvironment environment = new MockEnvironment();
PropertySource<?> propertySource = new SystemEnvironmentPropertySource( PropertySource<?> propertySource = new SystemEnvironmentPropertySource(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment