Skip to content

Commit

Permalink
Allow applications using quakus-info to contribute data to the /info …
Browse files Browse the repository at this point in the history
…at runtime
  • Loading branch information
jtama committed Jan 8, 2024
1 parent e87a492 commit 9453a08
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 10 deletions.
2 changes: 2 additions & 0 deletions docs/src/main/asciidoc/getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ but users can also choose to expose one that might present a security risk under

If the application contains the `quarkus-info` extension, then Quarkus will by default expose the `/q/info` endpoint which provides information about the build, java version, version control, and operating system. The level of detail of the exposed information is configurable.

Check warning on line 482 in docs/src/main/asciidoc/getting-started.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using ', which (non restrictive clause preceded by a comma)' or 'that (restrictive clause without a comma)' rather than 'which'.", "location": {"path": "docs/src/main/asciidoc/getting-started.adoc", "range": {"start": {"line": 482, "column": 117}}}, "severity": "INFO"}

All CDI beans implementing the `InfoContributor` will be picked up and their data will be append to the endpoint.

==== Configuration Reference

Check warning on line 486 in docs/src/main/asciidoc/getting-started.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.HeadingPunctuation] Do not use end punctuation in headings. Raw Output: {"message": "[Quarkus.HeadingPunctuation] Do not use end punctuation in headings.", "location": {"path": "docs/src/main/asciidoc/getting-started.adoc", "range": {"start": {"line": 486, "column": 1}}}, "severity": "INFO"}

Check warning on line 486 in docs/src/main/asciidoc/getting-started.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Headings] Use sentence-style capitalization in '12.1.1. Configuration Reference'. Raw Output: {"message": "[Quarkus.Headings] Use sentence-style capitalization in '12.1.1. Configuration Reference'.", "location": {"path": "docs/src/main/asciidoc/getting-started.adoc", "range": {"start": {"line": 486, "column": 1}}}, "severity": "INFO"}

include::{generated-dir}/config/quarkus-info.adoc[opts=optional, leveloffset=+2]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.jboss.logging.Logger;

import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.workspace.WorkspaceModule;
import io.quarkus.builder.Version;
Expand Down Expand Up @@ -274,13 +275,15 @@ RouteBuildItem defineRoute(InfoBuildTimeConfig buildTimeConfig,
List<InfoBuildTimeValuesBuildItem> buildTimeValues,
List<InfoBuildTimeContributorBuildItem> contributors,
NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
BuildProducer<UnremovableBeanBuildItem> unremovableBeanBuildItemBuildProducer,
InfoRecorder recorder) {
Map<String, Object> buildTimeInfo = buildTimeValues.stream().collect(
Collectors.toMap(InfoBuildTimeValuesBuildItem::getName, InfoBuildTimeValuesBuildItem::getValue, (x, y) -> y,
LinkedHashMap::new));
List<InfoContributor> infoContributors = contributors.stream()
.map(InfoBuildTimeContributorBuildItem::getInfoContributor)
.collect(Collectors.toList());
unremovableBeanBuildItemBuildProducer.produce(UnremovableBeanBuildItem.beanTypes(InfoContributor.class));
return nonApplicationRootPathBuildItem.routeBuilder()
.management()
.route(buildTimeConfig.path())
Expand Down
48 changes: 38 additions & 10 deletions extensions/info/deployment/src/main/resources/dev-ui/qwc-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class QwcInfo extends LitElement {
super.connectedCallback();
await this.load();
}

async load() {
const response = await fetch(this._infoUrl);
const data = await response.json();
Expand All @@ -68,6 +68,7 @@ export class QwcInfo extends LitElement {
${this._renderJavaInfo(this._info)}
${this._renderBuildInfo(this._info)}
${this._renderGitInfo(this._info)}
${this._renderExternalContributedInfo(this._info)}
`;
}else{
return html`
Expand All @@ -78,7 +79,7 @@ export class QwcInfo extends LitElement {
`;
}
}

_renderOsInfo(info){
if(info.os){
let os = info.os;
Expand All @@ -94,7 +95,7 @@ export class QwcInfo extends LitElement {
</qui-card>`;
}
}

_renderJavaInfo(info){
if(info.java){
let java = info.java;
Expand All @@ -108,9 +109,9 @@ export class QwcInfo extends LitElement {
</qui-card>`;
}
}

_renderOsIcon(osname){

if(osname){
if(osname.toLowerCase().startsWith("linux")){
return html`<vaadin-icon icon="font-awesome-brands:linux"></vaadin-icon>`;
Expand All @@ -121,7 +122,7 @@ export class QwcInfo extends LitElement {
}
}
}

_renderGitInfo(info){
if(info.git){
let git = info.git;
Expand All @@ -138,26 +139,26 @@ export class QwcInfo extends LitElement {
</qui-card>`;
}
}

_renderCommitId(git){
if(typeof git.commit.id === "string"){
return html`${git.commit.id}`;
}else {
return html`${git.commit.id.full}`;
}
}

_renderOptionalData(git){
if(typeof git.commit.id !== "string"){
return html`<tr><td class="row-header">Commit User</td><td>${git.commit.user.name} &lt;${git.commit.user.email}&gt;</td></tr>
<tr><td class="row-header">Commit Message</td><td>${unsafeHTML(this._replaceNewLine(git.commit.id.message.full))}</td></tr>`
}
}

_replaceNewLine(line){
return line.replace(new RegExp('\r?\n','g'), '<br />');
}

_renderBuildInfo(info){
if(info.build){
let build = info.build;
Expand All @@ -173,5 +174,32 @@ export class QwcInfo extends LitElement {
</qui-card>`;
}
}

_renderExternalContributedInfo(info){
const externalConstributors = Object.keys(info)
.filter(key => key !== 'build')
.filter(key => key !== 'os')
.filter(key => key !== 'git')
.filter(key => key !== 'java')
if(externalConstributors.length > 0){
const cards = [];
externalConstributors.map(key => {
const extInfo = info[key];
const rows = [];
for (const property of Object.keys(extInfo)){
rows.push(html`<tr><td class="row-header">${property}</td><td>${extInfo[property]}</td></tr>`);
}
cards.push(html`<qui-card title=${key}>
<div class="cardContent" slot="content">
<vaadin-icon icon="font-awesome-solid:circle-info"></vaadin-icon>
<table class="table">
${rows}
</table>
</div>
</qui-card>`);
})
return html`${cards}`;
}
}
}
customElements.define('qwc-info', QwcInfo);
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkus.info.deployment;

import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;

import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.info.runtime.spi.InfoContributor;
import io.quarkus.test.QuarkusUnitTest;

public class ExternalInfoContributorTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.addBuildChainCustomizer(
buildChainBuilder -> buildChainBuilder.addBuildStep(
context -> new AdditionalBeanBuildItem(TestInfoContributor.class))
.produces(AdditionalBeanBuildItem.class)
.build())
.withApplicationRoot((jar) -> jar
.addClasses(TestInfoContributor.class));

@Test
public void test() {
when().get("/q/info")
.then()
.statusCode(200)
.body("os", is(notNullValue()))
.body("os.name", is(notNullValue()))
.body("java", is(notNullValue()))
.body("java.version", is(notNullValue()))
.body("build", is(notNullValue()))
.body("build.time", is(notNullValue()))
.body("git", is(notNullValue()))
.body("git.branch", is(notNullValue()))
.body("test", is(notNullValue()))
.body("test.foo", is("bar"));

}

@ApplicationScoped
public static class TestInfoContributor implements InfoContributor {

@Override
public String name() {
return "test";
}

@Override
public Map<String, Object> data() {
return Map.of("foo", "bar");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.util.Map;
import java.util.function.Supplier;

import io.quarkus.arc.Arc;
import io.quarkus.arc.InstanceHandle;
import io.quarkus.info.BuildInfo;
import io.quarkus.info.GitInfo;
import io.quarkus.info.JavaInfo;
Expand Down Expand Up @@ -143,6 +145,10 @@ public InfoHandler(Map<String, Object> buildTimeInfo, List<InfoContributor> know
// also, do we want to merge information or simply replace like we are doing here?
finalBuildInfo.put(contributor.name(), contributor.data());
}
for (InstanceHandle<InfoContributor> handler : Arc.container().listAll(InfoContributor.class)) {
InfoContributor contributor = handler.get();
finalBuildInfo.put(contributor.name(), contributor.data());
}
}

@Override
Expand Down

0 comments on commit 9453a08

Please sign in to comment.