Skip to content

Commit 648fd77

Browse files
authored
Merge pull request wildfly#18837 from jasondlee/WFLY-20482
WFLY-20482 - Improve context name conflict handling with Metrics and Micrometer
2 parents 7280ec1 + 2329ecb commit 648fd77

File tree

4 files changed

+166
-13
lines changed

4 files changed

+166
-13
lines changed

metrics/src/main/java/org/wildfly/extension/metrics/MetricsContextService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*/
2929
public class MetricsContextService implements Service {
3030

31-
private static final String CONTEXT_NAME = "/metrics";
31+
static final String CONTEXT_NAME = "/metrics";
3232

3333
private final Consumer<MetricsContextService> consumer;
3434
private final Supplier<ExtensibleHttpManagement> extensibleHttpManagement;

metrics/src/main/java/org/wildfly/extension/metrics/MetricsSubsystemAdd.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.jboss.as.controller.OperationContext;
2424
import org.jboss.as.controller.OperationFailedException;
2525
import org.jboss.as.controller.OperationStepHandler;
26+
import org.jboss.as.controller.capability.RuntimeCapability;
2627
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
2728
import org.jboss.as.controller.registry.Resource;
2829
import org.jboss.as.server.AbstractDeploymentChainStep;
@@ -45,6 +46,16 @@ class MetricsSubsystemAdd extends AbstractBoottimeAddStepHandler {
4546

4647
static final MetricsSubsystemAdd INSTANCE = new MetricsSubsystemAdd();
4748

49+
@Override
50+
protected void recordCapabilitiesAndRequirements(OperationContext operationContext, ModelNode operation, Resource resource) throws OperationFailedException {
51+
super.recordCapabilitiesAndRequirements(operationContext, operation, resource);
52+
53+
operationContext.registerCapability(
54+
RuntimeCapability.Builder.of("org.wildfly.management.context", true).build()
55+
.fromBaseCapability(MetricsContextService.CONTEXT_NAME.substring(1))
56+
);
57+
}
58+
4859
@Override
4960
protected void performBoottime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
5061
super.performBoottime(context, operation, model);

observability/micrometer/src/main/java/org/wildfly/extension/micrometer/prometheus/PrometheusRegistryDefinitionRegistrar.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
import org.jboss.as.controller.OperationContext;
1313
import org.jboss.as.controller.OperationFailedException;
1414
import org.jboss.as.controller.OperationStepHandler;
15+
import org.jboss.as.controller.PathAddress;
1516
import org.jboss.as.controller.PathElement;
1617
import org.jboss.as.controller.ResourceDefinition;
1718
import org.jboss.as.controller.ResourceRegistration;
1819
import org.jboss.as.controller.SimpleAttributeDefinition;
1920
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
21+
import org.jboss.as.controller.capability.RuntimeCapability;
22+
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
2023
import org.jboss.as.controller.registry.ManagementResourceRegistration;
2124
import org.jboss.as.controller.registry.RuntimePackageDependency;
2225
import org.jboss.as.server.mgmt.domain.ExtensibleHttpManagement;
@@ -71,19 +74,9 @@ public ManagementResourceRegistration register(ManagementResourceRegistration pa
7174

7275
ResourceDescriptor description = ResourceDescriptor.builder(MicrometerSubsystemRegistrar.RESOLVER.createChildResolver(PATH))
7376
.addAttributes(ATTRIBUTES)
77+
.withOperationTransformation(ModelDescriptionConstants.ADD, new AddHandler())
7478
.withRuntimeHandler(ResourceOperationRuntimeHandler.configureService(this))
75-
.withOperationTransformation("add", new UnaryOperator<OperationStepHandler>() {
76-
@Override
77-
public OperationStepHandler apply(OperationStepHandler handler) {
78-
return (context, operation) -> {
79-
if (context.getProcessType().isHostController()) {
80-
throw MicrometerExtensionLogger.MICROMETER_LOGGER.prometheusNotSupportedOnHostControllers();
81-
}
82-
handler.execute(context, operation);
83-
};
84-
}
85-
})
86-
.build();
79+
.build();
8780
ManagementResourceRegistration resourceRegistration = parent.registerSubModel(
8881
ResourceDefinition.builder(RESOURCE_REGISTRATION, description.getResourceDescriptionResolver()).build());
8982
if (resourceRegistration != null) {
@@ -112,4 +105,29 @@ public ResourceServiceInstaller configure(OperationContext context, ModelNode mo
112105
.asActive()
113106
.build();
114107
}
108+
109+
private static class AddHandler implements UnaryOperator<OperationStepHandler> {
110+
@Override
111+
public OperationStepHandler apply(OperationStepHandler operationStepHandler) {
112+
return (operationContext, operation) -> {
113+
if (operationContext.getProcessType().isHostController()) {
114+
throw MicrometerExtensionLogger.MICROMETER_LOGGER.prometheusNotSupportedOnHostControllers();
115+
}
116+
operationStepHandler.execute(operationContext, operation);
117+
118+
ModelNode model = operationContext.readResource(PathAddress.EMPTY_ADDRESS, false).getModel();
119+
String context = CONTEXT.resolveModelAttribute(operationContext, model).asString();
120+
121+
if (context.startsWith("/")) {
122+
context = context.substring(1);
123+
}
124+
125+
operationContext.registerCapability(
126+
RuntimeCapability.Builder.of("org.wildfly.management.context", true).build()
127+
.fromBaseCapability(context)
128+
);
129+
130+
};
131+
}
132+
}
115133
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright The WildFly Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
package org.wildfly.test.integration.observability.micrometer;
6+
7+
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
8+
import static org.junit.Assert.assertTrue;
9+
10+
import java.io.IOException;
11+
12+
import org.jboss.arquillian.container.test.api.Deployment;
13+
import org.jboss.arquillian.container.test.api.RunAsClient;
14+
import org.jboss.arquillian.junit.Arquillian;
15+
import org.jboss.arquillian.junit.InSequence;
16+
import org.jboss.arquillian.testcontainers.api.DockerRequired;
17+
import org.jboss.as.arquillian.api.ContainerResource;
18+
import org.jboss.as.arquillian.api.ServerSetup;
19+
import org.jboss.as.arquillian.container.ManagementClient;
20+
import org.jboss.as.controller.client.Operation;
21+
import org.jboss.as.controller.client.helpers.Operations;
22+
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
23+
import org.jboss.as.test.shared.CdiUtils;
24+
import org.jboss.as.test.shared.ServerReload;
25+
import org.jboss.as.test.shared.observability.setuptasks.MicrometerSetupTask;
26+
import org.jboss.as.test.shared.util.AssumeTestGroupUtil;
27+
import org.jboss.dmr.ModelNode;
28+
import org.jboss.shrinkwrap.api.Archive;
29+
import org.jboss.shrinkwrap.api.ShrinkWrap;
30+
import org.jboss.shrinkwrap.api.spec.WebArchive;
31+
import org.junit.AssumptionViolatedException;
32+
import org.junit.BeforeClass;
33+
import org.junit.Test;
34+
import org.junit.runner.RunWith;
35+
import org.wildfly.test.integration.observability.JaxRsActivator;
36+
37+
@RunWith(Arquillian.class)
38+
@ServerSetup({MicrometerSetupTask.class})
39+
@DockerRequired
40+
@RunAsClient
41+
public class ConflictingPrometheusContextTestCase {
42+
private static final ModelNode metricsExtension = Operations.createAddress("extension", "org.wildfly.extension.metrics");
43+
private static final ModelNode metricsSubsystem = Operations.createAddress("subsystem", "metrics");
44+
45+
public static final ModelNode PROMETHEUS_REGISTRY_ADDRESS = Operations.createAddress(SUBSYSTEM, "micrometer", "registry", "prometheus");
46+
47+
private boolean metricsExtAdded = false;
48+
private boolean metricsSubsystemAdded = false;
49+
50+
@ContainerResource
51+
protected ManagementClient managementClient;
52+
53+
@Deployment
54+
public static Archive<?> deploy() {
55+
return ShrinkWrap.create(WebArchive.class, "micrometer-prometheus.war")
56+
.addClasses(JaxRsActivator.class, MicrometerResource.class)
57+
.addAsWebInfResource(CdiUtils.createBeansXml(), "beans.xml");
58+
}
59+
60+
@BeforeClass
61+
public static void beforeClass() {
62+
if (AssumeTestGroupUtil.isBootableJar() || AssumeTestGroupUtil.isWildFlyPreview() || isGalleon()) {
63+
throw new AssumptionViolatedException("Not supported in this configuration");
64+
}
65+
}
66+
67+
private static boolean isGalleon() {
68+
return System.getProperty("ts.layers") != null || System.getProperty("ts.galleon") != null;
69+
}
70+
71+
@Test
72+
@InSequence(1)
73+
public void setupMetrics() throws IOException {
74+
if (!Operations.isSuccessfulOutcome(executeRead(managementClient, metricsExtension))) {
75+
executeOp(managementClient, Operations.createAddOperation(metricsExtension));
76+
metricsExtAdded = true;
77+
}
78+
79+
if (!Operations.isSuccessfulOutcome(executeRead(managementClient, metricsSubsystem))) {
80+
executeOp(managementClient, Operations.createAddOperation(metricsSubsystem));
81+
metricsSubsystemAdded = true;
82+
}
83+
84+
ServerReload.executeReloadAndWaitForCompletion(managementClient);
85+
}
86+
87+
@Test
88+
@InSequence(2)
89+
public void configureConflictingContexts() throws Exception {
90+
ModelNode addOperation = Operations.createAddOperation(PROMETHEUS_REGISTRY_ADDRESS);
91+
addOperation.get("context").set("${no.such.property:/metrics}");
92+
addOperation.get("security-enabled").set("false");
93+
94+
ModelNode response = managementClient.getControllerClient().execute(Operation.Factory.create(addOperation));
95+
assertTrue(response.asString(), response.get(ModelDescriptionConstants.FAILURE_DESCRIPTION)
96+
.asString().contains("WFLYCTL0436"));
97+
}
98+
99+
@Test
100+
@InSequence(3)
101+
public void tearDown() throws IOException {
102+
if (Operations.isSuccessfulOutcome(executeRead(managementClient, PROMETHEUS_REGISTRY_ADDRESS))) {
103+
executeOp(managementClient, Operations.createRemoveOperation(PROMETHEUS_REGISTRY_ADDRESS));
104+
}
105+
if (metricsSubsystemAdded) {
106+
executeOp(managementClient, Operations.createRemoveOperation(metricsSubsystem));
107+
}
108+
if (metricsExtAdded) {
109+
executeOp(managementClient, Operations.createRemoveOperation(metricsExtension));
110+
}
111+
}
112+
113+
public ModelNode executeRead(final ManagementClient managementClient, ModelNode address) throws IOException {
114+
return managementClient.getControllerClient().execute(Operations.createReadResourceOperation(address));
115+
}
116+
117+
private void executeOp(final ManagementClient client, final ModelNode op) throws IOException {
118+
final ModelNode result = client.getControllerClient().execute(Operation.Factory.create(op));
119+
if (!Operations.isSuccessfulOutcome(result)) {
120+
throw new RuntimeException("Failed to execute operation: " + Operations.getFailureDescription(result)
121+
.asString());
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)