Skip to content

Commit

Permalink
refactor: port mgmt from kube to ext publishing the
Browse files Browse the repository at this point in the history
build items
  • Loading branch information
iocanel committed Jul 12, 2023
1 parent 1da5a0b commit b3cbcee
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,7 @@ KubernetesPortBuildItem registerGrpcServiceInKubernetes(List<BindableServiceBuil
.orElse(true);
if (useSeparateServer) {
// Only expose the named port "grpc" if the gRPC server is exposed using a separate server.
int port = ConfigProvider.getConfig().getOptionalValue("quarkus.grpc.server.port", Integer.class)
.orElse(9000);
return new KubernetesPortBuildItem(port, "grpc");
return KubernetesPortBuildItem.fromRuntimeConfiguration("https", "quarkus.grpc.server.port", 9000);
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
package io.quarkus.kubernetes.spi;

import java.util.Optional;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.deployment.Feature;

public final class KubernetesPortBuildItem extends MultiBuildItem {

private final int port;
private final String name;
/**
* Indicates when the port is enabled vs simply configured.
* For example the presence `quarkus.http.ssl-port` also is not enought to tell us if enabled.
* Still, we need to communicate its value and let `quarkus-kubernetes` extension decide.
**/
private final boolean enabled;
private final Optional<Property<Integer>> source;

public KubernetesPortBuildItem(int port, Feature feature) {
this(port, feature.getName());
this(port, feature.getName(), true, Optional.empty());
}

public KubernetesPortBuildItem(int port, String name) {
this(port, name, true, Optional.empty());
}

public KubernetesPortBuildItem(int port, String name, boolean enabled, Optional<Property<Integer>> source) {
this.port = port;
this.name = name;
this.source = source;
this.enabled = enabled;
}

public static KubernetesPortBuildItem fromRuntimeConfiguration(String name, String propertyName, Integer defaultValue,
boolean enabled) {
Property<Integer> origin = Property.fromRuntimeConfiguration(propertyName, Integer.class, defaultValue);
Integer port = origin.getValue().orElse(defaultValue);
return new KubernetesPortBuildItem(port, name, enabled, Optional.of(origin));
}

public static KubernetesPortBuildItem fromRuntimeConfiguration(String name, String propertyName, Integer defaultValue) {
Property<Integer> origin = Property.fromRuntimeConfiguration(propertyName, Integer.class, defaultValue);
Integer port = origin.getValue().orElse(defaultValue);
return new KubernetesPortBuildItem(port, name, origin.getValue().isPresent(), Optional.of(origin));
}

public int getPort() {
Expand All @@ -24,4 +52,12 @@ public int getPort() {
public String getName() {
return name;
}

public boolean isEnabled() {
return enabled;
}

public Optional<Property<Integer>> getSource() {
return source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.quarkus.kubernetes.spi;

import java.util.Optional;

import org.eclipse.microprofile.config.ConfigProvider;

public class Property<T> {

private final String name;
private final Class<T> type;
private final Optional<T> value;
private final T defaultValue;
private final boolean runtime;

public Property(String name, Class<T> type, Optional<T> value, T defaultValue, boolean runtime) {
this.name = name;
this.type = type;
this.value = value;
this.defaultValue = defaultValue;
this.runtime = runtime;
}

public static <T> Property<T> fromRuntimeConfiguration(String name, Class<T> type, T defaultValue) {
return new Property<T>(name, type, ConfigProvider.getConfig().getOptionalValue(name, type), defaultValue, true);
}

public String getName() {
return name;
}

public Class<T> getType() {
return type;
}

public Optional<T> getValue() {
return value;
}

public T getDefaultValue() {
return defaultValue;
}

public boolean isRuntime() {
return runtime;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -97,6 +98,7 @@
import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;
import io.quarkus.kubernetes.spi.KubernetesServiceAccountBuildItem;
import io.quarkus.kubernetes.spi.Property;
import io.quarkus.kubernetes.spi.RoleRef;
import io.quarkus.kubernetes.spi.Subject;

Expand Down Expand Up @@ -161,7 +163,14 @@ public static Optional<Port> getPort(List<KubernetesPortBuildItem> ports, Platfo
public static Map<String, Port> combinePorts(List<KubernetesPortBuildItem> ports,
PlatformConfiguration config) {
Map<String, Port> allPorts = new HashMap<>();
allPorts.putAll(verifyPorts(ports).entrySet().stream()
Map<String, Port> activePorts = new HashMap<>();

allPorts.putAll(ports.stream()
.map(p -> new PortBuilder().withName(p.getName()).withContainerPort(p.getPort()).build())
.collect(Collectors.toMap(Port::getName, p -> p)));

activePorts.putAll(verifyPorts(ports)
.entrySet().stream()
.map(e -> new PortBuilder().withName(e.getKey()).withContainerPort(e.getValue()).build())
.collect(Collectors.toMap(Port::getName, p -> p)));

Expand All @@ -183,31 +192,30 @@ public static Map<String, Port> combinePorts(List<KubernetesPortBuildItem> ports
.withPath(Strings.isNotNullOrEmpty(configuredPort.getPath()) ? configuredPort.getPath()
: buildItemPort.getPath())
.build();

// Special handling for ports with mapped configuration. We look up the container port from the Quarkus configuration.
if (combinedPort.getContainerPort() == null) {
Integer containerPort = RuntimePropertiesUtil.getPortNumberFromRuntime(name);
if (containerPort != null) {
combinedPort = new PortBuilder(combinedPort)
.withContainerPort(containerPort)
.build();
}
}

allPorts.put(name, combinedPort);
activePorts.put(name, combinedPort);
});
return allPorts;
return activePorts;
}

/**
* Creates the configurator build items.
*/
public static void printMessageAboutPortsThatCantChange(String target, List<KubernetesPortBuildItem> ports,
PlatformConfiguration config) {
Collection<Port> allPorts = combinePorts(ports, config).values();
for (Port port : allPorts) {
RuntimePropertiesUtil.printTraceIfRuntimePropertyIsSet(target, port);
}
PlatformConfiguration configuration) {
ports.stream().forEach(port -> {
boolean enabled = port.isEnabled() || configuration.getPorts().containsKey(port.getName());
if (enabled) {
String name = "quarkus." + target + ".ports." + port.getName() + ".container-port";
Optional<Integer> value = Optional.ofNullable(configuration.getPorts().get(port.getName()))
.map(p -> p.containerPort)
.filter(OptionalInt::isPresent)
.map(OptionalInt::getAsInt);
Property<Integer> kubernetesPortProperty = new Property(name, Integer.class, value, null, false);
PropertyUtil.printMessages(String.format("The container port %s", port.getName()), target,
kubernetesPortProperty,
port.getSource());
}
});
}

/**
Expand Down Expand Up @@ -1078,6 +1086,9 @@ private static Map<String, Integer> verifyPorts(List<KubernetesPortBuildItem> ku
final Map<String, Integer> result = new HashMap<>();
final Set<Integer> usedPorts = new HashSet<>();
for (KubernetesPortBuildItem entry : kubernetesPortBuildItems) {
if (!entry.isEnabled()) {
continue;
}
final String name = entry.getName();
if (result.containsKey(name)) {
throw new IllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
}

printMessageAboutPortsThatCantChange(OPENSHIFT, ports, config);

return result;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.quarkus.kubernetes.deployment;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import org.jboss.logging.Logger;

import io.quarkus.kubernetes.spi.Property;

public class PropertyUtil {

private static final Set<String> VISITED_EXTENSION_PROPERTIES = new HashSet<>();
private static final Logger LOG = Logger.getLogger(PropertyUtil.class);

public static <T> void printMessages(String usage, String platform, Property<T> kubernetesProperty,
Optional<Property<T>> extensionProperty) {
extensionProperty.ifPresent(p -> {
printMessages(usage, platform, kubernetesProperty, p);
});
}

public static <T> void printMessages(String usage, String platform, Property<T> kubernetesProperty,
Property<T> extensionProperty) {
if (!VISITED_EXTENSION_PROPERTIES.add(extensionProperty.getName())) {
return;
}

String platformCapitalized = platform.substring(0, 1).toUpperCase() + platform.substring(1);
T kubernetesValue = kubernetesProperty.getValue().orElse(null);
if (kubernetesValue == null) {
// If no kubernetes property is provided, this will be used instead.
String defaultOrProvided = extensionProperty.getValue().isPresent() ? "provided" : "default";
String stringValue = String.valueOf(extensionProperty.getValue().orElse(extensionProperty.getDefaultValue()));
LOG.infof("%s manifests are generated with '%s' having %s value '%s'. "
+ "The app and manifests will get out of sync if the property '%s' is changed at runtime.",
platformCapitalized, usage, defaultOrProvided, stringValue, extensionProperty.getName());

} else if (extensionProperty.getValue().filter(v -> !v.equals(kubernetesValue)).isPresent()) {
// We have conflicting properties that need to be aligned. Maybe warn?
String runtimeOrBuildTime = extensionProperty.isRuntime() ? "runtime" : "buildtime";
LOG.debugf(
"%s property '%s' has been set with value '%s' while %s property '%s' is set with '%s'. %s will be set using the former.",
platformCapitalized, kubernetesProperty.getName(), kubernetesProperty.getValue().get(), runtimeOrBuildTime,
extensionProperty.getName(), extensionProperty.getValue().get(), usage);
} else {
// Both proeprties are present and aligned.
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -174,26 +174,16 @@ void filterMultipleVertxInstancesWarning(LaunchModeBuildItem launchModeBuildItem

@BuildStep
public void kubernetes(BuildProducer<KubernetesPortBuildItem> kubernetesPorts) {
if (isSslConfigured()) {
// ssl is not disabled
int sslPort = ConfigProvider.getConfig()
.getOptionalValue("quarkus.http.ssl-port", Integer.class)
.orElse(8443);
kubernetesPorts.produce(new KubernetesPortBuildItem(sslPort, "https"));
}

int port = ConfigProvider.getConfig().getOptionalValue("quarkus.http.port", Integer.class).orElse(8080);
kubernetesPorts.produce(new KubernetesPortBuildItem(port, "http"));
kubernetesPorts.produce(KubernetesPortBuildItem.fromRuntimeConfiguration("http", "quarkus.http.port", 8080, true));
kubernetesPorts.produce(
KubernetesPortBuildItem.fromRuntimeConfiguration("https", "quarkus.http.ssl-port", 8443, isSslConfigured()));
}

@BuildStep
public KubernetesPortBuildItem kubernetesForManagement(
ManagementInterfaceBuildTimeConfig managementInterfaceBuildTimeConfig) {
if (managementInterfaceBuildTimeConfig.enabled) {
int port = ConfigProvider.getConfig().getOptionalValue("quarkus.management.port", Integer.class).orElse(9000);
return new KubernetesPortBuildItem(port, "management");
}
return null;
return KubernetesPortBuildItem.fromRuntimeConfiguration("management", "quarkus.management.port", 9000,
managementInterfaceBuildTimeConfig.enabled);
}

@BuildStep
Expand Down

0 comments on commit b3cbcee

Please sign in to comment.