Polish info contributor feature
This commit improves the `InfoContributor` infrastructure as follows: * `InfoEndpoint` no longer breaks its public API and returns a Map as before * `Info` is now immutable * All properties of the build are now displayed. Since we control the generation of that file, there is no longer a mode to restrict what's shown * Build info is now generated in `META-INF/build-info.properties` by default Closes gh-5734
This commit is contained in:
@@ -82,8 +82,7 @@ public class InfoContributorAutoConfiguration {
|
||||
@ConditionalOnSingleCandidate(BuildProperties.class)
|
||||
@Order(DEFAULT_ORDER)
|
||||
public InfoContributor buildInfoContributor(BuildProperties buildProperties) {
|
||||
return new BuildInfoContributor(buildProperties,
|
||||
this.properties.getBuild().getMode());
|
||||
return new BuildInfoContributor(buildProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import org.springframework.boot.actuate.info.BuildInfoContributor;
|
||||
import org.springframework.boot.actuate.info.GitInfoContributor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@@ -29,34 +28,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties("management.info")
|
||||
public class InfoContributorProperties {
|
||||
|
||||
private final Build build = new Build();
|
||||
|
||||
private final Git git = new Git();
|
||||
|
||||
public Build getBuild() {
|
||||
return this.build;
|
||||
}
|
||||
|
||||
public Git getGit() {
|
||||
return this.git;
|
||||
}
|
||||
|
||||
public static class Build {
|
||||
|
||||
/**
|
||||
* Mode to use to expose build information.
|
||||
*/
|
||||
private BuildInfoContributor.Mode mode = BuildInfoContributor.Mode.SIMPLE;
|
||||
|
||||
public BuildInfoContributor.Mode getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
public void setMode(BuildInfoContributor.Mode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Git {
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.Assert;
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.info")
|
||||
public class InfoEndpoint extends AbstractEndpoint<Info> {
|
||||
public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private final List<InfoContributor> infoContributors;
|
||||
|
||||
@@ -48,13 +48,14 @@ public class InfoEndpoint extends AbstractEndpoint<Info> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Info invoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
Info.Builder builder = new Info.Builder();
|
||||
for (InfoContributor contributor : this.infoContributors) {
|
||||
contributor.contribute(builder);
|
||||
}
|
||||
builder.withDetails(getAdditionalInfo());
|
||||
return builder.build();
|
||||
Info build = builder.build();
|
||||
return build.getDetails();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,12 +31,8 @@ import org.springframework.core.env.PropertySource;
|
||||
*/
|
||||
public class BuildInfoContributor extends InfoPropertiesInfoContributor<BuildProperties> {
|
||||
|
||||
public BuildInfoContributor(BuildProperties properties, Mode mode) {
|
||||
super(properties, mode);
|
||||
}
|
||||
|
||||
public BuildInfoContributor(BuildProperties properties) {
|
||||
this(properties, Mode.SIMPLE);
|
||||
super(properties, Mode.FULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.actuate.info;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -39,8 +40,9 @@ public final class Info {
|
||||
private final Map<String, Object> details;
|
||||
|
||||
private Info(Builder builder) {
|
||||
this.details = new LinkedHashMap<String, Object>();
|
||||
this.details.putAll(builder.content);
|
||||
LinkedHashMap<String, Object> content = new LinkedHashMap<String, Object>();
|
||||
content.putAll(builder.content);
|
||||
this.details = Collections.unmodifiableMap(content);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -187,7 +187,7 @@ public class EndpointAutoConfigurationTests {
|
||||
this.context.refresh();
|
||||
|
||||
InfoEndpoint endpoint = this.context.getBean(InfoEndpoint.class);
|
||||
Info info = endpoint.invoke();
|
||||
Map<String, Object> info = endpoint.invoke();
|
||||
assertThat(info).isNotNull();
|
||||
assertThat(info.get("name")).isEqualTo("foo");
|
||||
assertThat(info.get("version")).isEqualTo("1.0");
|
||||
|
||||
@@ -115,7 +115,7 @@ public class InfoContributorAutoConfigurationTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void buildPropertiesDefaultMode() {
|
||||
public void buildProperties() {
|
||||
load(BuildPropertiesConfiguration.class);
|
||||
Map<String, InfoContributor> beans = this.context
|
||||
.getBeansOfType(InfoContributor.class);
|
||||
@@ -125,18 +125,6 @@ public class InfoContributorAutoConfigurationTests {
|
||||
Object build = content.get("build");
|
||||
assertThat(build).isInstanceOf(Map.class);
|
||||
Map<String, Object> buildInfo = (Map<String, Object>) build;
|
||||
assertThat(buildInfo).containsOnlyKeys("group", "artifact");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void buildPropertiesFullMode() {
|
||||
load(BuildPropertiesConfiguration.class, "management.info.build.mode=full");
|
||||
Map<String, Object> content = invokeContributor(
|
||||
this.context.getBean("buildInfoContributor", InfoContributor.class));
|
||||
Object build = content.get("build");
|
||||
assertThat(build).isInstanceOf(Map.class);
|
||||
Map<String, Object> buildInfo = (Map<String, Object>) build;
|
||||
assertThat(buildInfo).containsOnlyKeys("group", "artifact", "foo");
|
||||
assertThat(buildInfo.get("foo")).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -43,7 +44,7 @@ public class InfoEndpointTests extends AbstractEndpointTests<InfoEndpoint> {
|
||||
|
||||
@Test
|
||||
public void invoke() throws Exception {
|
||||
Info actual = getEndpointBean().invoke();
|
||||
Map<String, Object> actual = getEndpointBean().invoke();
|
||||
assertThat(actual.get("key1")).isEqualTo("value1");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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.info;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Tests for {@link Info}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class InfoTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void infoIsImmutable() {
|
||||
Info info = new Info.Builder().withDetail("foo", "bar").build();
|
||||
|
||||
this.thrown.expect(UnsupportedOperationException.class);
|
||||
info.getDetails().clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void infoTakesCopyOfMap() {
|
||||
Info.Builder builder = new Info.Builder();
|
||||
builder.withDetail("foo", "bar");
|
||||
Info build = builder.build();
|
||||
builder.withDetail("biz", "bar");
|
||||
assertThat(build.getDetails()).containsOnly(entry("foo", "bar"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class ProjectInfoAutoConfiguration {
|
||||
return new GitProperties(loadFrom(this.properties.getGit().getLocation(), "git"));
|
||||
}
|
||||
|
||||
@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/boot/build.properties}")
|
||||
@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
|
||||
@ConditionalOnMissingBean
|
||||
@Bean
|
||||
public BuildProperties buildProperties() throws Exception {
|
||||
|
||||
@@ -59,10 +59,10 @@ public class ProjectInfoProperties {
|
||||
public static class Build {
|
||||
|
||||
/**
|
||||
* Location of the generated build.properties file.
|
||||
* Location of the generated build-info.properties file.
|
||||
*/
|
||||
private Resource location = new ClassPathResource(
|
||||
"META-INF/boot/build.properties");
|
||||
"META-INF/build-info.properties");
|
||||
|
||||
public Resource getLocation() {
|
||||
return this.location;
|
||||
|
||||
@@ -105,7 +105,7 @@ public class ProjectInfoAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void buildPropertiesCustomLocation() {
|
||||
load("spring.info.build.location=classpath:/org/springframework/boot/autoconfigure/info/build.properties");
|
||||
load("spring.info.build.location=classpath:/org/springframework/boot/autoconfigure/info/build-info.properties");
|
||||
BuildProperties buildProperties = this.context.getBean(BuildProperties.class);
|
||||
assertThat(buildProperties.getGroup()).isEqualTo("com.example.acme");
|
||||
assertThat(buildProperties.getArtifact()).isEqualTo("acme");
|
||||
@@ -116,7 +116,7 @@ public class ProjectInfoAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void buildPropertiesCustomInvalidLocation() {
|
||||
load("spring.info.build.location=classpath:/org/acme/no-build.properties");
|
||||
load("spring.info.build.location=classpath:/org/acme/no-build-info.properties");
|
||||
Map<String, BuildProperties> beans = this.context
|
||||
.getBeansOfType(BuildProperties.class);
|
||||
assertThat(beans).hasSize(0);
|
||||
|
||||
@@ -86,7 +86,7 @@ content into your application; rather pick only the properties that you need.
|
||||
spring.hazelcast.config= # The location of the configuration file to use to initialize Hazelcast.
|
||||
|
||||
# PROJECT INFORMATION ({sc-spring-boot-autoconfigure}/info/ProjectInfoProperties.{sc-ext}[ProjectInfoProperties])
|
||||
spring.info.build.location=classpath:META-INF/boot/build.properties # Location of the generated build.properties file.
|
||||
spring.info.build.location=classpath:META-INF/build-info.properties # Location of the generated build-info.properties file.
|
||||
spring.info.git.location=classpath:git.properties # Location of the generated git.properties file.
|
||||
|
||||
# JMX
|
||||
@@ -1015,7 +1015,6 @@ content into your application; rather pick only the properties that you need.
|
||||
|
||||
# INFO CONTRIBUTORS ({sc-spring-boot-actuator}/autoconfigure/InfoContributorProperties.{sc-ext}[InfoContributorProperties])
|
||||
management.info.build.enabled=true # Enable build info.
|
||||
management.info.build.mode=simple # Mode to use to expose build information.
|
||||
management.info.defaults.enabled=true # Enable default info contributors.
|
||||
management.info.env.enabled=true # Enable environment info.
|
||||
management.info.git.enabled=true # Enable git info.
|
||||
|
||||
@@ -393,7 +393,7 @@ The following `InfoContributors` are auto-configured by Spring Boot when appropr
|
||||
|Expose git information if a `git.properties` file is available.
|
||||
|
||||
|{sc-spring-boot-actuator}/info/BuildInfoContributor.{sc-ext}[`BuildInfoContributor`]
|
||||
|Expose build information if a `META-INF/boot/build.properties` file is available.
|
||||
|Expose build information if a `META-INF/build-info.properties` file is available.
|
||||
|===
|
||||
|
||||
TIP: It is possible to disable them all using the `management.info.defaults.enabled`
|
||||
@@ -453,19 +453,12 @@ If you want to display the full git information (i.e. the full content of
|
||||
[[production-ready-application-info-build]]
|
||||
==== Build information
|
||||
The `info` endpoint can also publish information about your build if a `BuildProperties`
|
||||
bean is available. This happens if a `META-INF/boot/build.properties` file is available
|
||||
bean is available. This happens if a `META-INF/build-info.properties` file is available
|
||||
in the classpath.
|
||||
|
||||
TIP: The Maven and Gradle plugins can both generate that file, see
|
||||
<<howto.adoc#howto-build-info,Generate build information>> for more details.
|
||||
|
||||
If additional properties are present they are not exposed unless configured explicitly:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
management.info.build.mode=full
|
||||
----
|
||||
|
||||
|
||||
[[production-ready-application-info-custom]]
|
||||
==== Writing custom InfoContributors
|
||||
|
||||
@@ -34,11 +34,11 @@ import org.springframework.boot.loader.tools.BuildPropertiesWriter;
|
||||
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
|
||||
|
||||
/**
|
||||
* {@link DefaultTask} for generating a {@code build.properties} file from a
|
||||
* {@link DefaultTask} for generating a {@code build-info.properties} file from a
|
||||
* {@code Project}.
|
||||
* <p>
|
||||
* By default, the {@code build.properties} file is generated in
|
||||
* project.buildDir/resources/main/META-INF/boot.
|
||||
* By default, the {@code build-info.properties} file is generated in
|
||||
* project.buildDir/resources/main/META-INF.
|
||||
* </p>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
@@ -47,7 +47,7 @@ public class BuildInfo extends DefaultTask {
|
||||
|
||||
@OutputFile
|
||||
private File outputFile = getProject().file(new File(getProject().getBuildDir(),
|
||||
"resources/main/META-INF/boot/build.properties"));
|
||||
"resources/main/META-INF/build-info.properties"));
|
||||
|
||||
@Input
|
||||
private String projectGroup = getProject().getGroup().toString();
|
||||
|
||||
@@ -25,8 +25,8 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@code BuildPropertiesWriter} writes the {@code build.properties} for consumption by
|
||||
* the Actuator.
|
||||
* A {@code BuildPropertiesWriter} writes the {@code build-info.properties} for
|
||||
* consumption by the Actuator.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Stephane Nicoll
|
||||
|
||||
@@ -3,7 +3,7 @@ import org.springframework.boot.maven.Verify
|
||||
import static org.junit.Assert.assertEquals
|
||||
import static org.junit.Assert.assertTrue
|
||||
|
||||
def file = new File(basedir, "target/classes/META-INF/boot/build.properties")
|
||||
def file = new File(basedir, "target/classes/META-INF/build-info.properties")
|
||||
println file.getAbsolutePath()
|
||||
Properties properties = Verify.verifyBuildInfo(file,
|
||||
'org.springframework.boot.maven.it', 'build-info-additional-properties',
|
||||
|
||||
@@ -2,7 +2,7 @@ import org.springframework.boot.maven.Verify
|
||||
|
||||
import static org.junit.Assert.assertTrue
|
||||
|
||||
def file = new File(basedir, "target/classes/META-INF/boot/build.properties")
|
||||
def file = new File(basedir, "target/classes/META-INF/build-info.properties")
|
||||
println file.getAbsolutePath()
|
||||
Properties properties = Verify.verifyBuildInfo(file,
|
||||
'org.springframework.boot.maven.it', 'build-info',
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.boot.loader.tools.BuildPropertiesWriter;
|
||||
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
|
||||
|
||||
/**
|
||||
* Generate a {@code build.properties} file based the content of the current
|
||||
* Generate a {@code build-info.properties} file based the content of the current
|
||||
* {@link MavenProject}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
@@ -47,14 +47,14 @@ public class BuildInfoMojo extends AbstractMojo {
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* The location of the generated build.properties.
|
||||
* The location of the generated build-info.properties.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}/META-INF/boot/build.properties")
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}/META-INF/build-info.properties")
|
||||
private File outputFile;
|
||||
|
||||
/**
|
||||
* Additional properties to store in the build.properties. Each entry is prefixed by
|
||||
* {@code build.} in the generated build.properties.
|
||||
* Additional properties to store in the build-info.properties. Each entry is prefixed by
|
||||
* {@code build.} in the generated build-info.properties.
|
||||
*/
|
||||
@Parameter
|
||||
private Map<String, String> additionalProperties;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
2016-03-17
|
||||
-----
|
||||
|
||||
Spring Boot Actuator displays build-related information if a <<<META-INF/boot/build.properties>>>
|
||||
Spring Boot Actuator displays build-related information if a <<<META-INF/build-info.properties>>>
|
||||
file is present. The <<<build-info>>> goal generates such file with the coordinates of the project
|
||||
and the build time. It also allows you to add an arbitrary number of additional properties:
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
</project>
|
||||
---
|
||||
|
||||
This configuration will generate a <<<build.properties>>> at the expected location with four
|
||||
additional keys. Note that <<<maven.compiler.source>>> and <<<maven.compiler.target>>> are
|
||||
expected to be regular properties available in the project. They will be interpolated as you
|
||||
would expect.
|
||||
This configuration will generate a <<<build-info.properties>>> at the expected location with
|
||||
four additional keys. Note that <<<maven.compiler.source>>> and <<<maven.compiler.target>>>
|
||||
are expected to be regular properties available in the project. They will be interpolated as
|
||||
you would expect.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user