Skip to content

Commit

Permalink
Merge pull request #24708 from Yelzhasdev/fix_#24676
Browse files Browse the repository at this point in the history
Add container-name configuration for kubernetes extension
  • Loading branch information
geoand authored Apr 11, 2022
2 parents 7ebb1a2 + 8b0a75d commit c8730c6
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.quarkus.kubernetes.deployment;

import io.dekorate.kubernetes.decorator.AddEnvVarDecorator;
import io.dekorate.kubernetes.decorator.AddInitContainerDecorator;
import io.dekorate.kubernetes.decorator.AddLivenessProbeDecorator;
import io.dekorate.kubernetes.decorator.AddMountDecorator;
import io.dekorate.kubernetes.decorator.AddPortDecorator;
import io.dekorate.kubernetes.decorator.AddReadinessProbeDecorator;
import io.dekorate.kubernetes.decorator.AddSidecarDecorator;
import io.dekorate.kubernetes.decorator.ApplicationContainerDecorator;
import io.dekorate.kubernetes.decorator.ApplyArgsDecorator;
import io.dekorate.kubernetes.decorator.ApplyCommandDecorator;
import io.dekorate.kubernetes.decorator.ApplyImageDecorator;
import io.dekorate.kubernetes.decorator.ApplyImagePullPolicyDecorator;
import io.dekorate.kubernetes.decorator.ApplyLimitsCpuDecorator;
import io.dekorate.kubernetes.decorator.ApplyLimitsMemoryDecorator;
import io.dekorate.kubernetes.decorator.ApplyPortNameDecorator;
import io.dekorate.kubernetes.decorator.ApplyRequestsCpuDecorator;
import io.dekorate.kubernetes.decorator.ApplyRequestsMemoryDecorator;
import io.dekorate.kubernetes.decorator.ApplyWorkingDirDecorator;
import io.dekorate.kubernetes.decorator.Decorator;
import io.dekorate.kubernetes.decorator.ResourceProvidingDecorator;
import io.fabric8.kubernetes.api.model.ContainerFluent;

public class ChangeContainerNameDecorator extends ApplicationContainerDecorator<ContainerFluent<?>> {

private final String name;

public ChangeContainerNameDecorator(String name) {
this.name = name;
}

@Override
public void andThenVisit(ContainerFluent<?> containerFluent) {
containerFluent.withName(name);
}

@Override
public Class<? extends Decorator>[] after() {
return new Class[] {
ApplyRequestsMemoryDecorator.class, AddEnvVarDecorator.class, AddMountDecorator.class,
AddPortDecorator.class, ApplyArgsDecorator.class, ApplyCommandDecorator.class,
ApplyImagePullPolicyDecorator.class,
ApplyLimitsCpuDecorator.class, ApplyLimitsMemoryDecorator.class, ApplyPortNameDecorator.class,
ApplyRequestsCpuDecorator.class,
ApplyWorkingDirDecorator.class, ResourceProvidingDecorator.class, AddSidecarDecorator.class,
AddInitContainerDecorator.class,
AddLivenessProbeDecorator.class, AddReadinessProbeDecorator.class, ApplyImageDecorator.class
};
}

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

import io.dekorate.kubernetes.decorator.*;
import io.dekorate.kubernetes.decorator.AddSidecarDecorator;
import io.dekorate.openshift.decorator.ApplyDeploymentTriggerDecorator;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.openshift.api.model.DeploymentConfigSpecFluent;

public class ChangeContainerNameInDeploymentTriggerDecorator extends NamedResourceDecorator<DeploymentConfigSpecFluent<?>> {

private final String containerName;

public ChangeContainerNameInDeploymentTriggerDecorator(String containerName) {
this.containerName = containerName;
}

@Override
public void andThenVisit(DeploymentConfigSpecFluent<?> deploymentConfigSpecFluent, ObjectMeta objectMeta) {
if (deploymentConfigSpecFluent.hasTriggers()) {
deploymentConfigSpecFluent
.editFirstTrigger()
.editImageChangeParams()
.withContainerNames(containerName)
.endImageChangeParams()
.endTrigger()
.buildTriggers();
}
}

@Override
public Class<? extends Decorator>[] after() {
return new Class[] { ApplyDeploymentTriggerDecorator.class, AddEnvVarDecorator.class, AddPortDecorator.class,
AddMountDecorator.class, AddPvcVolumeDecorator.class, AddAwsElasticBlockStoreVolumeDecorator.class,
AddAzureDiskVolumeDecorator.class, AddAwsElasticBlockStoreVolumeDecorator.class, ApplyImageDecorator.class,
ApplyImagePullPolicyDecorator.class, ApplyWorkingDirDecorator.class, ApplyCommandDecorator.class,
ApplyArgsDecorator.class, ApplyServiceAccountNamedDecorator.class, AddReadinessProbeDecorator.class,
AddLivenessProbeDecorator.class, ApplyApplicationContainerDecorator.class, AddSidecarDecorator.class,
AddInitContainerDecorator.class };
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ public class KnativeConfig implements PlatformConfiguration {
@ConfigItem
Map<String, AzureDiskVolumeConfig> azureDiskVolumes;

/**
* If set, it will change the name of the container according to the configuration
*/
@ConfigItem
Optional<String> containerName;

/**
* Init containers
*/
Expand Down Expand Up @@ -264,6 +270,11 @@ public Optional<String> getHost() {
return host;
}

@Override
public Optional<String> getContainerName() {
return containerName;
}

public Map<String, PortConfig> getPorts() {
return ports;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
result.add(new DecoratorBuildItem(KNATIVE, new ApplyContainerImageDecorator(name, i.getImage())));
});

config.getContainerName().ifPresent(containerName -> result
.add(new DecoratorBuildItem(KNATIVE, new ChangeContainerNameDecorator(containerName))));

Stream.concat(config.convertToBuildItems().stream(),
envs.stream().filter(e -> e.getTarget() == null || KNATIVE.equals(e.getTarget()))).forEach(e -> {
result.add(new DecoratorBuildItem(KNATIVE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ public enum DeploymentResourceKind {
@ConfigItem
SecurityContextConfig securityContext;

/**
* If set, it will change the name of the container according to the configuration
*/
@ConfigItem
Optional<String> containerName;

/**
* Debug configuration to be set in pods.
*/
Expand Down Expand Up @@ -395,6 +401,11 @@ public Optional<String> getHost() {
return host;
}

@Override
public Optional<String> getContainerName() {
return containerName;
}

public Map<String, PortConfig> getPorts() {
return ports;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,12 @@ public static enum DeploymentResourceKind {
@ConfigItem
ResourcesConfig resources;

/**
* If set, it will change the name of the container according to the configuration
*/
@ConfigItem
Optional<String> containerName;

/**
* If true, an Openshift Route will be created
*
Expand Down Expand Up @@ -351,6 +357,11 @@ public Optional<String> getHost() {
return host;
}

@Override
public Optional<String> getContainerName() {
return containerName;
}

public Integer getReplicas() {
return replicas;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public List<ConfiguratorBuildItem> createConfigurators(ApplicationInfoBuildItem
image.map(ContainerImageInfoBuildItem::getGroup).ifPresent(g -> {
result.add(new ConfiguratorBuildItem(new ApplyImageGroupConfigurator(g)));
});

}
return result;
}
Expand Down Expand Up @@ -226,6 +227,17 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
image.ifPresent(i -> {
result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyContainerImageDecorator(name, i.getImage())));
});
if ((!capabilities.isPresent(Capability.CONTAINER_IMAGE_S2I) && !capabilities.isPresent(Capability.OPENSHIFT))
|| (capabilities.isPresent(Capability.OPENSHIFT) && !(capabilities.isPresent(Capability.CONTAINER_IMAGE_S2I)
|| capabilities.isPresent(Capability.CONTAINER_IMAGE_OPENSHIFT)))) {
result.add(new DecoratorBuildItem(OPENSHIFT, new RemoveDeploymentTriggerDecorator()));
}

config.getContainerName().ifPresent(containerName -> {
result.add(new DecoratorBuildItem(OPENSHIFT, new ChangeContainerNameDecorator(containerName)));
result.add(new DecoratorBuildItem(OPENSHIFT, new ChangeContainerNameInDeploymentTriggerDecorator(containerName)));
});

result.add(new DecoratorBuildItem(OPENSHIFT, new ApplyImagePullPolicyDecorator(name, config.getImagePullPolicy())));
result.add(new DecoratorBuildItem(OPENSHIFT, new AddLabelDecorator(name, OPENSHIFT_APP_RUNTIME, QUARKUS)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public interface PlatformConfiguration extends EnvVarHolder {

Optional<String> getHost();

Optional<String> getContainerName();

Map<String, PortConfig> getPorts();

ServiceType getServiceType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
result.add(new DecoratorBuildItem(KUBERNETES, new RemoveFromMatchingLabelsDecorator(name, Labels.VERSION)));
}

config.getContainerName().ifPresent(containerName -> result
.add(new DecoratorBuildItem(KUBERNETES, new ChangeContainerNameDecorator(containerName))));

// Service handling
result.add(new DecoratorBuildItem(KUBERNETES, new ApplyServiceTypeDecorator(name, config.getServiceType().name())));
if ((config.getServiceType() == ServiceType.NodePort)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.quarkus.it.kubernetes;

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

import java.io.IOException;
import java.nio.file.Path;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.fabric8.knative.serving.v1.Service;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;

public class KnativeWithSpecifiedContainerNameTest {

@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class))
.setApplicationName("knative-with-specified-container-name")
.setApplicationVersion("0.1-SNAPSHOT")
.withConfigurationResource("knative-with-specified-container-name.properties");

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;

@Test
public void assertGeneratedResources() throws IOException {
Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes");
assertThat(kubernetesDir)
.isDirectoryContaining(p -> p.getFileName().endsWith("knative.json"))
.isDirectoryContaining(p -> p.getFileName().endsWith("knative.yml"))
.satisfies(p -> assertThat(p.toFile().listFiles()).hasSize(2));

List<HasMetadata> kubernetesList = DeserializationUtil
.deserializeAsList(kubernetesDir.resolve("knative.yml"));

assertThat(kubernetesList).filteredOn(i -> "Service".equals(i.getKind())).singleElement().satisfies(i -> {
assertThat(i).isInstanceOfSatisfying(Service.class, s -> {
assertThat(s.getSpec()).satisfies(spec -> {
assertThat(s.getMetadata()).satisfies(m -> {
assertThat(m.getName()).isEqualTo("kfoo");
});

assertThat(spec.getTemplate().getSpec().getContainers()).singleElement().satisfies(container -> {
assertThat(container.getCommand()).contains("my-command");
assertThat(container.getName()).isEqualTo("kbar");
assertThat(container.getArgs()).containsExactly("A", "B");
});
});
});
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.quarkus.it.kubernetes;

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

import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.assertj.core.api.AbstractObjectAssert;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.openshift.api.model.DeploymentTriggerPolicy;
import io.quarkus.bootstrap.model.AppArtifact;
import io.quarkus.builder.Version;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;

public class KubernetesWithSpecifiedContainerNameTest {

@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class))
.setApplicationName("kubernetes-with-specified-container-name")
.setApplicationVersion("0.1-SNAPSHOT")
.withConfigurationResource("kubernetes-with-specified-container-name.properties")
.setForcedDependencies(
Arrays.asList(
new AppArtifact("io.quarkus", "quarkus-kubernetes", Version.getVersion()),
new AppArtifact("io.quarkus", "quarkus-container-image-s2i", Version.getVersion())));

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;

@Test
public void assertGeneratedResources() throws IOException {
Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes");
assertThat(kubernetesDir)
.isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.json"))
.isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.yml"));

List<HasMetadata> kubernetesList = DeserializationUtil
.deserializeAsList(kubernetesDir.resolve("kubernetes.yml"));
assertThat(kubernetesList.get(0)).isInstanceOfSatisfying(Deployment.class, d -> {
assertThat(d.getMetadata()).satisfies(m -> {
assertThat(m.getName()).isEqualTo("foo");
assertThat(m.getLabels()).contains(entry("app.kubernetes.io/name", "foo"));
});

assertThat(d.getSpec().getTemplate().getSpec().getContainers().get(0))
.satisfies(c -> assertThat(c.getName()).isEqualTo("bar"));
assertThat(d.getSpec().getTemplate().getSpec().getContainers().get(0))
.satisfies(c -> assertThat(c.getCommand()).contains("my-command"));
assertThat(d.getSpec().getTemplate().getSpec().getContainers().get(0))
.satisfies(c -> assertThat(c.getArgs()).containsExactly("A", "B"));
});

List<HasMetadata> openshiftList = DeserializationUtil
.deserializeAsList(kubernetesDir.resolve("openshift.yml"));
assertThat(openshiftList).filteredOn(h -> "DeploymentConfig".equals(h.getKind())).singleElement().satisfies(h -> {
AbstractObjectAssert<?, ?> specAssert = assertThat(h).extracting("spec");
specAssert.extracting("template").extracting("spec").isInstanceOfSatisfying(PodSpec.class,
podSpec -> {
assertThat(podSpec.getContainers()).singleElement().satisfies(container -> {
assertThat(container.getCommand())
.contains("my-openshift-command");
assertThat(container.getArgs()).containsExactly("C", "D");
assertThat(container)
.satisfies(c -> assertThat(c.getName()).isEqualTo("obar"));
});
});

specAssert.extracting("triggers").isInstanceOfSatisfying(Collection.class, c -> {
assertThat(c).singleElement().satisfies(trigger -> {
assertThat(((DeploymentTriggerPolicy) trigger).getImageChangeParams().getContainerNames())
.contains("obar");
});
});

assertThat(h.getMetadata().getName()).isIn("ofoo", "foo", "openjdk-11");
assertThat(h.getMetadata().getLabels()).contains(entry("app.kubernetes.io/name", "ofoo"));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Configuration file
quarkus.kubernetes.deployment-target=knative
quarkus.knative.name=kfoo
quarkus.knative.container-name=kbar
quarkus.knative.command=my-command
quarkus.knative.arguments=A,B
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
quarkus.kubernetes.deployment-target=kubernetes,openshift

quarkus.application.name=test
quarkus.kubernetes.name=foo
quarkus.kubernetes.container-name=bar
quarkus.kubernetes.command=my-command
quarkus.kubernetes.arguments=A,B

quarkus.openshift.name=ofoo
quarkus.openshift.container-name=obar
quarkus.openshift.command=my-openshift-command
quarkus.openshift.arguments=C,D

quarkus.s2i.name=s2ifoo

0 comments on commit c8730c6

Please sign in to comment.