Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,29 @@ static void afterAll() {

@Test
void noAuth() {
try (TestAppContainer app = new TestAppContainer().withNetwork(network).withJmxPort(9990)) {
int port = PortSelector.getAvailableRandomPort();
try (TestAppContainer app =
new TestAppContainer().withJmxPort(port).withJmxAccessibleFromHost()) {
app.start();
testConnector(
() -> JmxConnectorBuilder.createNew(app.getHost(), app.getMappedPort(9990)).build());
() -> JmxConnectorBuilder.createNew(app.getHost(), app.getMappedPort(port)).build());
}
}

@Test
void loginPwdAuth() {
int port = PortSelector.getAvailableRandomPort();
String login = "user";
String pwd = "t0p!Secret";
try (TestAppContainer app =
new TestAppContainer().withNetwork(network).withJmxPort(9999).withUserAuth(login, pwd)) {
new TestAppContainer()
.withJmxPort(port)
.withJmxAccessibleFromHost()
.withUserAuth(login, pwd)) {
app.start();
testConnector(
() ->
JmxConnectorBuilder.createNew(app.getHost(), app.getMappedPort(9999))
JmxConnectorBuilder.createNew(app.getHost(), app.getMappedPort(port))
.userCredentials(login, pwd)
.build());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxscraper;

import java.io.IOException;
import java.net.Socket;
import java.util.Random;

/** Class used for finding random free network port from range 1024-65535 */
public class PortSelector {
private static final Random random = new Random(System.currentTimeMillis());

private static final int MIN_PORT = 1024;
private static final int MAX_PORT = 65535;

private PortSelector() {}

/**
* @return random available TCP port
*/
public static synchronized int getAvailableRandomPort() {
int port;

do {
port = random.nextInt(MAX_PORT - MIN_PORT + 1) + MIN_PORT;
} while (!isPortAvailable(port));

return port;
}

private static boolean isPortAvailable(int port) {
// see https://stackoverflow.com/a/13826145 for the chosen implementation
try (Socket s = new Socket("localhost", port)) {
return false;
} catch (IOException e) {
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
public class TestAppContainer extends GenericContainer<TestAppContainer> {

private final Map<String, String> properties;
private int port;
private String login;
private String pwd;

Expand All @@ -46,9 +45,16 @@ public TestAppContainer() {

@CanIgnoreReturnValue
public TestAppContainer withJmxPort(int port) {
this.port = port;
properties.put("com.sun.management.jmxremote.port", Integer.toString(port));
return this.withExposedPorts(port);
properties.put("com.sun.management.jmxremote.rmi.port", Integer.toString(port));

// To get host->container JMX connection working docker must expose JMX/RMI port under the same
// port number. Because of this testcontainers' standard exposed port randomization approach
// can't be used.
// Explanation:
// https://forums.docker.com/t/exposing-mapped-jmx-ports-from-multiple-containers/5287/6
addFixedExposedPort(port, port);
return this;
}

@CanIgnoreReturnValue
Expand All @@ -58,9 +64,17 @@ public TestAppContainer withUserAuth(String login, String pwd) {
return this;
}

@CanIgnoreReturnValue
public TestAppContainer withJmxAccessibleFromHost() {
properties.put("java.rmi.server.hostname", getHost());
return this;
}

@Override
public void start() {

// properties.put("com.sun.management.jmxremote.local.only", "false");
// properties.put("java.rmi.server.logCalls", "true");
//
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest either remove or include a code comment explaining why you may want to uncomment

Suggested change
// properties.put("com.sun.management.jmxremote.local.only", "false");
// properties.put("java.rmi.server.logCalls", "true");
//

// TODO: add support for ssl
properties.put("com.sun.management.jmxremote.ssl", "false");

Expand Down Expand Up @@ -92,11 +106,9 @@ public void start() {

this.withEnv("JAVA_TOOL_OPTIONS", confArgs);

logger().info("Test application JAVA_TOOL_OPTIONS = " + confArgs);
logger().info("Test application JAVA_TOOL_OPTIONS = {}", confArgs);

super.start();

logger().info("Test application JMX port mapped to {}:{}", getHost(), getMappedPort(port));
}

private static Path createPwdFile(String login, String pwd) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,20 @@

package io.opentelemetry.contrib.jmxscraper.target_systems;

import static org.assertj.core.api.Assertions.assertThat;

import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.grpc.GrpcService;
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
import io.grpc.stub.StreamObserver;
import io.opentelemetry.contrib.jmxscraper.JmxConnectorBuilder;
import io.opentelemetry.contrib.jmxscraper.JmxScraperContainer;
import io.opentelemetry.contrib.jmxscraper.PortSelector;
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse;
import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingDeque;
import javax.management.remote.JMXConnector;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
Expand All @@ -35,8 +31,8 @@
import org.testcontainers.containers.output.Slf4jLogConsumer;

public abstract class TargetSystemIntegrationTest {

private static final Logger logger = LoggerFactory.getLogger(TargetSystemIntegrationTest.class);
private static final Logger targetSystemLogger = LoggerFactory.getLogger("TargetSystemContainer");
private static final Logger jmxScraperLogger = LoggerFactory.getLogger("JmxScraperContainer");
private static final String TARGET_SYSTEM_NETWORK_ALIAS = "targetsystem";
private static String otlpEndpoint;

Expand All @@ -54,7 +50,6 @@ public abstract class TargetSystemIntegrationTest {
private JmxScraperContainer scraper;

private static final String OTLP_HOST = "host.testcontainers.internal";
private static final int JMX_PORT = 9999;

@BeforeAll
static void beforeAll() {
Expand Down Expand Up @@ -90,32 +85,20 @@ void afterEach() {

@Test
void endToEndTest() {
int jmxPort = PortSelector.getAvailableRandomPort();

target =
createTargetContainer(JMX_PORT)
.withLogConsumer(new Slf4jLogConsumer(logger))
createTargetContainer(jmxPort)
.withLogConsumer(new Slf4jLogConsumer(targetSystemLogger))
.withNetwork(network)
.withExposedPorts(JMX_PORT)
.withNetworkAliases(TARGET_SYSTEM_NETWORK_ALIAS);
target.start();

String targetHost = target.getHost();
Integer targetPort = target.getMappedPort(JMX_PORT);
logger.info(
"Target system started, JMX port: {} mapped to {}:{}", JMX_PORT, targetHost, targetPort);

// TODO : wait for metrics to be sent and add assertions on what is being captured
// for now we just test that we can connect to remote JMX using our client.
try (JMXConnector connector = JmxConnectorBuilder.createNew(targetHost, targetPort).build()) {
assertThat(connector.getMBeanServerConnection()).isNotNull();
} catch (IOException e) {
throw new RuntimeException(e);
}

Comment on lines -102 to -114
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] this part had to go anyway as it's now replaced by actual integration tests in #1485 , here it only checked the connection from the host as a proxy of "target JVM is working with JMX settings".

scraper =
new JmxScraperContainer(otlpEndpoint)
.withLogConsumer(new Slf4jLogConsumer(jmxScraperLogger))
.withNetwork(network)
.withService(TARGET_SYSTEM_NETWORK_ALIAS, JMX_PORT);
.withService(TARGET_SYSTEM_NETWORK_ALIAS, jmxPort);

scraper = customizeScraperContainer(scraper);
scraper.start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ private Map<String, Object> buildEnv() {
@SuppressWarnings("BanJNDI")
private static JMXConnector doConnect(JMXServiceURL url, Map<String, Object> env)
throws IOException {
logger.info("Connecting to " + url);
return JMXConnectorFactory.connect(url, env);
}

Expand Down
Loading