Enable git remote linking automatically on CF

Closes gh-13586
pull/16219/head
Madhura Bhave 6 years ago
parent 55e5bafcfc
commit e8cb75bba8

@ -79,7 +79,7 @@ public class CloudFoundryWebEndpointDiscoverer extends WebEndpointDiscoverer {
private boolean isCloudFoundryHealthEndpointExtension(Object extensionBean) {
return AnnotatedElementUtils.hasAnnotation(extensionBean.getClass(),
HealthEndpointCloudFoundryExtension.class);
EndpointCloudFoundryExtension.class);
}
}

@ -22,12 +22,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
import org.springframework.boot.actuate.health.HealthEndpoint;
/**
* Identifies a type as being a Cloud Foundry specific extension for the
* {@link HealthEndpoint}.
* Identifies a type as being a Cloud Foundry specific extension for an {@link Endpoint}.
*
* @author Phillip Webb
* @since 2.0.0
@ -35,7 +34,9 @@ import org.springframework.boot.actuate.health.HealthEndpoint;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EndpointExtension(filter = CloudFoundryEndpointFilter.class, endpoint = HealthEndpoint.class)
public @interface HealthEndpointCloudFoundryExtension {
@EndpointExtension(filter = CloudFoundryEndpointFilter.class)
public @interface EndpointCloudFoundryExtension {
Class<?> endpoint();
}

@ -18,7 +18,7 @@ package org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive;
import reactor.core.publisher.Mono;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.HealthEndpointCloudFoundryExtension;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.EndpointCloudFoundryExtension;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
@ -34,7 +34,7 @@ import org.springframework.boot.actuate.health.ShowDetails;
* @author Madhura Bhave
* @since 2.0.0
*/
@HealthEndpointCloudFoundryExtension
@EndpointCloudFoundryExtension(endpoint = HealthEndpoint.class)
public class CloudFoundryReactiveHealthEndpointWebExtension {
private final ReactiveHealthEndpointWebExtension delegate;

@ -21,13 +21,16 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryWebEndpointDiscoverer;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryInfoEndpointWebExtension;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnExposedEndpoint;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
@ -37,6 +40,10 @@ import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
import org.springframework.boot.actuate.info.GitInfoContributor;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.boot.actuate.info.InfoEndpoint;
import org.springframework.boot.actuate.info.InfoPropertiesInfoContributor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@ -46,6 +53,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.info.GitProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -68,7 +76,8 @@ import org.springframework.web.server.WebFilter;
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "management.cloudfoundry", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter(HealthEndpointAutoConfiguration.class)
@AutoConfigureAfter({ HealthEndpointAutoConfiguration.class,
InfoEndpointAutoConfiguration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
public class ReactiveCloudFoundryActuatorAutoConfiguration {
@ -84,6 +93,25 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
reactiveHealthEndpointWebExtension);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
@ConditionalOnExposedEndpoint
@ConditionalOnBean({ InfoEndpoint.class, GitProperties.class })
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
InfoEndpoint infoEndpoint, GitProperties properties) {
List<InfoContributor> existingContributors = infoEndpoint.getInfoContributors();
List<InfoContributor> contributors = existingContributors.stream()
.map((infoContributor) -> {
if (infoContributor instanceof GitInfoContributor) {
return new GitInfoContributor(properties,
InfoPropertiesInfoContributor.Mode.FULL);
}
return infoContributor;
}).collect(Collectors.toList());
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
}
@Bean
public CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebFluxEndpointHandlerMapping(
ParameterValueMapper parameterMapper, EndpointMediaTypes endpointMediaTypes,

@ -21,11 +21,13 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryWebEndpointDiscoverer;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnExposedEndpoint;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
@ -37,6 +39,10 @@ import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpoi
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.HealthEndpointWebExtension;
import org.springframework.boot.actuate.info.GitInfoContributor;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.boot.actuate.info.InfoEndpoint;
import org.springframework.boot.actuate.info.InfoPropertiesInfoContributor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@ -47,6 +53,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.cloud.CloudPlatform;
import org.springframework.boot.info.GitProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@ -70,7 +77,7 @@ import org.springframework.web.servlet.DispatcherServlet;
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "management.cloudfoundry", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter({ ServletManagementContextAutoConfiguration.class,
HealthEndpointAutoConfiguration.class })
HealthEndpointAutoConfiguration.class, InfoEndpointAutoConfiguration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@ConditionalOnBean(DispatcherServlet.class)
@ -87,6 +94,25 @@ public class CloudFoundryActuatorAutoConfiguration {
return new CloudFoundryHealthEndpointWebExtension(healthEndpointWebExtension);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
@ConditionalOnExposedEndpoint
@ConditionalOnBean({ InfoEndpoint.class, GitProperties.class })
public CloudFoundryInfoEndpointWebExtension cloudFoundryInfoEndpointWebExtension(
InfoEndpoint infoEndpoint, GitProperties properties) {
List<InfoContributor> existingContributors = infoEndpoint.getInfoContributors();
List<InfoContributor> contributors = existingContributors.stream()
.map((infoContributor) -> {
if (infoContributor instanceof GitInfoContributor) {
return new GitInfoContributor(properties,
InfoPropertiesInfoContributor.Mode.FULL);
}
return infoContributor;
}).collect(Collectors.toList());
return new CloudFoundryInfoEndpointWebExtension(new InfoEndpoint(contributors));
}
@Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
ParameterValueMapper parameterMapper, EndpointMediaTypes endpointMediaTypes,

@ -16,7 +16,7 @@
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.HealthEndpointCloudFoundryExtension;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.EndpointCloudFoundryExtension;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;
@ -32,7 +32,7 @@ import org.springframework.boot.actuate.health.ShowDetails;
* @author Madhura Bhave
* @since 2.0.0
*/
@HealthEndpointCloudFoundryExtension
@EndpointCloudFoundryExtension(endpoint = HealthEndpoint.class)
public class CloudFoundryHealthEndpointWebExtension {
private final HealthEndpointWebExtension delegate;

@ -0,0 +1,46 @@
/*
* Copyright 2012-2019 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.
*/
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet;
import java.util.Map;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.EndpointCloudFoundryExtension;
import org.springframework.boot.actuate.endpoint.annotation.EndpointExtension;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.info.InfoEndpoint;
/**
* {@link EndpointExtension} for the {@link InfoEndpoint} that always exposes full git
* details.
*
* @author Madhura Bhave
* @since 2.2.0
*/
@EndpointCloudFoundryExtension(endpoint = InfoEndpoint.class)
public class CloudFoundryInfoEndpointWebExtension {
private final InfoEndpoint delegate;
public CloudFoundryInfoEndpointWebExtension(InfoEndpoint delegate) {
this.delegate = delegate;
}
@ReadOperation
public Map<String, Object> info() {
return this.delegate.info();
}
}

@ -162,7 +162,7 @@ public class CloudFoundryWebEndpointDiscovererTests {
}
@HealthEndpointCloudFoundryExtension
@EndpointCloudFoundryExtension(endpoint = HealthEndpoint.class)
static class TestHealthEndpointCloudFoundryExtension {
@ReadOperation

@ -20,6 +20,7 @@ import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.net.ssl.SSLException;
@ -28,10 +29,13 @@ import org.junit.After;
import org.junit.Test;
import reactor.netty.http.HttpResources;
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryInfoEndpointWebExtension;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
@ -44,6 +48,7 @@ import org.springframework.boot.actuate.endpoint.web.WebOperation;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration;
@ -87,6 +92,9 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
InfoContributorAutoConfiguration.class,
InfoEndpointAutoConfiguration.class,
ProjectInfoAutoConfiguration.class,
ReactiveCloudFoundryActuatorAutoConfiguration.class));
@After
@ -295,6 +303,18 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
});
}
@Test
@SuppressWarnings("unchecked")
public void gitFullDetailsAlwaysPresent() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---").run((context) -> {
CloudFoundryInfoEndpointWebExtension extension = context
.getBean(CloudFoundryInfoEndpointWebExtension.class);
Map<String, Object> git = (Map<String, Object>) extension.info().get("git");
Map<String, Object> commit = (Map<String, Object>) git.get("commit");
assertThat(commit).hasSize(4);
});
}
@Test
public void skipSslValidation() {
this.contextRunner

@ -0,0 +1,84 @@
/*
* Copyright 2012-2019 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.
*/
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet;
import java.util.Map;
import org.junit.Test;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CloudFoundryInfoEndpointWebExtension}.
*
* @author Madhura Bhave
*/
public class CloudFoundryInfoEndpointWebExtensionTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withPropertyValues("VCAP_APPLICATION={}")
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
RestTemplateAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ProjectInfoAutoConfiguration.class,
InfoContributorAutoConfiguration.class,
InfoEndpointAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
CloudFoundryActuatorAutoConfiguration.class));
@Test
@SuppressWarnings("unchecked")
public void gitFullDetailsAlwaysPresent() {
this.contextRunner
.withInitializer(
new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
.run((context) -> {
CloudFoundryInfoEndpointWebExtension extension = context
.getBean(CloudFoundryInfoEndpointWebExtension.class);
Map<String, Object> git = (Map<String, Object>) extension.info()
.get("git");
Map<String, Object> commit = (Map<String, Object>) git.get("commit");
assertThat(commit).hasSize(4);
});
}
}

@ -55,4 +55,8 @@ public class InfoEndpoint {
return build.getDetails();
}
public List<InfoContributor> getInfoContributors() {
return this.infoContributors;
}
}

Loading…
Cancel
Save