Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kubernetes cleanup #12655

Merged
merged 2 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
<aws-alexa-sdk.version>2.35.1</aws-alexa-sdk.version>
<azure-functions-java-library.version>1.3.0</azure-functions-java-library.version>
<kotlin.version>1.3.72</kotlin.version>
<dekorate.version>0.12.11</dekorate.version>
<dekorate.version>0.13.2</dekorate.version>
<maven-artifact-transfer.version>0.10.0</maven-artifact-transfer.version>
<jline.version>2.14.6</jline.version>
<maven-invoker.version>3.0.1</maven-invoker.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@ public Set<String> getAdditionalTags() {
public String getRepository() {
return repository;
}

public String getGroup() {
return repository == null ? null : repository.split("/")[0];
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,170 @@
package io.quarkus.minikube.deployment;

import static io.quarkus.kubernetes.deployment.Constants.DEFAULT_HTTP_PORT;
import static io.quarkus.kubernetes.deployment.Constants.DEPLOYMENT;
import static io.quarkus.kubernetes.deployment.Constants.HTTP_PORT;
import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES;
import static io.quarkus.kubernetes.deployment.Constants.MAX_NODE_PORT_VALUE;
import static io.quarkus.kubernetes.deployment.Constants.MAX_PORT_NUMBER;
import static io.quarkus.kubernetes.deployment.Constants.MINIKUBE;
import static io.quarkus.kubernetes.deployment.Constants.MIN_NODE_PORT_VALUE;
import static io.quarkus.kubernetes.deployment.Constants.MIN_PORT_NUMBER;
import static io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem.DEFAULT_PRIORITY;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import io.dekorate.kubernetes.annotation.ServiceType;
import io.dekorate.kubernetes.config.EnvBuilder;
import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator;
import io.dekorate.project.Project;
import io.quarkus.container.spi.BaseImageInfoBuildItem;
import io.quarkus.container.spi.ContainerImageInfoBuildItem;
import io.quarkus.container.spi.ContainerImageLabelBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.kubernetes.deployment.AddNodePortDecorator;
import io.quarkus.kubernetes.deployment.ApplyContainerImageDecorator;
import io.quarkus.kubernetes.deployment.ApplyHttpGetActionPortDecorator;
import io.quarkus.kubernetes.deployment.ApplyServiceTypeDecorator;
import io.quarkus.kubernetes.deployment.EnvConverter;
import io.quarkus.kubernetes.deployment.KubernetesCommonHelper;
import io.quarkus.kubernetes.deployment.KubernetesConfig;
import io.quarkus.kubernetes.deployment.ResourceNameUtil;
import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem;
import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem;
import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
import io.quarkus.kubernetes.spi.KubernetesEnvBuildItem;
import io.quarkus.kubernetes.spi.KubernetesHealthLivenessPathBuildItem;
import io.quarkus.kubernetes.spi.KubernetesHealthReadinessPathBuildItem;
import io.quarkus.kubernetes.spi.KubernetesLabelBuildItem;
import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem;
import io.quarkus.kubernetes.spi.KubernetesRoleBuildItem;

public class MinikubeProcessor {

public static final String DEFAULT_HASH_ALGORITHM = "SHA-256";
private static final int MINIKUBE_PRIORITY = DEFAULT_PRIORITY + 20;

@BuildStep
public void checkMinikube(BuildProducer<KubernetesDeploymentTargetBuildItem> deploymentTargets) {
deploymentTargets.produce(new KubernetesDeploymentTargetBuildItem(MINIKUBE, DEPLOYMENT, MINIKUBE_PRIORITY, true));
}

@BuildStep
public void createAnnotations(KubernetesConfig config, BuildProducer<KubernetesAnnotationBuildItem> annotations) {
config.getAnnotations().forEach((k, v) -> {
annotations.produce(new KubernetesAnnotationBuildItem(k, v, MINIKUBE));
});
}

@BuildStep
public void checkOpenshift(BuildProducer<KubernetesDeploymentTargetBuildItem> deploymentTargets) {
deploymentTargets
.produce(new KubernetesDeploymentTargetBuildItem(MINIKUBE, DEPLOYMENT, true));
public void createLabels(KubernetesConfig config, BuildProducer<KubernetesLabelBuildItem> labels,
BuildProducer<ContainerImageLabelBuildItem> imageLabels) {
config.getLabels().forEach((k, v) -> {
labels.produce(new KubernetesLabelBuildItem(k, v, MINIKUBE));
imageLabels.produce(new ContainerImageLabelBuildItem(k, v));
});
}

@BuildStep
public List<ConfiguratorBuildItem> createConfigurators(KubernetesConfig config, List<KubernetesPortBuildItem> ports) {
List<ConfiguratorBuildItem> result = new ArrayList<>();
result.addAll(KubernetesCommonHelper.createPlatformConfigurators(config));
result.addAll(KubernetesCommonHelper.createGlobalConfigurators(ports));
return result;

}

@BuildStep
public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applicationInfo,
OutputTargetBuildItem outputTarget,
KubernetesConfig config,
PackageConfig packageConfig,
Optional<MetricsCapabilityBuildItem> metricsConfiguration,
List<KubernetesAnnotationBuildItem> annotations,
List<KubernetesLabelBuildItem> labels,
List<KubernetesEnvBuildItem> envs,
Optional<BaseImageInfoBuildItem> baseImage,
Optional<ContainerImageInfoBuildItem> image,
Optional<KubernetesCommandBuildItem> command,
List<KubernetesPortBuildItem> ports,
Optional<KubernetesHealthLivenessPathBuildItem> livenessPath,
Optional<KubernetesHealthReadinessPathBuildItem> readinessPath,
List<KubernetesRoleBuildItem> roles,
List<KubernetesRoleBindingBuildItem> roleBindings) {

List<DecoratorBuildItem> result = new ArrayList<>();
String name = ResourceNameUtil.getResourceName(config, applicationInfo);

Project project = KubernetesCommonHelper.createProject(applicationInfo, outputTarget, packageConfig);
result.addAll(KubernetesCommonHelper.createDecorators(project, MINIKUBE, name, config, metricsConfiguration,
annotations, labels, command,
ports, livenessPath, readinessPath, roles, roleBindings));

image.ifPresent(i -> {
result.add(new DecoratorBuildItem(MINIKUBE, new ApplyContainerImageDecorator(name, i.getImage())));
});

Stream.concat(config.convertToBuildItems().stream(),
envs.stream().filter(e -> e.getTarget() == null || KUBERNETES.equals(e.getTarget()))).forEach(e -> {
result.add(new DecoratorBuildItem(MINIKUBE,
new AddEnvVarDecorator(ApplicationContainerDecorator.ANY, name, new EnvBuilder()
.withName(EnvConverter.convertName(e.getName()))
.withValue(e.getValue())
.withSecret(e.getSecret())
.withConfigmap(e.getConfigMap())
.withField(e.getField())
.build())));
});

result.add(new DecoratorBuildItem(MINIKUBE, new ApplyImagePullPolicyDecorator(name, "IfNotPresent")));

//Service handling
result.add(new DecoratorBuildItem(MINIKUBE, new ApplyServiceTypeDecorator(name, ServiceType.NodePort.name())));
result.add(new DecoratorBuildItem(MINIKUBE, new AddNodePortDecorator(name, config.getNodePort()
.orElseGet(() -> getStablePortNumberInRange(name, MIN_NODE_PORT_VALUE, MAX_NODE_PORT_VALUE)))));

//Probe port handling
Integer port = ports.stream().filter(p -> HTTP_PORT.equals(p.getName())).map(KubernetesPortBuildItem::getPort)
.findFirst().orElse(DEFAULT_HTTP_PORT);
result.add(new DecoratorBuildItem(MINIKUBE, new ApplyHttpGetActionPortDecorator(port)));

return result;
}

/**
* Given a string, generate a port number within the supplied range
* The output is always the same (between {@code min} and {@code max})
* given the same input and it's useful when we need to generate a port number
* which needs to stay the same but we don't care about the exact value
*/
private int getStablePortNumberInRange(String input, int min, int max) {
if (min < MIN_PORT_NUMBER || max > MAX_PORT_NUMBER) {
throw new IllegalArgumentException(
String.format("Port number range must be within [%d-%d]", MIN_PORT_NUMBER, MAX_PORT_NUMBER));
}

try {
byte[] hash = MessageDigest.getInstance(DEFAULT_HASH_ALGORITHM).digest(input.getBytes(StandardCharsets.UTF_8));
return min + new BigInteger(hash).mod(BigInteger.valueOf(max - min)).intValue();
} catch (Exception e) {
throw new RuntimeException("Unable to generate stable port number from input string: '" + input + "'", e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.quarkus.kubernetes.spi;

import java.util.Optional;

import io.quarkus.builder.item.MultiBuildItem;

/**
* A build item that wraps around Configurator objects.
* The purpose of those build items is influence the configuration that will be feed to the generator process.
* Configurators are similar to decorators, but are applied to configuration instead of generated resources.
*/
public final class ConfiguratorBuildItem extends MultiBuildItem {
iocanel marked this conversation as resolved.
Show resolved Hide resolved

/**
* The configurator
*/
private final Object configurator;

public ConfiguratorBuildItem(Object configurator) {
this.configurator = configurator;
}

public Object getConfigurator() {
return this.configurator;
}

public boolean matches(Class type) {
return type.isInstance(configurator);

}

public <C> Optional<C> getConfigurator(Class<C> type) {
if (matches(type)) {
return Optional.<C> of((C) configurator);
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

import io.quarkus.builder.item.MultiBuildItem;

/**
* A build item that wraps around Decorator objects.
* The purpose of those build items is to perform modification on the generated resources.
*/
public final class DecoratorBuildItem extends MultiBuildItem {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

package io.quarkus.kubernetes.deployment;

import io.dekorate.kubernetes.config.Configurator;
import io.dekorate.kubernetes.config.ImageConfigurationFluent;

public class ApplyImageGroupConfigurator extends Configurator<ImageConfigurationFluent<?>> {

private final String group;

public ApplyImageGroupConfigurator(String group) {
this.group = group;
}

@Override
public void visit(ImageConfigurationFluent<?> config) {
config.withGroup(group);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

package io.quarkus.kubernetes.deployment;

import io.dekorate.kubernetes.config.Configurator;
import io.dekorate.kubernetes.config.ImageConfigurationFluent;

public class ApplyImageRegistryConfigurator extends Configurator<ImageConfigurationFluent<?>> {

private final String registry;

public ApplyImageRegistryConfigurator(String registry) {
this.registry = registry;
}

@Override
public void visit(ImageConfigurationFluent<?> config) {
config.withRegistry(registry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public final class Constants {

static final String KUBERNETES = "kubernetes";
public static final String KUBERNETES = "kubernetes";
public static final String MINIKUBE = "minikube";
public static final String DEPLOYMENT = "Deployment";
static final String DOCKER = "docker";
Expand All @@ -28,13 +28,13 @@ public final class Constants {
static final String QUARKUS_ANNOTATIONS_VCS_URL = "app.quarkus.io/vcs-url";
static final String QUARKUS_ANNOTATIONS_BUILD_TIMESTAMP = "app.quarkus.io/build-timestamp";

static final String HTTP_PORT = "http";
static final int DEFAULT_HTTP_PORT = 8080;
public static final String HTTP_PORT = "http";
public static final int DEFAULT_HTTP_PORT = 8080;

static final int MIN_PORT_NUMBER = 1;
static final int MAX_PORT_NUMBER = 65535;
static final int MIN_NODE_PORT_VALUE = 30000;
static final int MAX_NODE_PORT_VALUE = 31999;
public static final int MIN_PORT_NUMBER = 1;
public static final int MAX_PORT_NUMBER = 65535;
public static final int MIN_NODE_PORT_VALUE = 30000;
public static final int MAX_NODE_PORT_VALUE = 31999;

private Constants() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ public static Container adapt(io.dekorate.kubernetes.config.Container container)
builder.accept(new AddMountDecorator(mount));
}

builder.accept(new ApplyImagePullPolicyDecorator(container.getImagePullPolicy()));

builder.accept(new ApplyImagePullPolicyDecorator(name, container.getImagePullPolicy()));
builder.accept(new AddLivenessProbeDecorator(name, container.getLivenessProbe()));
builder.accept(new AddReadinessProbeDecorator(name, container.getReadinessProbe()));
return builder.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

package io.quarkus.kubernetes.deployment;

import io.dekorate.kubernetes.config.Configurator;
import io.dekorate.s2i.config.S2iBuildConfigFluent;

public class DisableS2iConfigurator extends Configurator<S2iBuildConfigFluent<?>> {

@Override
public void visit(S2iBuildConfigFluent<?> s2i) {
s2i.withEnabled(false);
}
}
Loading