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

Align deployment image name when custom name is set in Openshift configuration #32458

Merged
merged 1 commit into from
Apr 11, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jboss.logging.Logger;

import io.quarkus.container.spi.ContainerImageBuildRequestBuildItem;
import io.quarkus.container.spi.ContainerImageCustomNameBuildItem;
import io.quarkus.container.spi.ContainerImageInfoBuildItem;
import io.quarkus.container.spi.ContainerImagePushRequestBuildItem;
import io.quarkus.container.spi.FallbackContainerImageRegistryBuildItem;
Expand Down Expand Up @@ -48,6 +49,7 @@ public void ignoreCredentialsChange(BuildProducer<SuppressNonRuntimeConfigChange
public void publishImageInfo(ApplicationInfoBuildItem app,
ContainerImageConfig containerImageConfig,
Optional<FallbackContainerImageRegistryBuildItem> containerImageRegistry,
Optional<ContainerImageCustomNameBuildItem> containerImageCustomName,
Capabilities capabilities,
BuildProducer<ContainerImageInfoBuildItem> containerImage) {

Expand Down Expand Up @@ -86,7 +88,9 @@ public void publishImageInfo(ApplicationInfoBuildItem app,
throw new IllegalArgumentException("The supplied container-image registry '" + registry + "' is invalid");
}

String effectiveName = containerImageConfig.name.orElse(app.getName());
String effectiveName = containerImageCustomName.map(ContainerImageCustomNameBuildItem::getName)
.or(() -> containerImageConfig.name)
.orElse(app.getName());
String repository = (containerImageConfig.getEffectiveGroup().map(s -> s + "/").orElse("")) + effectiveName;
if (!ImageReference.isValidRepository(repository)) {
throw new IllegalArgumentException("The supplied combination of container-image group '"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private void whenPublishImageInfo() {
Capabilities capabilities = new Capabilities(Collections.emptySet());
BuildProducer<ContainerImageInfoBuildItem> containerImage = actualImageConfig -> actualContainerImageInfo = actualImageConfig;
ContainerImageProcessor processor = new ContainerImageProcessor();
processor.publishImageInfo(app, containerImageConfig, Optional.empty(), capabilities, containerImage);
processor.publishImageInfo(app, containerImageConfig, Optional.empty(), Optional.empty(), capabilities, containerImage);
}

private void thenImageIs(String expectedImage) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.container.spi;

import io.quarkus.builder.item.BuildItem;
import io.quarkus.builder.item.SimpleBuildItem;

/**
* This {@link BuildItem} can be used to override the default image name.
* It can be used in cases where the name of the image is customized externally.
* Example: The openshift extension may override the name. To ensure that things are in sync
* with the image name needs to be set.
*
*/
public final class ContainerImageCustomNameBuildItem extends SimpleBuildItem {

private final String name;

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

public String getName() {
return name;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import io.quarkus.container.image.deployment.ContainerImageConfig;
import io.quarkus.container.image.deployment.util.ImageUtil;
import io.quarkus.container.spi.BaseImageInfoBuildItem;
import io.quarkus.container.spi.ContainerImageCustomNameBuildItem;
import io.quarkus.container.spi.ContainerImageInfoBuildItem;
import io.quarkus.container.spi.ContainerImageLabelBuildItem;
import io.quarkus.container.spi.FallbackContainerImageRegistryBuildItem;
Expand Down Expand Up @@ -97,6 +98,12 @@ public void checkOpenshift(ApplicationInfoBuildItem applicationInfo, Capabilitie
}
}

@BuildStep
public void populateCustomImageName(OpenshiftConfig openshiftConfig,
BuildProducer<ContainerImageCustomNameBuildItem> containerImageCustomName) {
openshiftConfig.name.ifPresent(name -> containerImageCustomName.produce(new ContainerImageCustomNameBuildItem(name)));
}

@BuildStep
public void populateInternalRegistry(OpenshiftConfig openshiftConfig, ContainerImageConfig containerImageConfig,
Capabilities capabilities,
Expand Down Expand Up @@ -381,4 +388,4 @@ void externalizeInitTasks(
decorators);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

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.List;

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

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.quarkus.builder.Version;
import io.quarkus.maven.dependency.Dependency;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;

//
// The purpose of this test is to assert that
// When: We run an in-cluster container builds targeting Openshift (and `Deployment` is used).
// Then:
// - A BuildConfg is generated.
// - Two ImageStream are generated (one named after the app).
// - A Deployment resource was created
// - image-registry.openshift-image-registry.svc:5000 is used as registry (why? so that Deployment can point to the incluster built image).
//
public class OpenshiftWithCustomNameTest {

private static final String NAME = "openshift-with-custom-name";
private static final String CUSTOM_NAME = "custom-name";

@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class))
.setApplicationName(NAME)
.setApplicationVersion("0.1-SNAPSHOT")
.overrideConfigKey("quarkus.openshift.name", "custom-name")
.overrideConfigKey("quarkus.openshift.deployment-kind", "Deployment")
.overrideConfigKey("quarkus.container-image.group", "testme")
.setLogFileName("k8s.log")
.setForcedDependencies(List.of(Dependency.of("io.quarkus", "quarkus-openshift", Version.getVersion())));

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;

@Test
public void assertGeneratedResources() throws IOException {
final Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes");
assertThat(kubernetesDir)
.isDirectoryContaining(p -> p.getFileName().endsWith("openshift.json"))
.isDirectoryContaining(p -> p.getFileName().endsWith("openshift.yml"));
List<HasMetadata> kubernetesList = DeserializationUtil
.deserializeAsList(kubernetesDir.resolve("openshift.yml"));

assertThat(kubernetesList).filteredOn(h -> "BuildConfig".equals(h.getKind())).hasSize(1);
assertThat(kubernetesList).filteredOn(h -> "ImageStream".equals(h.getKind())).hasSize(2);
assertThat(kubernetesList).filteredOn(h -> "ImageStream".equals(h.getKind())
&& h.getMetadata().getName().equals(CUSTOM_NAME)).hasSize(1);

assertThat(kubernetesList).filteredOn(i -> i instanceof Deployment).singleElement().satisfies(i -> {
assertThat(i).isInstanceOfSatisfying(Deployment.class, d -> {
assertThat(d.getMetadata()).satisfies(m -> {
assertThat(m.getName()).isEqualTo("custom-name");
});

assertThat(d.getSpec()).satisfies(deploymentSpec -> {
assertThat(deploymentSpec.getTemplate()).satisfies(t -> {
assertThat(t.getMetadata()).satisfies(metadata -> assertThat(metadata.getLabels()).containsAnyOf(
entry("app.kubernetes.io/name", CUSTOM_NAME),
entry("app.kubernetes.io/version", "0.1-SNAPSHOT")));

assertThat(t.getSpec()).satisfies(podSpec -> {
assertThat(podSpec.getContainers()).singleElement().satisfies(container -> {
assertThat(container.getImage())
.isEqualTo(
"image-registry.openshift-image-registry.svc:5000/testme/" + CUSTOM_NAME
+ ":0.1-SNAPSHOT");
});
});
});
});
});
});
}
}