Skip to content

Commit

Permalink
Assign random ports in Config
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez committed Sep 11, 2024
1 parent 0364ef8 commit cc8a740
Show file tree
Hide file tree
Showing 20 changed files with 314 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ public boolean equals(Object obj) {
@Deprecated(forRemoval = true)
@JsonIgnore
public boolean isMixedModule() {
return "io.quarkus".equals(groupId) && ("quarkus-core".equals(artifactId) || "quarkus-messaging".equals(artifactId));
return "io.quarkus".equals(groupId) && ("quarkus-core".equals(artifactId) ||
"quarkus-vertx-http".equals(artifactId) ||
"quarkus-grpc".equals(artifactId) ||
"quarkus-messaging".equals(artifactId));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
Expand All @@ -79,6 +80,7 @@
import io.quarkus.grpc.runtime.GrpcContainer;
import io.quarkus.grpc.runtime.GrpcServerRecorder;
import io.quarkus.grpc.runtime.ServerInterceptorStorage;
import io.quarkus.grpc.runtime.config.GrpcConfigBuilder;
import io.quarkus.grpc.runtime.config.GrpcConfiguration;
import io.quarkus.grpc.runtime.config.GrpcServerBuildTimeConfig;
import io.quarkus.grpc.runtime.health.GrpcHealthEndpoint;
Expand Down Expand Up @@ -106,6 +108,11 @@ public class GrpcServerProcessor {
private static final String KEY_STORE = SSL_PREFIX + "key-store";
private static final String TRUST_STORE = SSL_PREFIX + "trust-store";

@BuildStep
void config(BuildProducer<RunTimeConfigBuilderBuildItem> runtimeConfigBuilder) {
runtimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(GrpcConfigBuilder.class));
}

@BuildStep
MinNettyAllocatorMaxOrderBuildItem setMinimalNettyMaxOrderSize() {
return new MinNettyAllocatorMaxOrderBuildItem(3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.vertx.http.runtime.PortSystemProperties;
import io.quarkus.virtual.threads.VirtualThreadsRecorder;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.AsyncResult;
Expand Down Expand Up @@ -606,7 +605,6 @@ private class GrpcServerVerticle extends AbstractVerticle {
private final LaunchMode launchMode;
private final Map<String, List<String>> blockingMethodsPerService;
private final Map<String, List<String>> virtualMethodsPerService;
private volatile PortSystemProperties portSystemProperties;

private Server grpcServer;

Expand Down Expand Up @@ -645,15 +643,6 @@ public void start(Promise<Void> startPromise) {
}
startPromise.fail(effectiveCause);
} else {
try {
int actualPort = grpcServer.getPort();
if (actualPort != portToServer.getKey()) {
portSystemProperties = new PortSystemProperties();
portSystemProperties.set("grpc.server", actualPort, launchMode);
}
} catch (Exception e) {
// Ignore, port reused.
}
startPromise.complete();
grpcVerticleCount.incrementAndGet();
}
Expand All @@ -663,11 +652,6 @@ public void start(Promise<Void> startPromise) {
vertx.executeBlocking(() -> {
try {
grpcServer.start();
int actualPort = grpcServer.getPort();
if (actualPort != portToServer.getKey()) {
portSystemProperties = new PortSystemProperties();
portSystemProperties.set("grpc.server", actualPort, launchMode);
}
startPromise.complete();
} catch (Exception e) {
LOGGER.error("Unable to start gRPC server", e);
Expand All @@ -692,9 +676,6 @@ public void stop(Promise<Void> stopPromise) {
stopPromise.complete();
grpcVerticleCount.decrementAndGet();
}
if (portSystemProperties != null) {
portSystemProperties.restore();
}
});
} else {
try {
Expand All @@ -707,10 +688,6 @@ public void stop(Promise<Void> stopPromise) {
} catch (Exception e) {
LOGGER.errorf(e, "Unable to stop the gRPC server gracefully");
stopPromise.fail(e);
} finally {
if (portSystemProperties != null) {
portSystemProperties.restore();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkus.grpc.runtime.config;

import static io.vertx.core.net.SocketAddress.inetSocketAddress;
import static java.lang.Integer.MAX_VALUE;
import static java.net.InetAddress.getByName;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.microprofile.config.spi.ConfigSource;

import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.configuration.ConfigBuilder;
import io.smallrye.config.ConfigSourceContext;
import io.smallrye.config.ConfigSourceFactory.ConfigurableConfigSourceFactory;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.common.MapBackedConfigSource;
import io.vertx.core.net.SocketAddress;

public class GrpcConfigBuilder implements ConfigBuilder {
@Override
public SmallRyeConfigBuilder configBuilder(final SmallRyeConfigBuilder builder) {
return builder.withSources(new RandomPortConfigSourceFactory());
}

private static class RandomPortConfigSourceFactory implements ConfigurableConfigSourceFactory<GrpcServerConfig> {
@Override
public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context, final GrpcServerConfig config) {
Map<String, String> randomPorts = new HashMap<>();

String host = config.host();
if (LaunchMode.current().equals(LaunchMode.TEST)) {
if (config.testPort() == 0) {
String port = assignRandomPort(inetSocketAddress(0, host));
randomPorts.put("quarkus.grpc.server.test-port", port);
randomPorts.put("quarkus.grpc.server.port", port);
}
} else {
if (config.port() == 0) {
String port = assignRandomPort(inetSocketAddress(0, host));
randomPorts.put("quarkus.grpc.server.port", port);
}
}
return randomPorts.isEmpty() ? Collections.emptyList()
: List.of(new MapBackedConfigSource("Quarkus GRPC Random Ports", randomPorts, MAX_VALUE - 1000) {
});
}

private static String assignRandomPort(SocketAddress socketAddress) {
try (ServerSocket serverSocket = new ServerSocket(socketAddress.port(), 0, getByName(socketAddress.host()))) {
return serverSocket.getLocalPort() + "";
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkus.grpc.runtime.config;

import static io.quarkus.runtime.annotations.ConfigPhase.RUN_TIME;

import java.util.Map;

import io.quarkus.runtime.annotations.ConfigDocIgnore;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithParentName;

@ConfigMapping(prefix = "quarkus.grpc.server")
@ConfigRoot(phase = RUN_TIME)
public interface GrpcServerConfig {
@ConfigDocIgnore
@WithDefault("9000")
int port();

@ConfigDocIgnore
@WithDefault("9001")
int testPort();

@ConfigDocIgnore
@WithDefault("0.0.0.0")
String host();

@ConfigDocIgnore
@WithParentName
Map<String, String> properties();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.Map;
import java.util.Optional;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.rest.client.ext.QueryParamStyle;

import io.quarkus.runtime.annotations.ConfigDocDefault;
Expand All @@ -13,11 +12,8 @@
import io.quarkus.runtime.annotations.ConfigRoot;
import io.quarkus.runtime.configuration.MemorySize;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithDefaults;
import io.smallrye.config.WithName;
import io.smallrye.config.WithParentName;

@ConfigMapping(prefix = "quarkus.rest-client")
Expand Down Expand Up @@ -373,40 +369,12 @@ interface RestClientConfig {
*/
Optional<String> url();

/**
* Duplicate mapping of {@link RestClientConfig#url()} to keep a reference of the name used to retrieve the
* <code>url</code>. We need this to reload the <code>url</code> configuration in case it contains an expression
* to <code>${quarkus.http.port}</code>, which is only set after we load the config.
*/
@ConfigDocIgnore
@WithName("url")
ConfigValue urlValue();

default Optional<String> urlReload() {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
return config.getOptionalValue(urlValue().getName(), String.class);
}

/**
* The base URI to use for this service. This property or the `url` property is considered required, unless
* the `baseUri` attribute is configured in the `@RegisterRestClient` annotation.
*/
Optional<String> uri();

/**
* Duplicate mapping of {@link RestClientConfig#uri()} to keep a reference of the name used to retrieve the
* <code>uri</code>. We need this to reload the <code>uri</code> configuration in case it contains an expression
* to <code>${quarkus.http.port}</code>, which is only set after we load the config.
*/
@ConfigDocIgnore
@WithName("uri")
ConfigValue uriValue();

default Optional<String> uriReload() {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
return config.getOptionalValue(uriValue().getName(), String.class);
}

/**
* This property is only meant to be set by advanced configurations to override whatever value was set for the uri or
* url.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ class RestClientRandomPortTest {
void config() {
RestClientConfig echoClientConfig = restClientsConfig.getClient(EchoClient.class);
assertTrue(echoClientConfig.url().isPresent());
assertEquals("http://localhost:0", echoClientConfig.url().get());
assertNotEquals("http://localhost:0", echoClientConfig.urlReload());
assertNotEquals("http://localhost:0", echoClientConfig.url().get());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,9 @@ protected void configureTimeouts(RestClientBuilder builder) {
}

protected void configureBaseUrl(RestClientBuilder builder) {
Optional<String> baseUrlOptional = oneOf(clientConfigByClassName().uriReload(), clientConfigByConfigKey().uriReload());
Optional<String> baseUrlOptional = oneOf(clientConfigByClassName().uri(), clientConfigByConfigKey().uri());
if (baseUrlOptional.isEmpty()) {
baseUrlOptional = oneOf(clientConfigByClassName().urlReload(), clientConfigByConfigKey().urlReload());
baseUrlOptional = oneOf(clientConfigByClassName().url(), clientConfigByConfigKey().url());
}
if (((baseUriFromAnnotation == null) || baseUriFromAnnotation.isEmpty())
&& baseUrlOptional.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private static Map<String, String> createSampleConfigRoot() {
private static Map<String, String> createSampleClientConfig(final String restClientName) {
Map<String, String> clientConfig = new HashMap<>();
// properties only configurable via client config
clientConfig.put("quarkus.rest-client." + restClientName + ".url", "http://localhost");
clientConfig.put("quarkus.rest-client." + restClientName + ".url", "http://localhost:8080");
// properties that override configRoot counterparts
clientConfig.put("quarkus.rest-client." + restClientName + ".proxy-address", "host1:123");
clientConfig.put("quarkus.rest-client." + restClientName + ".connect-timeout", "100");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,12 @@ private void configureTimeouts(QuarkusRestClientBuilder builder) {
}

private void configureBaseUrl(QuarkusRestClientBuilder builder) {
Optional<String> propertyOptional = oneOf(clientConfigByClassName().uriReload(),
clientConfigByConfigKey().uriReload());
Optional<String> propertyOptional = oneOf(clientConfigByClassName().uri(),
clientConfigByConfigKey().uri());

if (propertyOptional.isEmpty()) {
propertyOptional = oneOf(clientConfigByClassName().urlReload(),
clientConfigByConfigKey().urlReload());
propertyOptional = oneOf(clientConfigByClassName().url(),
clientConfigByConfigKey().url());
}
if (((baseUriFromAnnotation == null) || baseUriFromAnnotation.isEmpty())
&& propertyOptional.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
import java.net.URL;

import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.hamcrest.Matchers;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
Expand All @@ -16,6 +15,7 @@
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.restassured.RestAssured;
import io.smallrye.config.SmallRyeConfig;
import io.vertx.core.Handler;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
Expand Down Expand Up @@ -43,21 +43,20 @@ public void testActualPortAccessibleToApp() {
}

public static class AppClass {

@ConfigProperty(name = "quarkus.http.port")
String port;
@Inject
SmallRyeConfig config;

public void route(@Observes Router router) {
router.route("/test").handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
event.response().end(System.getProperty("quarkus.http.test-port"));
event.response().end(config.getConfigValue("quarkus.http.test-port").getValue());
}
});
router.route("/app").handler(new Handler<RoutingContext>() {
@Override
public void handle(RoutingContext event) {
event.response().end(ConfigProvider.getConfig().getValue("quarkus.http.port", String.class));
event.response().end(config.getConfigValue("quarkus.http.port").getValue());
}
});
}
Expand Down
3 changes: 0 additions & 3 deletions extensions/vertx-http/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-AlegacyConfigRoot=true</arg>
</compilerArgs>
</configuration>
</execution>
</executions>
Expand Down
Loading

0 comments on commit cc8a740

Please sign in to comment.