From 60b223732052f03287e63c1be019c6b0e0e8d4ad Mon Sep 17 00:00:00 2001 From: Ioannis Canellos Date: Wed, 26 Jul 2023 17:23:16 +0300 Subject: [PATCH] feat: generate/use pull secrets when possible --- .../asciidoc/deploying-to-kubernetes.adoc | 35 ++++++++++++ .../deployment/OpenshiftProcessor.java | 2 - .../deployment/DevClusterHelper.java | 4 +- .../kubernetes/deployment/KnativeConfig.java | 11 ++++ .../deployment/KnativeProcessor.java | 4 +- .../deployment/KubernetesCommonHelper.java | 17 ++++++ .../deployment/KubernetesConfig.java | 11 ++++ .../deployment/OpenshiftConfig.java | 11 ++++ .../deployment/OpenshiftProcessor.java | 2 +- .../deployment/PlatformConfiguration.java | 2 + .../VanillaKubernetesProcessor.java | 2 +- .../BaseOpenshiftWithRemoteRegistry.java | 43 ++++++--------- .../it/kubernetes/BaseWithRemoteRegistry.java | 55 +++++++++++++++++++ .../KubernetesWithImagePushTest.java | 40 ++++++++++++++ .../OpenshiftWithRemoteImagePushTest.java | 4 ++ .../OpenshiftWithRemoteRegistryPushTest.java | 1 + 16 files changed, 209 insertions(+), 35 deletions(-) create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseWithRemoteRegistry.java create mode 100644 integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithImagePushTest.java diff --git a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc index 5895c885045e0..adc3dfbc3b142 100644 --- a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc +++ b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc @@ -281,6 +281,41 @@ quarkus.container-image.registry=my.docker-registry.net By adding this property along with the rest of the container image properties of the previous section, the generated manifests will use the image `my.docker-registry.net/quarkus/demo-app:1.0`. The image is not the only thing that can be customized in the generated manifests, as will become evident in the following sections. + +==== Automatic generation of pull secrets + +When docker registries are used, users often provide credentials, so that an image is built and pushed to the specified registry during the build. +[source,properties] +---- +quarkus.container-image.username=myusername +quarkus.container-image.password=mypassword +---- + +Kubernetes will also need these credentials when it comes to pull the image from the registry. This is where image pull secrets are used. An image pull secret is a special kind +of secret that contains the required credentials. Quarkus can automatically generate and configure when: + +[source,properties] +---- +quarkus.kubernetes.generate-image-pull-secret=true +---- + +More specifically a `Secret`like the one bellow is genrated: + +[source,yaml] +---- +apiVersion: v1 +kind: Secret +metadata: + name: test-quarkus-app-pull-secret +data: + ".dockerconfigjson": ewogCSJhdXRocyI6IHsKCQkibXkucmVnaXN0eS5vcmciOiB7CiAJCQkiYXV0aCI6ImJYbDFjMlZ5Ym1GdFpUcHRlWEJoYzNOM2IzSmsiCgkJfQoJfQp9 +type: kubernetes.io/dockerconfigjson + +---- + +And also `test-quarkus-app-pull-secret is added to the `imagePullSecrets` list. + + === Labels and Annotations ==== Labels diff --git a/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java b/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java index ca73c5cbb81db..0dd2941774299 100644 --- a/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java +++ b/extensions/container-image/container-image-openshift/deployment/src/main/java/io/quarkus/container/image/openshift/deployment/OpenshiftProcessor.java @@ -30,7 +30,6 @@ import org.jboss.logging.Logger; import io.dekorate.kubernetes.decorator.AddDockerConfigJsonSecretDecorator; -import io.dekorate.kubernetes.decorator.AddImagePullSecretDecorator; import io.dekorate.utils.Packaging; import io.dekorate.utils.Serialization; import io.fabric8.kubernetes.api.model.HasMetadata; @@ -262,7 +261,6 @@ public void configureExternalRegistry(ApplicationInfoBuildItem applicationInfo, applicationInfo.getName(), containerImageInfo.getImage(), imagePushSecret))); decorator.produce(new DecoratorBuildItem(OPENSHIFT, new ApplyDockerImageRepositoryToImageStream(applicationInfo.getName(), repositoryWithRegistry))); - decorator.produce(new DecoratorBuildItem(OPENSHIFT, new AddImagePullSecretDecorator(name, imagePushSecret))); }); } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java index f6b2e79a0052d..a84b86f6b155a 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java @@ -92,7 +92,7 @@ public static List createDecorators(String clusterKind, Optional port = KubernetesCommonHelper.getPort(ports, config); result.addAll(KubernetesCommonHelper.createDecorators(project, clusterKind, name, config, metricsConfiguration, kubernetesClientConfiguration, - annotations, labels, command, + annotations, labels, image, command, port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings)); image.ifPresent(i -> { @@ -181,4 +181,4 @@ private static int getStablePortNumberInRange(String input, int min, int max) { throw new RuntimeException("Unable to generate stable port number from input string: '" + input + "'", e); } } -} \ No newline at end of file +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeConfig.java index 303fbe7edd86e..1b5d5e135ff74 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeConfig.java @@ -115,6 +115,13 @@ public class KnativeConfig implements PlatformConfiguration { @ConfigItem Optional> imagePullSecrets; + /** + * Enable generation of image pull secret, when the container image username and + * password are provided. + */ + @ConfigItem(defaultValue = "false") + boolean generateImagePullSecret; + /** * The liveness probe */ @@ -329,6 +336,10 @@ public Optional> getImagePullSecrets() { return imagePullSecrets; } + public boolean isGenerateImagePullSecret() { + return generateImagePullSecret; + } + public ProbeConfig getLivenessProbe() { return livenessProbe; } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java index 190aa39d4aab2..49ce2c288cc17 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java @@ -165,7 +165,7 @@ public List createDecorators(ApplicationInfoBuildItem applic Optional port = KubernetesCommonHelper.getPort(ports, config, "http"); result.addAll(KubernetesCommonHelper.createDecorators(project, KNATIVE, name, config, metricsConfiguration, kubernetesClientConfiguration, annotations, - labels, command, port, livenessPath, readinessPath, startupProbePath, + labels, image, command, port, livenessPath, readinessPath, startupProbePath, roles, clusterRoles, serviceAccounts, roleBindings)); image.ifPresent(i -> { @@ -375,4 +375,4 @@ private static List createVolumeDecorators(Optional }); return result; } -} \ No newline at end of file +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java index 5e3204620405d..78bc5a2f8b4f9 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java @@ -39,6 +39,7 @@ import io.dekorate.kubernetes.decorator.AddAzureDiskVolumeDecorator; import io.dekorate.kubernetes.decorator.AddAzureFileVolumeDecorator; import io.dekorate.kubernetes.decorator.AddConfigMapVolumeDecorator; +import io.dekorate.kubernetes.decorator.AddDockerConfigJsonSecretDecorator; import io.dekorate.kubernetes.decorator.AddEmptyDirVolumeDecorator; import io.dekorate.kubernetes.decorator.AddEnvVarDecorator; import io.dekorate.kubernetes.decorator.AddHostAliasesDecorator; @@ -78,6 +79,7 @@ import io.fabric8.kubernetes.api.model.PodSpecBuilder; import io.fabric8.kubernetes.api.model.rbac.PolicyRule; import io.fabric8.kubernetes.api.model.rbac.PolicyRuleBuilder; +import io.quarkus.container.spi.ContainerImageInfoBuildItem; import io.quarkus.deployment.builditem.ApplicationInfoBuildItem; import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem; import io.quarkus.deployment.pkg.PackageConfig; @@ -228,6 +230,7 @@ public static List createDecorators(Optional projec Optional kubernetesClientConfiguration, List annotations, List labels, + Optional image, Optional command, Optional port, Optional livenessProbePath, @@ -249,6 +252,20 @@ public static List createDecorators(Optional projec result.addAll(createCommandDecorator(project, target, name, config, command)); result.addAll(createArgsDecorator(project, target, name, config, command)); + // Handle Pull Secrets + if (config.isGenerateImagePullSecret()) { + image.ifPresent(i -> { + i.getRegistry().ifPresent(registry -> { + if (i.getUsername().isPresent() && i.getPassword().isPresent()) { + String imagePullSecret = name + "-pull-secret"; + result.add(new DecoratorBuildItem(target, new AddImagePullSecretDecorator(name, imagePullSecret))); + result.add(new DecoratorBuildItem(target, new AddDockerConfigJsonSecretDecorator(imagePullSecret, + registry, i.username.get(), i.password.get()))); + } + }); + }); + } + // Handle Probes if (!port.isEmpty()) { result.addAll(createProbeDecorators(name, target, config.getLivenessProbe(), config.getReadinessProbe(), diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java index 5067221b90ca9..87db6c01deee5 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesConfig.java @@ -170,6 +170,13 @@ public enum DeploymentResourceKind { @ConfigItem Optional> imagePullSecrets; + /** + * Enable generation of image pull secret, when the container image username and + * password are provided. + */ + @ConfigItem(defaultValue = "false") + boolean generateImagePullSecret; + /** * The liveness probe */ @@ -513,6 +520,10 @@ public Optional> getImagePullSecrets() { return imagePullSecrets; } + public boolean isGenerateImagePullSecret() { + return generateImagePullSecret; + } + public ProbeConfig getLivenessProbe() { return livenessProbe; } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java index b4855fcaa652f..3c3062eb7f3eb 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftConfig.java @@ -183,6 +183,13 @@ public static enum DeploymentResourceKind { @ConfigItem Optional> imagePullSecrets; + /** + * Enable generation of image pull secret, when the container image username and + * password are provided. + */ + @ConfigItem(defaultValue = "false") + boolean generateImagePullSecret; + /** * The liveness probe */ @@ -412,6 +419,10 @@ public Optional> getImagePullSecrets() { return imagePullSecrets; } + public boolean isGenerateImagePullSecret() { + return generateImagePullSecret; + } + public ProbeConfig getLivenessProbe() { return livenessProbe; } diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java index 9b93c34187f78..f726103d98db5 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java @@ -222,7 +222,7 @@ public List createDecorators(ApplicationInfoBuildItem applic Optional port = KubernetesCommonHelper.getPort(ports, config, config.route.targetPort); result.addAll(KubernetesCommonHelper.createDecorators(project, OPENSHIFT, name, config, metricsConfiguration, kubernetesClientConfiguration, - annotations, labels, command, + annotations, labels, image, command, port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings)); if (config.flavor == v3) { diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java index 94673530041b7..2710ef71d8675 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/PlatformConfiguration.java @@ -46,6 +46,8 @@ public interface PlatformConfiguration extends EnvVarHolder { Optional> getImagePullSecrets(); + boolean isGenerateImagePullSecret(); + ProbeConfig getLivenessProbe(); ProbeConfig getReadinessProbe(); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java index 74e197ac406f0..3e35fbaac5fc6 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java @@ -162,7 +162,7 @@ public List createDecorators(ApplicationInfoBuildItem applic packageConfig); Optional port = KubernetesCommonHelper.getPort(ports, config); result.addAll(KubernetesCommonHelper.createDecorators(project, KUBERNETES, name, config, - metricsConfiguration, kubernetesClientConfiguration, annotations, labels, command, port, + metricsConfiguration, kubernetesClientConfiguration, annotations, labels, image, command, port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings)); diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseOpenshiftWithRemoteRegistry.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseOpenshiftWithRemoteRegistry.java index 0e711498e8ae8..72c1d5b27ebe1 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseOpenshiftWithRemoteRegistry.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseOpenshiftWithRemoteRegistry.java @@ -9,40 +9,29 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.openshift.api.model.BuildConfig; -import io.fabric8.openshift.api.model.DeploymentConfig; import io.fabric8.openshift.api.model.ImageStream; -public class BaseOpenshiftWithRemoteRegistry { +public class BaseOpenshiftWithRemoteRegistry extends BaseWithRemoteRegistry { public void assertGeneratedResources(String name, String tag, Path buildDir) throws IOException { - Path kubernetesDir = buildDir.resolve("kubernetes"); + List resourceList = getResources("openshift", buildDir); + assertGeneratedResources(name, tag, resourceList); + } - assertThat(kubernetesDir).isDirectoryContaining(p -> p.getFileName().endsWith("openshift.json")) - .isDirectoryContaining(p -> p.getFileName().endsWith("openshift.yml")); - List openshiftList = DeserializationUtil.deserializeAsList(kubernetesDir.resolve("openshift.yml")); + public void assertGeneratedResources(String name, String tag, List resourceList) throws IOException { + super.assertGeneratedResources(name, resourceList); - assertThat(openshiftList).filteredOn(h -> "DeploymentConfig".equals(h.getKind())).singleElement().satisfies(h -> { - assertThat(h.getMetadata()).satisfies(m -> { - assertThat(m.getName()).isEqualTo(name); - }); - assertThat(h).isInstanceOfSatisfying(DeploymentConfig.class, d -> { - assertThat(d.getSpec().getTemplate().getSpec().getImagePullSecrets()).singleElement().satisfies(l -> { - assertThat(l.getName()).isEqualTo(name + "-push-secret"); + assertThat(resourceList) + .filteredOn( + h -> "Secret".equals(h.getKind()) && h.getMetadata().getName().equals(name + "-push-secret")) + .singleElement().satisfies(h -> { + assertThat(h).isInstanceOfSatisfying(Secret.class, s -> { + assertThat(s.getType()).isEqualTo("kubernetes.io/dockerconfigjson"); + assertThat(s.getData()).containsKey(".dockerconfigjson"); + }); }); - }); - }); - - assertThat(openshiftList).filteredOn(h -> "Secret".equals(h.getKind())).singleElement().satisfies(h -> { - assertThat(h.getMetadata()).satisfies(m -> { - assertThat(m.getName()).isEqualTo(name + "-push-secret"); - }); - assertThat(h).isInstanceOfSatisfying(Secret.class, s -> { - assertThat(s.getType()).isEqualTo("kubernetes.io/dockerconfigjson"); - assertThat(s.getData()).containsKey(".dockerconfigjson"); - }); - }); - assertThat(openshiftList).filteredOn(h -> "BuildConfig".equals(h.getKind())).singleElement().satisfies(h -> { + assertThat(resourceList).filteredOn(h -> "BuildConfig".equals(h.getKind())).singleElement().satisfies(h -> { assertThat(h.getMetadata()).satisfies(m -> { assertThat(m.getName()).isEqualTo(name); }); @@ -52,7 +41,7 @@ public void assertGeneratedResources(String name, String tag, Path buildDir) thr }); }); - assertThat(openshiftList) + assertThat(resourceList) .filteredOn(h -> "ImageStream".equals(h.getKind()) && h.getMetadata().getName().equals(name)) .singleElement().satisfies(h -> { assertThat(h).isInstanceOfSatisfying(ImageStream.class, i -> { diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseWithRemoteRegistry.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseWithRemoteRegistry.java new file mode 100644 index 0000000000000..c807637b5a071 --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/BaseWithRemoteRegistry.java @@ -0,0 +1,55 @@ +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 io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.KubernetesList; +import io.fabric8.kubernetes.api.model.KubernetesListBuilder; +import io.fabric8.kubernetes.api.model.LocalObjectReference; +import io.fabric8.kubernetes.api.model.PodSpecFluent; +import io.fabric8.kubernetes.api.model.Secret; + +public class BaseWithRemoteRegistry { + + public void assertGeneratedResources(String name, String target, Path buildDir) throws IOException { + List resourceList = getResources(target, buildDir); + assertGeneratedResources(name, resourceList); + } + + List getResources(String target, Path buildDir) throws IOException { + Path kubernetesDir = buildDir.resolve("kubernetes"); + + assertThat(kubernetesDir).isDirectoryContaining(p -> p.getFileName().endsWith(target + ".json")) + .isDirectoryContaining(p -> p.getFileName().endsWith(target + ".yml")); + return DeserializationUtil.deserializeAsList(kubernetesDir.resolve(target + ".yml")); + } + + public void assertGeneratedResources(String name, List resourceList) { + assertThat(resourceList).satisfies(r -> { + KubernetesList kubernetesList = new KubernetesListBuilder() + .addAllToItems(resourceList) + .accept(PodSpecFluent.class, spec -> { + assertThat(spec.buildImagePullSecrets()).singleElement().satisfies(e -> { + assertThat(e).isInstanceOfSatisfying(LocalObjectReference.class, l -> { + assertThat(l.getName()).isEqualTo(name + "-pull-secret"); + }); + }); + + }).build(); + }); + + assertThat(resourceList) + .filteredOn( + h -> "Secret".equals(h.getKind()) && h.getMetadata().getName().equals(name + "-pull-secret")) + .singleElement().satisfies(h -> { + assertThat(h).isInstanceOfSatisfying(Secret.class, s -> { + assertThat(s.getType()).isEqualTo("kubernetes.io/dockerconfigjson"); + assertThat(s.getData()).containsKey(".dockerconfigjson"); + }); + }); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithImagePushTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithImagePushTest.java new file mode 100644 index 0000000000000..0e7ffe8f3a0cc --- /dev/null +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithImagePushTest.java @@ -0,0 +1,40 @@ +package io.quarkus.it.kubernetes; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +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; + +public class KubernetesWithImagePushTest extends BaseWithRemoteRegistry { + + private static final String APP_NAME = "kubernetes-with-remote-image-push"; + + @RegisterExtension + static final QuarkusProdModeTest config = new QuarkusProdModeTest() + .withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class)) + .setApplicationName(APP_NAME) + .setApplicationVersion("0.1-SNAPSHOT") + .overrideConfigKey("quarkus.container-image.group", "user") + .overrideConfigKey("quarkus.container-image.image", "quay.io/user/" + APP_NAME + ":1.0") + .overrideConfigKey("quarkus.container-image.username", "me") + .overrideConfigKey("quarkus.container-image.password", "pass") + .overrideConfigKey("quarkus.kubernetes.generate-image-pull-secret", "true") + .setForcedDependencies(List.of( + Dependency.of("io.quarkus", "quarkus-kubernetes", Version.getVersion()), + Dependency.of("io.quarkus", "quarkus-container-image-docker", Version.getVersion()))); + + @ProdBuildResults + private ProdModeTestResults prodModeTestResults; + + @Test + public void assertGeneratedResources() throws IOException { + assertGeneratedResources(APP_NAME, "kubernetes", prodModeTestResults.getBuildDir()); + } +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteImagePushTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteImagePushTest.java index 77a70cc7fdda1..8b190e66f86fd 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteImagePushTest.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteImagePushTest.java @@ -12,6 +12,9 @@ import io.quarkus.test.ProdModeTestResults; import io.quarkus.test.QuarkusProdModeTest; +/** + * This is similar to OpenshiftWithRemoteRegistryPushTest, but uses `quarkus.container-image.image` instead. + */ public class OpenshiftWithRemoteImagePushTest extends BaseOpenshiftWithRemoteRegistry { private static final String APP_NAME = "openshift-with-remote-image-push"; @@ -25,6 +28,7 @@ public class OpenshiftWithRemoteImagePushTest extends BaseOpenshiftWithRemoteReg .overrideConfigKey("quarkus.container-image.image", "quay.io/user/" + APP_NAME + ":1.0") .overrideConfigKey("quarkus.container-image.username", "me") .overrideConfigKey("quarkus.container-image.password", "pass") + .overrideConfigKey("quarkus.openshift.generate-image-pull-secret", "true") .setForcedDependencies(List.of(Dependency.of("io.quarkus", "quarkus-openshift", Version.getVersion()))); @ProdBuildResults diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteRegistryPushTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteRegistryPushTest.java index b52d076f61510..b8590779be397 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteRegistryPushTest.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithRemoteRegistryPushTest.java @@ -25,6 +25,7 @@ public class OpenshiftWithRemoteRegistryPushTest extends BaseOpenshiftWithRemote .overrideConfigKey("quarkus.container-image.registry", "quay.io") .overrideConfigKey("quarkus.container-image.username", "me") .overrideConfigKey("quarkus.container-image.password", "pass") + .overrideConfigKey("quarkus.openshift.generate-image-pull-secret", "true") .setForcedDependencies(List.of(Dependency.of("io.quarkus", "quarkus-openshift", Version.getVersion()))); @ProdBuildResults