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 Jun 19, 2023
1 parent fed4bc4 commit fc94e67
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,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 @@ -21,6 +21,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 @@ -96,6 +97,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 @@ -160,10 +162,18 @@ 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<>();
Map<String, Port> activePorts = new HashMap<>();

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

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

config.getPorts().entrySet().forEach(e -> {
String name = e.getKey();
Port configuredPort = PortConverter.convert(e);
Expand All @@ -182,31 +192,29 @@ 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()), kubernetesPortProperty,
port.getSource());
}
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,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,48 @@
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, Property<T> kubernetesProperty,
Optional<Property<T>> extensionProperty) {
extensionProperty.ifPresent(p -> {
printMessages(usage, kubernetesProperty, p);
});
}

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

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("Kubernetes 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.",
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(
"Kubernetes property '%s' has been set with value '%s' while %s property '%s' is set with '%s'. %s will be set using the former.",
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 @@ -292,7 +292,6 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
}

printMessageAboutPortsThatCantChange(KUBERNETES, ports, config);

return result;
}

Expand All @@ -314,4 +313,4 @@ void externalizeInitTasks(
jobs, initContainers, env, roles, roleBindings, decorators);
}
}
}
}
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 fc94e67

Please sign in to comment.