Skip to content

Commit 91976c0

Browse files
committed
refactor to use test containers
1 parent 966aee6 commit 91976c0

File tree

6 files changed

+291
-221
lines changed

6 files changed

+291
-221
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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.time.Duration;
11+
import java.util.ArrayList;
12+
import java.util.HashSet;
13+
import java.util.List;
14+
import java.util.Locale;
15+
import java.util.Set;
16+
import org.testcontainers.containers.GenericContainer;
17+
import org.testcontainers.containers.wait.strategy.Wait;
18+
import org.testcontainers.utility.MountableFile;
19+
20+
/** Test container that allows to execute {@link JmxScraper} in an isolated container */
21+
public class JmxScraperContainer extends GenericContainer<JmxScraperContainer> {
22+
23+
private final String endpoint;
24+
private final Set<String> targetSystems;
25+
private String serviceUrl;
26+
private int intervalMillis;
27+
private final Set<String> customYaml;
28+
29+
public JmxScraperContainer(String otlpEndpoint) {
30+
super("openjdk:8u272-jre-slim");
31+
32+
String scraperJarPath = System.getProperty("shadow.jar.path");
33+
assertThat(scraperJarPath).isNotNull();
34+
35+
this.withCopyFileToContainer(MountableFile.forHostPath(scraperJarPath), "/scraper.jar")
36+
.waitingFor(
37+
Wait.forLogMessage(".*JMX scraping started.*", 1)
38+
.withStartupTimeout(Duration.ofSeconds(10)));
39+
40+
this.endpoint = otlpEndpoint;
41+
this.targetSystems = new HashSet<>();
42+
this.customYaml = new HashSet<>();
43+
this.intervalMillis = 1000;
44+
}
45+
46+
public JmxScraperContainer withTargetSystem(String targetSystem) {
47+
targetSystems.add(targetSystem);
48+
return this;
49+
}
50+
51+
public JmxScraperContainer withIntervalMillis(int intervalMillis) {
52+
this.intervalMillis = intervalMillis;
53+
return this;
54+
}
55+
56+
public JmxScraperContainer withService(String host, int port) {
57+
// TODO: adding a way to provide 'host:port' syntax would make this easier for end users
58+
this.serviceUrl =
59+
String.format(
60+
Locale.getDefault(), "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi", host, port);
61+
return this;
62+
}
63+
64+
public JmxScraperContainer withCustomYaml(String yamlPath) {
65+
this.customYaml.add(yamlPath);
66+
return this;
67+
}
68+
69+
@Override
70+
public void start() {
71+
// for now only configure through JVM args
72+
List<String> arguments = new ArrayList<>();
73+
arguments.add("java");
74+
arguments.add("-Dotel.exporter.otlp.endpoint=" + endpoint);
75+
76+
if (!targetSystems.isEmpty()) {
77+
arguments.add("-Dotel.jmx.target.system=" + String.join(",", targetSystems));
78+
}
79+
80+
if (serviceUrl == null) {
81+
throw new IllegalStateException("Missing service URL");
82+
}
83+
arguments.add("-Dotel.jmx.service.url=" + serviceUrl);
84+
arguments.add("-Dotel.jmx.interval.milliseconds=" + intervalMillis);
85+
86+
if (!customYaml.isEmpty()) {
87+
int i = 0;
88+
StringBuilder sb = new StringBuilder("-Dotel.jmx.config=");
89+
for (String yaml : customYaml) {
90+
String containerPath = "/custom_" + i + ".yaml";
91+
this.withCopyFileToContainer(MountableFile.forClasspathResource(yaml), containerPath);
92+
if (i > 0) {
93+
sb.append(",");
94+
}
95+
sb.append(containerPath);
96+
i++;
97+
}
98+
arguments.add(sb.toString());
99+
}
100+
101+
arguments.add("-jar");
102+
arguments.add("/scraper.jar");
103+
104+
this.withCommand(arguments.toArray(new String[0]));
105+
106+
super.start();
107+
}
108+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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.io.IOException;
11+
import java.nio.charset.StandardCharsets;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
15+
import java.time.Duration;
16+
import java.util.HashMap;
17+
import java.util.Map;
18+
import java.util.stream.Collectors;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
import org.testcontainers.containers.GenericContainer;
22+
import org.testcontainers.containers.wait.strategy.Wait;
23+
import org.testcontainers.shaded.com.google.errorprone.annotations.CanIgnoreReturnValue;
24+
import org.testcontainers.utility.MountableFile;
25+
26+
/** Test container that allows to execute {@link TestApp} in an isolated container */
27+
public class TestAppContainer extends GenericContainer<TestAppContainer> {
28+
29+
private static final Logger logger = LoggerFactory.getLogger(TestAppContainer.class);
30+
31+
private final Map<String, String> properties;
32+
private int port;
33+
private String login;
34+
private String pwd;
35+
36+
public TestAppContainer() {
37+
super("openjdk:8u272-jre-slim");
38+
39+
this.properties = new HashMap<>();
40+
41+
String appJar = System.getProperty("app.jar.path");
42+
assertThat(Paths.get(appJar)).isNotEmptyFile().isReadable();
43+
44+
this.withCopyFileToContainer(MountableFile.forHostPath(appJar), "/app.jar")
45+
.waitingFor(
46+
Wait.forLogMessage(TestApp.APP_STARTED_MSG + "\\n", 1)
47+
.withStartupTimeout(Duration.ofSeconds(5)))
48+
.withCommand("java", "-jar", "/app.jar");
49+
}
50+
51+
@CanIgnoreReturnValue
52+
public TestAppContainer withJmxPort(int port) {
53+
this.port = port;
54+
properties.put("com.sun.management.jmxremote.port", Integer.toString(port));
55+
return this.withExposedPorts(port);
56+
}
57+
58+
@CanIgnoreReturnValue
59+
public TestAppContainer withUserAuth(String login, String pwd) {
60+
this.login = login;
61+
this.pwd = pwd;
62+
return this;
63+
}
64+
65+
public int getPort() {
66+
return getMappedPort(port);
67+
}
68+
69+
@Override
70+
protected void doStart() {
71+
super.doStart();
72+
}
73+
74+
@Override
75+
public void start() {
76+
77+
// TODO: add support for ssl
78+
properties.put("com.sun.management.jmxremote.ssl", "false");
79+
80+
if (pwd == null) {
81+
properties.put("com.sun.management.jmxremote.authenticate", "false");
82+
} else {
83+
properties.put("com.sun.management.jmxremote.authenticate", "true");
84+
85+
Path pwdFile = createPwdFile(login, pwd);
86+
this.withCopyFileToContainer(MountableFile.forHostPath(pwdFile), "/jmx.password");
87+
properties.put("com.sun.management.jmxremote.password.file", "/jmx.password");
88+
89+
Path accessFile = createAccessFile(login);
90+
this.withCopyFileToContainer(MountableFile.forHostPath(accessFile), "/jmx.access");
91+
properties.put("com.sun.management.jmxremote.access.file", "/jmx.access");
92+
}
93+
94+
String confArgs =
95+
properties.entrySet().stream()
96+
.map(
97+
e -> {
98+
String s = "-D" + e.getKey();
99+
if (!e.getValue().isEmpty()) {
100+
s += "=" + e.getValue();
101+
}
102+
return s;
103+
})
104+
.collect(Collectors.joining(" "));
105+
106+
this.withEnv("JAVA_TOOL_OPTIONS", confArgs);
107+
108+
logger.info("Test application JAVA_TOOL_OPTIONS = " + confArgs);
109+
110+
super.start();
111+
112+
logger.info("Test application JMX port mapped to {}:{}", getHost(), getMappedPort(port));
113+
}
114+
115+
private static Path createPwdFile(String login, String pwd) {
116+
try {
117+
Path path = Files.createTempFile("test", ".pwd");
118+
writeLine(path, String.format("%s %s", login, pwd));
119+
return path;
120+
} catch (IOException e) {
121+
throw new RuntimeException(e);
122+
}
123+
}
124+
125+
private static Path createAccessFile(String login) {
126+
try {
127+
Path path = Files.createTempFile("test", ".pwd");
128+
writeLine(path, String.format("%s %s", login, "readwrite"));
129+
return path;
130+
} catch (IOException e) {
131+
throw new RuntimeException(e);
132+
}
133+
}
134+
135+
private static void writeLine(Path path, String line) throws IOException {
136+
line = line + "\n";
137+
Files.write(path, line.getBytes(StandardCharsets.UTF_8));
138+
}
139+
}

0 commit comments

Comments
 (0)