Skip to content

Commit f213ecd

Browse files
committed
test connection with container-to-container
1 parent 6388684 commit f213ecd

File tree

3 files changed

+142
-9
lines changed

3 files changed

+142
-9
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.jmxscraper;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import java.util.function.Function;
11+
import org.junit.jupiter.api.AfterAll;
12+
import org.junit.jupiter.api.BeforeAll;
13+
import org.junit.jupiter.api.Test;
14+
import org.slf4j.Logger;
15+
import org.slf4j.LoggerFactory;
16+
import org.testcontainers.containers.GenericContainer;
17+
import org.testcontainers.containers.Network;
18+
import org.testcontainers.containers.output.Slf4jLogConsumer;
19+
20+
/**
21+
* Tests all supported ways to connect to remote JMX interface. This indirectly tests
22+
* JmxConnectionBuilder and relies on containers to minimize the JMX/RMI network complications which
23+
* are not NAT-friendly.
24+
*/
25+
public class JmxConnectionTest {
26+
27+
// OTLP endpoint is not used in test mode, but still has to be provided
28+
private static final String DUMMY_OTLP_ENDPOINT = "http://dummy-otlp-endpoint:8080/";
29+
private static final String SCRAPER_BASE_IMAGE = "openjdk:8u342-jre-slim";
30+
31+
private static final int JMX_PORT = 9999;
32+
private static final String APP_HOST = "app";
33+
34+
private static final Logger jmxScraperLogger = LoggerFactory.getLogger("JmxScraperContainer");
35+
private static final Logger appLogger = LoggerFactory.getLogger("TestAppContainer");
36+
37+
private static Network network;
38+
39+
@BeforeAll
40+
static void beforeAll() {
41+
network = Network.newNetwork();
42+
}
43+
44+
@AfterAll
45+
static void afterAll() {
46+
network.close();
47+
}
48+
49+
@Test
50+
void connectionError() {
51+
try (JmxScraperContainer scraper = scraperContainer().withRmiServiceUrl("unknown_host", 1234)) {
52+
scraper.start();
53+
waitTerminated(scraper);
54+
checkConnectionLogs(scraper, /* expectedOk= */ false);
55+
}
56+
}
57+
58+
@Test
59+
void connectNoAuth() {
60+
connectionTest(
61+
app -> app.withJmxPort(JMX_PORT), scraper -> scraper.withRmiServiceUrl(APP_HOST, JMX_PORT));
62+
}
63+
64+
@Test
65+
void userPassword() {
66+
String login = "user";
67+
String pwd = "t0p!Secret";
68+
connectionTest(
69+
app -> app.withJmxPort(JMX_PORT).withUserAuth(login, pwd),
70+
scraper -> scraper.withRmiServiceUrl(APP_HOST, JMX_PORT).withUser(login).withPassword(pwd));
71+
}
72+
73+
private static void connectionTest(
74+
Function<TestAppContainer, TestAppContainer> customizeApp,
75+
Function<JmxScraperContainer, JmxScraperContainer> customizeScraper) {
76+
try (TestAppContainer app = customizeApp.apply(appContainer())) {
77+
app.start();
78+
try (JmxScraperContainer scraper = customizeScraper.apply(scraperContainer())) {
79+
scraper.start();
80+
waitTerminated(scraper);
81+
checkConnectionLogs(scraper, /* expectedOk= */ true);
82+
}
83+
}
84+
}
85+
86+
private static void checkConnectionLogs(JmxScraperContainer scraper, boolean expectedOk) {
87+
88+
String[] logLines = scraper.getLogs().split("\n");
89+
String lastLine = logLines[logLines.length - 1];
90+
91+
if (expectedOk) {
92+
assertThat(lastLine)
93+
.describedAs("should log connection success")
94+
.endsWith("JMX connection test OK");
95+
} else {
96+
assertThat(lastLine)
97+
.describedAs("should log connection failure")
98+
.endsWith("JMX connection test ERROR");
99+
}
100+
}
101+
102+
private static void waitTerminated(GenericContainer<?> container) {
103+
int retries = 10;
104+
while (retries > 0 && container.isRunning()) {
105+
retries--;
106+
try {
107+
Thread.sleep(100);
108+
} catch (InterruptedException e) {
109+
throw new RuntimeException(e);
110+
}
111+
}
112+
assertThat(retries)
113+
.describedAs("container should stop when testing connection")
114+
.isNotEqualTo(0);
115+
}
116+
117+
private static JmxScraperContainer scraperContainer() {
118+
return new JmxScraperContainer(DUMMY_OTLP_ENDPOINT, SCRAPER_BASE_IMAGE)
119+
.withLogConsumer(new Slf4jLogConsumer(jmxScraperLogger))
120+
.withNetwork(network)
121+
.withTargetSystem("jvm")
122+
.withTestJmx();
123+
}
124+
125+
private static TestAppContainer appContainer() {
126+
return new TestAppContainer()
127+
.withLogConsumer(new Slf4jLogConsumer(appLogger))
128+
.withNetwork(network)
129+
.withNetworkAliases(APP_HOST);
130+
}
131+
}

jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxScraperContainer.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ public JmxScraperContainer(String otlpEndpoint, String baseImage) {
3636
String scraperJarPath = System.getProperty("shadow.jar.path");
3737
assertThat(scraperJarPath).isNotNull();
3838

39-
this.withCopyFileToContainer(MountableFile.forHostPath(scraperJarPath), "/scraper.jar")
40-
.waitingFor(
41-
Wait.forLogMessage(".*JMX scraping started.*", 1)
42-
.withStartupTimeout(Duration.ofSeconds(10)));
39+
this.withCopyFileToContainer(MountableFile.forHostPath(scraperJarPath), "/scraper.jar");
4340

4441
this.endpoint = otlpEndpoint;
4542
this.targetSystems = new HashSet<>();
@@ -159,8 +156,13 @@ public void start() {
159156
arguments.add("io.opentelemetry.contrib.jmxscraper.JmxScraper");
160157
}
161158

162-
if(testJmx) {
159+
if (testJmx) {
163160
arguments.add("-test");
161+
this.waitingFor(Wait.forLogMessage(".*JMX connection test.*", 1));
162+
} else {
163+
this.waitingFor(
164+
Wait.forLogMessage(".*JMX scraping started.*", 1)
165+
.withStartupTimeout(Duration.ofSeconds(10)));
164166
}
165167

166168
this.withCommand(arguments.toArray(new String[0]));

jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public static void main(String[] args) {
8383
Optional.ofNullable(scraperConfig.getUsername()).ifPresent(connectorBuilder::withUser);
8484
Optional.ofNullable(scraperConfig.getPassword()).ifPresent(connectorBuilder::withPassword);
8585

86-
if(testMode) {
86+
if (testMode) {
8787
System.exit(testConnection(connectorBuilder) ? 0 : 1);
8888
} else {
8989
JmxScraper jmxScraper = new JmxScraper(connectorBuilder, service, scraperConfig);
@@ -94,10 +94,10 @@ public static void main(String[] args) {
9494
System.exit(1);
9595
} catch (InvalidArgumentException e) {
9696
logger.log(Level.SEVERE, "invalid configuration provided through arguments", e);
97-
logger.info(
98-
"Usage: java -jar <path_to_jmxscraper.jar> [-test] [-config <conf>]");
97+
logger.info("Usage: java -jar <path_to_jmxscraper.jar> [-test] [-config <conf>]");
9998
logger.info(" -test test JMX connection with provided configuration and exit");
100-
logger.info(" -config <conf> provide configuration, where <conf> is - for stdin, or <path_to_config.properties>" );
99+
logger.info(
100+
" -config <conf> provide configuration, where <conf> is - for stdin, or <path_to_config.properties>");
101101
System.exit(1);
102102
} catch (IOException e) {
103103
logger.log(Level.SEVERE, "Unable to connect ", e);

0 commit comments

Comments
 (0)