diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java index 101d3a5ff7a63b..62c43dec43d925 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/Constants.java @@ -36,6 +36,8 @@ public final class Constants { static final String S2I = "s2i"; static final String DEFAULT_S2I_IMAGE_NAME = "s2i-java"; //refers to the Dekorate default image. + static final String OPENSHIFT_INTERNAL_REGISTRY = "image-registry.openshift-image-registry.svc:5000"; + static final String KNATIVE = "knative"; static final String KNATIVE_SERVICE = "Service"; static final String KNATIVE_SERVICE_GROUP = "serving.knative.dev"; diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/EnableImageStreamLocalLookupPolicyDecorator.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/EnableImageStreamLocalLookupPolicyDecorator.java new file mode 100644 index 00000000000000..f27ababc67f8f8 --- /dev/null +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/EnableImageStreamLocalLookupPolicyDecorator.java @@ -0,0 +1,23 @@ +package io.quarkus.kubernetes.deployment; + +import io.dekorate.kubernetes.decorator.NamedResourceDecorator; +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.fabric8.openshift.api.model.ImageStreamSpecFluent; + +public class EnableImageStreamLocalLookupPolicyDecorator extends NamedResourceDecorator> { + + public EnableImageStreamLocalLookupPolicyDecorator() { + super("ImageStream", ANY); + } + + public EnableImageStreamLocalLookupPolicyDecorator(String name) { + super("ImageStream", name); + } + + @Override + public void andThenVisit(ImageStreamSpecFluent spec, ObjectMeta meta) { + spec.withNewLookupPolicy() + .withLocal() + .endLookupPolicy(); + } +} diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java index 38f874cafa6e03..40970c4a39ed87 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesDeployer.java @@ -5,7 +5,6 @@ import static io.quarkus.kubernetes.deployment.Constants.KNATIVE; import static io.quarkus.kubernetes.deployment.Constants.KUBERNETES; import static io.quarkus.kubernetes.deployment.Constants.MINIKUBE; -import static io.quarkus.kubernetes.deployment.Constants.OPENSHIFT; import java.io.File; import java.io.FileInputStream; @@ -30,7 +29,6 @@ import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.batch.v1.Job; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientException; import io.fabric8.kubernetes.client.dsl.Resource; @@ -160,7 +158,6 @@ private DeploymentTargetEntry determineDeploymentTarget( ContainerImageConfig containerImageConfig) { final DeploymentTargetEntry selectedTarget; - boolean checkForNamespaceGroupAlignment = false; List userSpecifiedDeploymentTargets = KubernetesConfigUtil.getExplictilyDeploymentTargets(); if (userSpecifiedDeploymentTargets.isEmpty()) { selectedTarget = targets.getEntriesSortedByPriority().get(0); @@ -184,22 +181,6 @@ private DeploymentTargetEntry determineDeploymentTarget( } } - if (OPENSHIFT.equals(selectedTarget.getName())) { - // We should ensure that we have image group and namespace alignment we are not using deployment triggers via DeploymentConfig. - if (!targets.getEntriesSortedByPriority().get(0).getKind().equals("DeploymentConfig")) { - checkForNamespaceGroupAlignment = true; - } - } - - //This might also be applicable in other scenarios too (e.g. Knative on Openshift), so we might need to make it slightly more generic. - if (checkForNamespaceGroupAlignment) { - Config config = Config.autoConfigure(null); - if (config.getNamespace() != null && !config.getNamespace().equals(containerImageInfo.getGroup())) { - log.warn("An openshift deployment was requested, but the container image group:" + containerImageInfo.getGroup() - + " is not aligned with the currently selected project:" + config.getNamespace() + "." - + "it is strongly advised to align them, or else the image might not be reachable."); - } - } return selectedTarget; } 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 6f731816ac42a2..842e6aec869e00 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 @@ -78,6 +78,12 @@ public static enum DeploymentResourceKind { @ConfigItem Optional partOf; + /** + * When this property is set to true, on deployment time the name of the project will be set as image group. + */ + @ConfigItem(defaultValue = "true") + boolean projectAsImageGroup; + /** * The name of the application. This value will be used for naming Kubernetes * resources like: 'Deployment', 'Service' and so on... 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 199b54be05228c..a06ccfd6c5c3f3 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 @@ -75,9 +75,9 @@ public class OpenshiftProcessor { private static final int OPENSHIFT_PRIORITY = DEFAULT_PRIORITY; - private static final String OPENSHIFT_INTERNAL_REGISTRY = "image-registry.openshift-image-registry.svc:5000"; private static final String DOCKERIO_REGISTRY = "docker.io"; private static final String OPENSHIFT_V3_APP = "app"; + private static final String ANY = null; @BuildStep public void checkOpenshift(ApplicationInfoBuildItem applicationInfo, Capabilities capabilities, OpenshiftConfig config, @@ -106,10 +106,7 @@ public void populateInternalRegistry(OpenshiftConfig openshiftConfig, ContainerI DeploymentResourceKind deploymentResourceKind = openshiftConfig.getDeploymentResourceKind(capabilities); if (deploymentResourceKind != DeploymentResourceKind.DeploymentConfig) { if (openshiftConfig.isOpenshiftBuildEnabled(containerImageConfig, capabilities)) { - // Images stored in internal openshift registry use the following pattern: - // 'image-registry.openshift-image-registry.svc:5000/{{ project name}}/{{ image name }}: {{image version }}. - // So, we need warn users if group does not match currently selected project. - containerImageRegistry.produce(new FallbackContainerImageRegistryBuildItem(OPENSHIFT_INTERNAL_REGISTRY)); + //Don't need fallback namespace, we use local lookup instead. } else { containerImageRegistry.produce(new FallbackContainerImageRegistryBuildItem(DOCKERIO_REGISTRY)); } @@ -291,6 +288,9 @@ public List createDecorators(ApplicationInfoBuildItem applic .build()))); }); + // Enalbe local lookup policy for all image streams + result.add(new DecoratorBuildItem(OPENSHIFT, new EnableImageStreamLocalLookupPolicyDecorator())); + // Handle custom s2i builder images baseImage.map(BaseImageInfoBuildItem::getImage).ifPresent(builderImage -> { String builderImageName = ImageUtil.getName(builderImage); @@ -381,4 +381,4 @@ void externalizeInitTasks( decorators); } } -} \ No newline at end of file +} diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithDeploymentResourceTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithDeploymentResourceTest.java index 4b86271cfdcbfc..b27c14c04a325a 100644 --- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithDeploymentResourceTest.java +++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/OpenshiftWithDeploymentResourceTest.java @@ -13,6 +13,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.openshift.api.model.ImageStream; import io.quarkus.builder.Version; import io.quarkus.maven.dependency.Dependency; import io.quarkus.test.ProdBuildResults; @@ -76,13 +77,22 @@ public void assertGeneratedResources() throws IOException { assertThat(t.getSpec()).satisfies(podSpec -> { assertThat(podSpec.getContainers()).singleElement().satisfies(container -> { assertThat(container.getImage()) - .isEqualTo( - "image-registry.openshift-image-registry.svc:5000/testme/openshift-with-deployment-resource:0.1-SNAPSHOT"); + .isEqualTo("testme/openshift-with-deployment-resource:0.1-SNAPSHOT"); }); }); }); }); }); }); + + assertThat(kubernetesList).filteredOn(r -> r instanceof ImageStream && r.getMetadata().getName().equals(NAME)) + .singleElement().satisfies(r -> { + assertThat(r).isInstanceOfSatisfying(ImageStream.class, i -> { + assertThat(i.getSpec()).satisfies(spec -> { + assertThat(spec.getLookupPolicy().getLocal()).isEqualTo(true); + }); + }); + }); + } }