diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/TaskUtil.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/TaskUtil.java index d0cb5eb93e..506c9464c0 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/TaskUtil.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/TaskUtil.java @@ -18,7 +18,6 @@ import org.eclipse.jkube.kit.build.service.docker.ImagePullManager; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; import org.eclipse.jkube.kit.common.KitLogger; -import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.service.BuildServiceConfig; import static org.eclipse.jkube.kit.build.service.docker.ImagePullManager.createImagePullManager; @@ -36,9 +35,7 @@ public static BuildServiceConfig.BuildServiceConfigBuilder buildServiceConfigBui kubernetesExtension.javaProject.getProperties()); return BuildServiceConfig.builder() .imagePullManager(imagePullManager) - .buildRecreateMode(BuildRecreateMode.fromParameter(kubernetesExtension.getBuildRecreateOrDefault())) .jKubeBuildStrategy(kubernetesExtension.getBuildStrategyOrDefault()) - .forcePull(kubernetesExtension.getForcePullOrDefault()) .buildDirectory(kubernetesExtension.javaProject.getBuildDirectory().getAbsolutePath()); } diff --git a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/task/TaskUtilTest.java b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/task/TaskUtilTest.java index a7d9e1349d..7b49e3022b 100644 --- a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/task/TaskUtilTest.java +++ b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/task/TaskUtilTest.java @@ -17,7 +17,6 @@ import org.eclipse.jkube.kit.build.service.docker.DockerAccessFactory; import org.eclipse.jkube.kit.common.KitLogger; import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; -import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.service.BuildServiceConfig; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -49,16 +48,13 @@ void buildServiceConfigBuilder_shouldInitializeBuildServiceConfigWithDefaults() // Then assertThat(buildServiceConfig) - .hasFieldOrPropertyWithValue("buildRecreateMode", BuildRecreateMode.none) .hasFieldOrPropertyWithValue("jKubeBuildStrategy", JKubeBuildStrategy.docker) - .hasFieldOrPropertyWithValue("forcePull", false) .hasFieldOrPropertyWithValue("buildDirectory", null); } @Test void buildServiceConfigBuilder_shouldInitializeBuildServiceConfigWithConfiguredValues() { // Given - extension.buildRecreate = "true"; extension.isForcePull = true; extension.buildStrategy = JKubeBuildStrategy.jib; when(extension.javaProject.getBuildDirectory().getAbsolutePath()).thenReturn("/tmp/foo"); @@ -68,9 +64,7 @@ void buildServiceConfigBuilder_shouldInitializeBuildServiceConfigWithConfiguredV // Then assertThat(buildServiceConfig) - .hasFieldOrPropertyWithValue("buildRecreateMode", BuildRecreateMode.all) .hasFieldOrPropertyWithValue("jKubeBuildStrategy", JKubeBuildStrategy.jib) - .hasFieldOrPropertyWithValue("forcePull", true) .hasFieldOrPropertyWithValue("buildDirectory", "/tmp/foo"); } diff --git a/gradle-plugin/openshift/src/main/java/org/eclipse/jkube/gradle/plugin/task/OpenShiftBuildTask.java b/gradle-plugin/openshift/src/main/java/org/eclipse/jkube/gradle/plugin/task/OpenShiftBuildTask.java index 8dd0d967c3..66790ff468 100644 --- a/gradle-plugin/openshift/src/main/java/org/eclipse/jkube/gradle/plugin/task/OpenShiftBuildTask.java +++ b/gradle-plugin/openshift/src/main/java/org/eclipse/jkube/gradle/plugin/task/OpenShiftBuildTask.java @@ -15,10 +15,19 @@ import javax.inject.Inject; +import org.eclipse.jkube.generator.api.DefaultGeneratorManager; import org.eclipse.jkube.gradle.plugin.OpenShiftExtension; +import org.eclipse.jkube.kit.build.api.helper.ImageConfigResolver; +import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.resource.PlatformMode; import org.eclipse.jkube.kit.config.service.BuildServiceConfig; +import java.io.IOException; +import java.util.List; + +import static org.eclipse.jkube.kit.build.api.helper.ConfigHelper.initImageConfiguration; +import static org.eclipse.jkube.kit.common.util.BuildReferenceDateUtil.getBuildTimestamp; + public class OpenShiftBuildTask extends KubernetesBuildTask implements OpenShiftJKubeTask { @Inject @@ -31,15 +40,29 @@ public OpenShiftBuildTask(Class extensionClass) { @Override protected BuildServiceConfig.BuildServiceConfigBuilder buildServiceConfigBuilder() { return super.buildServiceConfigBuilder() - .openshiftPullSecret(getOpenShiftExtension().getOpenshiftPullSecretOrDefault()) - .s2iBuildNameSuffix(getOpenShiftExtension().getS2iBuildNameSuffixOrDefault()) - .s2iImageStreamLookupPolicyLocal(getOpenShiftExtension().getS2iImageStreamLookupPolicyLocalOrDefault()) - .openshiftPushSecret(getOpenShiftExtension().getOpenshiftPushSecretOrDefault()) .resourceConfig(getOpenShiftExtension().resources) - .buildOutputKind(getOpenShiftExtension().getBuildOutputKindOrDefault()) .enricherTask(e -> { enricherManager.enrich(PlatformMode.kubernetes, e); enricherManager.enrich(PlatformMode.openshift, e); }); } + + @Override + protected List resolveImages(ImageConfigResolver imageConfigResolver) throws IOException { + return initImageConfiguration( + getBuildTimestamp(null, null, getOpenShiftExtension().javaProject.getBuildDirectory().getAbsolutePath(), + DOCKER_BUILD_TIMESTAMP), + getOpenShiftExtension().images, imageConfigResolver, kitLogger, + getOpenShiftExtension().getFilter().getOrNull(), + new DefaultGeneratorManager(initGeneratorContextBuilder().build()), + false, + jKubeServiceHub.getConfiguration(), + getOpenShiftExtension().getForcePullOrDefault(), + getOpenShiftExtension().getS2iBuildNameSuffixOrDefault(), + getOpenShiftExtension().getS2iImageStreamLookupPolicyLocalOrDefault(), + getOpenShiftExtension().getOpenshiftPullSecretOrDefault(), + getOpenShiftExtension().getOpenshiftPushSecretOrDefault(), + getOpenShiftExtension().getBuildOutputKindOrDefault(), + getOpenShiftExtension().getBuildRecreateOrDefault()); + } } diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelper.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelper.java index e28c7b08bc..0318205a75 100644 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelper.java +++ b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelper.java @@ -15,6 +15,7 @@ import org.eclipse.jkube.kit.build.api.config.handler.property.PropertyConfigHandler; import org.eclipse.jkube.kit.build.api.config.handler.property.PropertyMode; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jkube.kit.common.JKubeConfiguration; import org.eclipse.jkube.kit.config.image.GeneratorManager; import org.eclipse.jkube.kit.config.image.ImageConfiguration; @@ -129,6 +130,35 @@ public static boolean matchesConfiguredImages(String imageList, ImageConfigurati return imagesAllowed.contains(imageConfig.getName()) || imagesAllowed.contains(imageConfig.getAlias()); } + + private static BuildConfiguration mergeGlobalConfigParamsWithSingleImageBuildConfig(BuildConfiguration build, boolean forcePull, String s2iBuildNameSuffix, boolean s2iImageStreamLookupPolicyLocal, + String openshiftPullSecret, String openshiftPushSecret, String buildOutputKind, String buildRecreateMode) { + BuildConfiguration.BuildConfigurationBuilder buildConfigBuilder = build.toBuilder(); + if (!build.isOpenshiftForcePull() && forcePull) { + buildConfigBuilder.openshiftForcePull(true); + } + if (StringUtils.isBlank(build.getOpenshiftS2iBuildNameSuffix()) && + StringUtils.isNotBlank(s2iBuildNameSuffix)) { + buildConfigBuilder.openshiftS2iBuildNameSuffix(s2iBuildNameSuffix); + } + if (!build.isOpenshiftS2iImageStreamLookupPolicyLocal() && s2iImageStreamLookupPolicyLocal) { + buildConfigBuilder.openshiftS2iImageStreamLookupPolicyLocal(true); + } + if (StringUtils.isBlank(build.getOpenshiftPullSecret()) && StringUtils.isNotBlank(openshiftPullSecret)) { + buildConfigBuilder.openshiftPullSecret(openshiftPullSecret); + } + if (StringUtils.isBlank(build.getOpenshiftPushSecret()) && StringUtils.isNotBlank(openshiftPushSecret)) { + buildConfigBuilder.openshiftPushSecret(openshiftPushSecret); + } + if (StringUtils.isBlank(build.getOpenshiftBuildOutputKind()) && StringUtils.isNotBlank(buildOutputKind)) { + buildConfigBuilder.openshiftBuildOutputKind(buildOutputKind); + } + if (StringUtils.isBlank(build.getOpenshiftBuildRecreateMode()) && StringUtils.isNotBlank(buildRecreateMode)) { + buildConfigBuilder.openshiftBuildRecreateMode(buildRecreateMode); + } + return buildConfigBuilder.build(); + } + // =========================================================================================================== // Filter image configuration on name. Given filter should be either null (no filter) or a comma separated @@ -167,6 +197,15 @@ private static void verifyImageNames(List ret) { } public static List initImageConfiguration(Date buildTimeStamp, List unresolvedImages, ImageConfigResolver imageConfigResolver, KitLogger log, String filter, GeneratorManager generatorManager, boolean isPrePackagePhase, JKubeConfiguration jKubeConfiguration) { + return initImageConfiguration(buildTimeStamp, unresolvedImages, imageConfigResolver, log, filter, generatorManager, isPrePackagePhase, jKubeConfiguration, false, null, false, null, null, null, null); + } + + public static List initImageConfiguration(Date buildTimeStamp, List unresolvedImages, + ImageConfigResolver imageConfigResolver, KitLogger log, String filter, + GeneratorManager generatorManager, boolean isPrePackagePhase, + JKubeConfiguration jKubeConfiguration, boolean isForcePull, + String s2iBuildNameSuffix, boolean s2iImageStreamLookupPolicyLocal, + String openshiftPullSecret, String openshiftPushSecret, String buildOutputKind, String buildRecreateMode) { final ImageNameFormatter imageNameFormatter = new ImageNameFormatter(jKubeConfiguration.getProject(), buildTimeStamp); // Resolve images final List resolvedImages = ConfigHelper.resolveImages( @@ -191,6 +230,8 @@ public static List initImageConfiguration(Date buildTimeStam for (ImageConfiguration imageConfiguration : resolvedImages) { imageConfiguration.setName(imageNameFormatter.format(imageConfiguration.getName())); if (imageConfiguration.getBuild() != null) { + BuildConfiguration updatedBuild = mergeGlobalConfigParamsWithSingleImageBuildConfig(imageConfiguration.getBuild(), isForcePull, s2iBuildNameSuffix, s2iImageStreamLookupPolicyLocal, openshiftPullSecret, openshiftPushSecret, buildOutputKind, buildRecreateMode); + imageConfiguration.setBuild(updatedBuild); imageConfiguration.getBuild().initAndValidate(); } printDockerfileInfoIfDockerfileMode(imageConfiguration, log, jKubeConfiguration); diff --git a/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelperTest.java b/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelperTest.java index b09c2a87d6..f3dc4fb858 100644 --- a/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelperTest.java +++ b/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/ConfigHelperTest.java @@ -20,6 +20,8 @@ import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.io.File; @@ -67,102 +69,217 @@ void setUp() { .build(); } - @Test - void initImageConfiguration_withSimpleImageConfiguration_shouldReturnImageConfiguration() { - // Given - ImageConfiguration dummyImageConfiguration = createNewDummyImageConfiguration(); - List images = new ArrayList<>(); - images.add(dummyImageConfiguration); - when(imageConfigResolver.resolve(dummyImageConfiguration, javaProject)).thenReturn(images); - when(generatorManager.generate(images, false)).thenReturn(images); - - // When - List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); - - // Then - assertThat(resolvedImages).isNotNull() - .singleElement() - .isEqualTo(dummyImageConfiguration); - } + @Nested + @DisplayName("initImageConfiguration") + class InitImageConfiguration { + private ImageConfiguration imageConfiguration; + private List images; - @Test - void initImageConfiguration_withSimpleDockerFileInProjectBaseDir_shouldCreateImageConfiguration() { - List images = new ArrayList<>(); - File dockerFile = new File(Objects.requireNonNull(getClass().getResource("/dummy-javaproject/Dockerfile")).getFile()); - jKubeConfiguration = jKubeConfiguration.toBuilder() - .project(javaProject.toBuilder() - .baseDirectory(dockerFile.getParentFile()) - .build()) - .build(); + @BeforeEach + void setUp() { + imageConfiguration = createNewDummyImageConfiguration(); + images = new ArrayList<>(); + images.add(imageConfiguration); + when(imageConfigResolver.resolve(imageConfiguration, javaProject)).thenReturn(images); + when(generatorManager.generate(images, false)).thenReturn(images); + } - // When - List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); + @Test + void simpleImageConfiguration_shouldReturnImageConfiguration() { + // When + List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); - // Then - assertThat(resolvedImages).isNotNull() - .singleElement() - .hasFieldOrPropertyWithValue("name", "jkube/test-java-project:latest") - .hasFieldOrPropertyWithValue("build.dockerFile", dockerFile) - .hasFieldOrPropertyWithValue("build.ports", Collections.singletonList("8080")); - } + // Then + assertThat(resolvedImages).isNotNull() + .singleElement() + .isEqualTo(imageConfiguration); + } - @Test - void initImageConfiguration_withSimpleDockerFileModeEnabledAndImageConfigurationWithNoBuild_shouldModifyExistingImageConfiguration() { - ImageConfiguration dummyImageConfiguration = ImageConfiguration.builder() - .name("imageconfiguration-no-build:latest") - .build(); - List images = new ArrayList<>(); - images.add(dummyImageConfiguration); - File dockerFile = new File(getClass().getResource("/dummy-javaproject/Dockerfile").getFile()); - jKubeConfiguration = jKubeConfiguration.toBuilder() - .project(javaProject.toBuilder() - .baseDirectory(dockerFile.getParentFile()) - .build()) - .build(); - when(imageConfigResolver.resolve(dummyImageConfiguration, jKubeConfiguration.getProject())).thenReturn(images); - when(generatorManager.generate(images, false)).thenReturn(images); - - // When - List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); - - // Then - assertThat(resolvedImages).isNotNull() - .singleElement() - .hasFieldOrPropertyWithValue("name", "imageconfiguration-no-build:latest") - .hasFieldOrPropertyWithValue("build.dockerFile", dockerFile) - .hasFieldOrPropertyWithValue("build.ports", Collections.singletonList("8080")); - verify(logger).info(eq("Using Dockerfile: %s"), anyString()); - verify(logger).info(eq("Using Docker Context Directory: %s"), any(File.class)); - } + @Test + void simpleDockerFileInProjectBaseDir_shouldCreateImageConfiguration() { + List images = new ArrayList<>(); + File dockerFile = new File(Objects.requireNonNull(getClass().getResource("/dummy-javaproject/Dockerfile")).getFile()); + jKubeConfiguration = jKubeConfiguration.toBuilder() + .project(javaProject.toBuilder() + .baseDirectory(dockerFile.getParentFile()) + .build()) + .build(); - @Test - void initImageConfiguration_whenImageConfigurationNameBlank_thenThrowException() { - // Given - ImageConfiguration imageConfiguration = ImageConfiguration.builder().build(); - List images = Collections.singletonList(imageConfiguration); - when(imageConfigResolver.resolve(imageConfiguration, javaProject)).thenReturn(images); + // When + List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); - // When + Then - assertThatIllegalArgumentException() - .isThrownBy(() -> ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration)) - .withMessage("Configuration error: must have a non-null "); - } + // Then + assertThat(resolvedImages).isNotNull() + .singleElement() + .hasFieldOrPropertyWithValue("name", "jkube/test-java-project:latest") + .hasFieldOrPropertyWithValue("build.dockerFile", dockerFile) + .hasFieldOrPropertyWithValue("build.ports", Collections.singletonList("8080")); + } - @Test - void initImageConfiguration_whenNoMatchForImageFilter_thenLogWarning() { - // Given - ImageConfiguration dummyImageConfiguration = createNewDummyImageConfiguration(); - List images = Collections.singletonList(createNewDummyImageConfiguration()); - when(imageConfigResolver.resolve(dummyImageConfiguration, javaProject)).thenReturn(images); - when(generatorManager.generate(images, false)).thenReturn(images); + @Test + void simpleDockerFileModeEnabledAndImageConfigurationWithNoBuild_shouldModifyExistingImageConfiguration() { + imageConfiguration = ImageConfiguration.builder() + .name("imageconfiguration-no-build:latest") + .build(); + images = Collections.singletonList(imageConfiguration); + File dockerFile = new File(getClass().getResource("/dummy-javaproject/Dockerfile").getFile()); + jKubeConfiguration = jKubeConfiguration.toBuilder() + .project(javaProject.toBuilder() + .baseDirectory(dockerFile.getParentFile()) + .build()) + .build(); + when(imageConfigResolver.resolve(imageConfiguration, jKubeConfiguration.getProject())).thenReturn(images); + when(generatorManager.generate(images, false)).thenReturn(images); - // When - ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, "i-dont-exist", generatorManager, false, jKubeConfiguration); + // When + List resolvedImages = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); - // Then - verify(logger).warn("None of the resolved images [%s] match the configured filter '%s'", "foo/bar:latest", "i-dont-exist"); + // Then + assertThat(resolvedImages).isNotNull() + .singleElement() + .hasFieldOrPropertyWithValue("name", "imageconfiguration-no-build:latest") + .hasFieldOrPropertyWithValue("build.dockerFile", dockerFile) + .hasFieldOrPropertyWithValue("build.ports", Collections.singletonList("8080")); + verify(logger).info(eq("Using Dockerfile: %s"), anyString()); + verify(logger).info(eq("Using Docker Context Directory: %s"), any(File.class)); + } + + @Test + void whenImageConfigurationNameBlank_thenThrowException() { + // Given + imageConfiguration = ImageConfiguration.builder().build(); + images = Collections.singletonList(imageConfiguration); + when(imageConfigResolver.resolve(imageConfiguration, javaProject)).thenReturn(images); + + // When + Then + assertThatIllegalArgumentException() + .isThrownBy(() -> ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration)) + .withMessage("Configuration error: must have a non-null "); + } + + @Test + void initImageConfiguration_whenNoMatchForImageFilter_thenLogWarning() { + // When + ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, "i-dont-exist", generatorManager, false, jKubeConfiguration); + + // Then + verify(logger).warn("None of the resolved images [%s] match the configured filter '%s'", "foo/bar:latest", "i-dont-exist"); + } + + @Nested + @DisplayName("merge configuration parameters for OpenShift S2I build into Image Build configuration") + class MergeOpenShiftS2IImageConfigParams { + @Test + @DisplayName("zero configuration, do not set anything in image build configuration") + void whenNoConfigurationProvided_thenDoNotSetInBuildConfig() { + // When + List result = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration, false, null, false, null, null, null, null); + + // Then + assertThat(result) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", false) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", null) + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", false) + .hasFieldOrPropertyWithValue("openshiftPullSecret", null) + .hasFieldOrPropertyWithValue("openshiftPushSecret", null) + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", null) + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", null); + } + + @Test + @DisplayName("image Configuration, then fields retained in Image Configuration") + void whenProvidedInImageConfiguration_thenDoNotUpdateBuildConfig() { + // Given + imageConfiguration = imageConfiguration.toBuilder() + .build(BuildConfiguration.builder() + .openshiftForcePull(true) + .openshiftS2iBuildNameSuffix("-custom") + .openshiftS2iImageStreamLookupPolicyLocal(true) + .openshiftPushSecret("push-secret") + .openshiftPullSecret("pull-secret") + .openshiftBuildOutputKind("ImageStreamTag") + .openshiftBuildRecreateMode("buildConfig") + .build()) + .build(); + images = Collections.singletonList(imageConfiguration); + when(imageConfigResolver.resolve(imageConfiguration, javaProject)).thenReturn(images); + when(generatorManager.generate(images, false)).thenReturn(images); + + // When + List result = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration); + + // Then + assertThat(result) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", true) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", "-custom") + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", true) + .hasFieldOrPropertyWithValue("openshiftPullSecret", "pull-secret") + .hasFieldOrPropertyWithValue("openshiftPushSecret", "push-secret") + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", "ImageStreamTag") + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", "buildConfig"); + } + + @Test + @DisplayName("plugin configuration, then fields merged in final Image Configuration") + void whenProvidedViaPluginConfiguration_thenSetInBuildConfig() { + // When + List result = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration, true, "-custom", true, "pull-secret", "push-secret", "ImageStreamTag", "buildConfig"); + + // Then + assertThat(result) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", true) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", "-custom") + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", true) + .hasFieldOrPropertyWithValue("openshiftPullSecret", "pull-secret") + .hasFieldOrPropertyWithValue("openshiftPushSecret", "push-secret") + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", "ImageStreamTag") + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", "buildConfig"); + } + + @Test + @DisplayName("plugin configuration and image configuration, then fields retained in Image Configuration") + void whenProvidedViaBothPluginAndImageConfiguration_thenDoNotModifyConfigurationSetInBuildConfig() { + // Given + imageConfiguration = imageConfiguration.toBuilder() + .build(BuildConfiguration.builder() + .openshiftForcePull(true) + .openshiftS2iBuildNameSuffix("-custom-via-image-config") + .openshiftS2iImageStreamLookupPolicyLocal(true) + .openshiftPushSecret("push-secret-via-image-config") + .openshiftPullSecret("pull-secret-via-image-config") + .openshiftBuildOutputKind("ImageStreamTag-via-image-config") + .openshiftBuildRecreateMode("buildConfig-via-image-config") + .build()) + .build(); + images = Collections.singletonList(imageConfiguration); + when(imageConfigResolver.resolve(imageConfiguration, javaProject)).thenReturn(images); + when(generatorManager.generate(images, false)).thenReturn(images); + + // When + List result = ConfigHelper.initImageConfiguration(new Date(), images, imageConfigResolver, logger, null, generatorManager, false, jKubeConfiguration, true, "-custom-via-plugin-config", true, "pull-secret-via-plugin-config", "push-secret-via-plugin-config", "ImageStreamTag-via-plugin-config", "buildConfig-via-plugin-config"); + + // Then + assertThat(result) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", true) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", "-custom-via-image-config") + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", true) + .hasFieldOrPropertyWithValue("openshiftPullSecret", "pull-secret-via-image-config") + .hasFieldOrPropertyWithValue("openshiftPushSecret", "push-secret-via-image-config") + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", "ImageStreamTag-via-image-config") + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", "buildConfig-via-image-config"); + } + } } + @Test void validateExternalPropertyActivation_withMultipleImagesWithoutExplicitExternalConfig_shouldThrowException() { // Given diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildConfiguration.java index d2ffca8ab8..0e87000bee 100644 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildConfiguration.java +++ b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildConfiguration.java @@ -328,6 +328,66 @@ public class BuildConfiguration implements Serializable { @Singular("addCacheFrom") private List cacheFrom; + /** + * While creating a BuildConfig, By default, if the builder image specified in the + * build configuration is available locally on the node, that image will be used. + *

+ * ForcePull to override the local image and refresh it from the registry to which the image stream points. + *

+ * This field is applicable in case of s2i build strategy + */ + private boolean openshiftForcePull; + /** + * The S2I binary builder BuildConfig name suffix appended to the image name to avoid + * clashing with the underlying BuildConfig for the Jenkins pipeline + *

+ * This field is applicable in case of OpenShift s2i build strategy + */ + private String openshiftS2iBuildNameSuffix; + /** + * Allow the ImageStream used in the S2I binary build to be used in standard + * Kubernetes resources such as Deployment or StatefulSet. + *

+ * This field is only applicable in case of OpenShift s2i build strategy + */ + private boolean openshiftS2iImageStreamLookupPolicyLocal; + /** + * The name of pullSecret to be used to pull the base image in case pulling from a protected + * registry which requires authentication. + *

+ * This field is applicable in case of OpenShift s2i build strategy + */ + private String openshiftPullSecret; + /** + * The name of pushSecret to be used to push the final image in case pushing from a protected + * registry which requires authentication. + *

+ * This field is applicable in case of OpenShift s2i build strategy + */ + private String openshiftPushSecret; + /** + * Allow specifying in which registry to push the container image at the end of the build. + * If the output kind is ImageStreamTag, then the image will be pushed to the internal OpenShift registry. + * If the output is of type DockerImage, then the name of the output reference will be used as a Docker push specification. + *

+ * This field is applicable in case of OpenShift s2i build strategy + */ + private String openshiftBuildOutputKind; + + /** + * How the OpenShift resource objects associated with the build should be treated when they already exist + + * buildConfig or bc : Only the BuildConfig is recreated + * all or is : Only the ImageStream is recreated + * all : Both, BuildConfig and ImageStream are recreated + * none : Neither BuildConfig nor ImageStream is recreated + * The default is none. If you provide the property without value then all is assumed, so everything gets recreated. + * + *

+ * This field is applicable in case of OpenShift s2i build strategy + */ + private String openshiftBuildRecreateMode; + public boolean isDockerFileMode() { return dockerFile != null || contextDir != null; } diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/BuildServiceConfig.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/BuildServiceConfig.java index 4517a0777d..0c4b7bf80f 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/BuildServiceConfig.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/BuildServiceConfig.java @@ -22,7 +22,6 @@ import org.eclipse.jkube.kit.build.service.docker.ImagePullManager; import org.eclipse.jkube.kit.build.service.docker.helper.Task; import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; -import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.resource.ResourceConfig; import java.io.File; @@ -36,21 +35,13 @@ @Getter @EqualsAndHashCode public class BuildServiceConfig { - - private BuildRecreateMode buildRecreateMode; private JKubeBuildStrategy jKubeBuildStrategy; - private boolean forcePull; - private String s2iBuildNameSuffix; - private String openshiftPullSecret; - private String openshiftPushSecret; private Task enricherTask; private String buildDirectory; private Attacher attacher; private ImagePullManager imagePullManager; - private boolean s2iImageStreamLookupPolicyLocal; private ResourceConfig resourceConfig; private File resourceDir; - private String buildOutputKind; public void attachArtifact(String classifier, File destFile) { if (attacher != null) { diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtils.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtils.java index d524e9a9b8..7774b94cfd 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtils.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtils.java @@ -72,10 +72,10 @@ protected static File createBuildArchive(JKubeServiceHub jKubeServiceHub, ImageC * Returns the applicable name for the S2I Build resource considering the provided {@link ImageName} and * {@link BuildServiceConfig}. */ - static String computeS2IBuildName(BuildServiceConfig config, ImageName imageName) { + static String computeS2IBuildName(ImageConfiguration imageConfiguration, BuildServiceConfig config, ImageName imageName) { final StringBuilder s2IBuildName = new StringBuilder(resolveImageStreamName(imageName)); - if (!StringUtils.isEmpty(config.getS2iBuildNameSuffix())) { - s2IBuildName.append(config.getS2iBuildNameSuffix()); + if (!StringUtils.isEmpty(imageConfiguration.getBuild().getOpenshiftS2iBuildNameSuffix())) { + s2IBuildName.append(imageConfiguration.getBuild().getOpenshiftS2iBuildNameSuffix()); } else if (config.getJKubeBuildStrategy() == JKubeBuildStrategy.s2i) { s2IBuildName.append(DEFAULT_S2I_BUILD_SUFFIX); } @@ -149,7 +149,7 @@ protected static BuildStrategy createBuildStrategy( .withName(fromName) .withNamespace(StringUtils.isEmpty(fromNamespace) ? null : fromNamespace) .endFrom() - .withForcePull(config.isForcePull()) + .withForcePull(imageConfig.getBuild().isOpenshiftForcePull()) .endSourceStrategy() .build(); if (openshiftPullSecret != null) { @@ -163,16 +163,16 @@ protected static BuildStrategy createBuildStrategy( } } - protected static BuildOutput createBuildOutput(BuildServiceConfig config, ImageName imageName) { - final String buildOutputKind = Optional.ofNullable(config.getBuildOutputKind()).orElse(DEFAULT_BUILD_OUTPUT_KIND); + protected static BuildOutput createBuildOutput(ImageConfiguration imageConfiguration, ImageName imageName) { + final String buildOutputKind = Optional.ofNullable(imageConfiguration.getBuild().getOpenshiftBuildOutputKind()).orElse(DEFAULT_BUILD_OUTPUT_KIND); final String outputImageStreamTag = resolveImageStreamName(imageName) + ":" + (imageName.getTag() != null ? imageName.getTag() : "latest"); final BuildOutputBuilder buildOutputBuilder = new BuildOutputBuilder(); buildOutputBuilder.withNewTo().withKind(buildOutputKind).withName(outputImageStreamTag).endTo(); if (DOCKER_IMAGE.equals(buildOutputKind)) { buildOutputBuilder.editTo().withName(imageName.getFullName()).endTo(); } - if(StringUtils.isNotBlank(config.getOpenshiftPushSecret())) { - buildOutputBuilder.withNewPushSecret().withName(config.getOpenshiftPushSecret()).endPushSecret(); + if(StringUtils.isNotBlank(imageConfiguration.getBuild().getOpenshiftPushSecret())) { + buildOutputBuilder.withNewPushSecret().withName(imageConfiguration.getBuild().getOpenshiftPushSecret()).endPushSecret(); } return buildOutputBuilder.build(); } diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildService.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildService.java index b6842cb34d..ee04dd237c 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildService.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildService.java @@ -39,6 +39,7 @@ import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.eclipse.jkube.kit.common.JKubeConfiguration; import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; +import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.resource.RuntimeMode; import org.eclipse.jkube.kit.config.service.AbstractImageBuildService; import org.eclipse.jkube.kit.config.service.BuildServiceConfig; @@ -138,7 +139,7 @@ public void buildSingleImage(ImageConfiguration imageConfig) throws JKubeService KubernetesListBuilder builder = new KubernetesListBuilder(); // Check for buildconfig / imagestream / pullSecret and create them if necessary - String openshiftPullSecret = buildServiceConfig.getOpenshiftPullSecret(); + String openshiftPullSecret = imageConfig.getBuild().getOpenshiftPullSecret(); final boolean usePullSecret = checkOrCreatePullSecret(client, builder, openshiftPullSecret, applicableImageConfig); if (usePullSecret) { buildName = updateOrCreateBuildConfig(buildServiceConfig, client, builder, applicableImageConfig, openshiftPullSecret); @@ -146,8 +147,8 @@ public void buildSingleImage(ImageConfiguration imageConfig) throws JKubeService buildName = updateOrCreateBuildConfig(buildServiceConfig, client, builder, applicableImageConfig, null); } - if (buildServiceConfig.getBuildOutputKind() == null || IMAGE_STREAM_TAG.equals(buildServiceConfig.getBuildOutputKind())) { - checkOrCreateImageStream(buildServiceConfig, client, builder, resolveImageStreamName(imageName)); + if (imageConfig.getBuild().getOpenshiftBuildOutputKind() == null || IMAGE_STREAM_TAG.equals(imageConfig.getBuild().getOpenshiftBuildOutputKind())) { + checkOrCreateImageStream(applicableImageConfig, client, builder, resolveImageStreamName(imageName)); applyBuild(buildName, dockerTar, builder); @@ -201,10 +202,10 @@ public void postProcess() { protected String updateOrCreateBuildConfig(BuildServiceConfig config, OpenShiftClient client, KubernetesListBuilder builder, ImageConfiguration imageConfig, String openshiftPullSecret) { ImageName imageName = new ImageName(imageConfig.getName()); - String buildName = computeS2IBuildName(config, imageName); + String buildName = computeS2IBuildName(imageConfig, config, imageName); BuildStrategy buildStrategyResource = createBuildStrategy(jKubeServiceHub, imageConfig, openshiftPullSecret); - BuildOutput buildOutput = createBuildOutput(config, imageName); + BuildOutput buildOutput = createBuildOutput(imageConfig, imageName); // Fetch existing build config BuildConfig buildConfig = client.buildConfigs().inNamespace(applicableOpenShiftNamespace).withName(buildName).get(); @@ -213,7 +214,7 @@ protected String updateOrCreateBuildConfig(BuildServiceConfig config, OpenShiftC BuildConfigSpec spec = OpenShiftBuildServiceUtils.getBuildConfigSpec(buildConfig); validateSourceType(buildName, spec); - if (config.getBuildRecreateMode().isBuildConfig()) { + if (BuildRecreateMode.fromParameter(imageConfig.getBuild().getOpenshiftBuildRecreateMode()).isBuildConfig()) { // Delete and recreate afresh client.buildConfigs().inNamespace(applicableOpenShiftNamespace).withName(buildName).delete(); return createBuildConfig(builder, buildName, buildStrategyResource, buildOutput); @@ -235,7 +236,7 @@ ImageConfiguration getApplicableImageConfiguration(ImageConfiguration imageConfi imageConfig.getBuildConfiguration().getAssembly().getFlattenedClone(jKubeServiceHub.getConfiguration())) .build()); } - if (buildServiceConfig.getBuildOutputKind() != null && buildServiceConfig.getBuildOutputKind().equals(DOCKER_IMAGE)) { + if (imageConfig.getBuild().getOpenshiftBuildOutputKind() != null && imageConfig.getBuild().getOpenshiftBuildOutputKind().equals(DOCKER_IMAGE)) { String applicableRegistry = getApplicablePushRegistryFrom(imageConfig, registryConfig); applicableImageConfigBuilder.name(new ImageName(imageConfig.getName()).getFullName(applicableRegistry)); } @@ -402,9 +403,9 @@ private boolean updateSecret(OpenShiftClient client, String pullSecretName, Map< return true; } - private void checkOrCreateImageStream(BuildServiceConfig config, OpenShiftClient client, KubernetesListBuilder builder, String imageStreamName) { + private void checkOrCreateImageStream(ImageConfiguration applicableImageConfig, OpenShiftClient client, KubernetesListBuilder builder, String imageStreamName) { boolean hasImageStream = client.imageStreams().inNamespace(applicableOpenShiftNamespace).withName(imageStreamName).get() != null; - if (hasImageStream && config.getBuildRecreateMode().isImageStream()) { + if (hasImageStream && BuildRecreateMode.fromParameter(applicableImageConfig.getBuild().getOpenshiftBuildRecreateMode()).isImageStream()) { client.imageStreams().inNamespace(applicableOpenShiftNamespace).withName(imageStreamName).delete(); hasImageStream = false; } @@ -416,7 +417,7 @@ private void checkOrCreateImageStream(BuildServiceConfig config, OpenShiftClient .endMetadata() .withNewSpec() .withNewLookupPolicy() - .withLocal(config.isS2iImageStreamLookupPolicyLocal()) + .withLocal(applicableImageConfig.getBuild().isOpenshiftS2iImageStreamLookupPolicyLocal()) .endLookupPolicy() .endSpec() .build() diff --git a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceTest.java b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceTest.java index 550f2590f2..d7b82f204c 100644 --- a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceTest.java +++ b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceTest.java @@ -136,9 +136,9 @@ void build_withImageBuildConfigurationSkipEnabled_shouldNotBuildImage() throws J @Test void getApplicableImageConfiguration_withRegistryInImageConfigurationAndDockerImageBuildOutput_shouldAppendRegistryToImageName() { // Given - when(jKubeServiceHub.getBuildServiceConfig()).thenReturn(BuildServiceConfig.builder() - .buildOutputKind("DockerImage") - .build()); + imageConfiguration = imageConfiguration.toBuilder() + .build(imageConfiguration.getBuild().toBuilder().openshiftBuildOutputKind("DockerImage").build()) + .build(); OpenshiftBuildService openshiftBuildService = new OpenshiftBuildService(jKubeServiceHub); // When @@ -152,9 +152,9 @@ void getApplicableImageConfiguration_withRegistryInImageConfigurationAndDockerIm @Test void getApplicableImageConfiguration_withRegistryInImageConfiguration_shouldNotAppendRegistryToImageName() { // Given - when(jKubeServiceHub.getBuildServiceConfig()).thenReturn(BuildServiceConfig.builder() - .buildOutputKind("ImageStreamTag") - .build()); + imageConfiguration = imageConfiguration.toBuilder() + .build(imageConfiguration.getBuild().toBuilder().openshiftBuildOutputKind("ImageStreamTag").build()) + .build(); OpenshiftBuildService openshiftBuildService = new OpenshiftBuildService(jKubeServiceHub); // When diff --git a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtilsTest.java b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtilsTest.java index e662b45faf..d4df715331 100644 --- a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtilsTest.java +++ b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenShiftBuildServiceUtilsTest.java @@ -108,7 +108,7 @@ void computeS2IBuildName_withImageNameAndEmptyBuildServiceConfig_shouldReturnNam // Given final ImageName imageName = new ImageName("registry/name:tag"); // When - final String result = computeS2IBuildName(new BuildServiceConfig(), imageName); + final String result = computeS2IBuildName(imageConfiguration, new BuildServiceConfig(), imageName); // Then assertThat(result).isEqualTo("name"); } @@ -122,7 +122,7 @@ void computeS2IBuildName_withImageNameAndBuildServiceWithS2I_shouldReturnNameWit .build(); final ImageName imageName = new ImageName("registry/name:tag"); // When - final String result = computeS2IBuildName(buildServiceConfig, imageName); + final String result = computeS2IBuildName(imageConfiguration, buildServiceConfig, imageName); // Then assertThat(result).isEqualTo("name-s2i"); } @@ -132,12 +132,14 @@ void computeS2IBuildName_withImageNameAndBuildServiceWithCustomSuffix_shouldRetu // Given final BuildServiceConfig buildServiceConfig = BuildServiceConfig.builder() .jKubeBuildStrategy(JKubeBuildStrategy.s2i) - .s2iBuildNameSuffix("-custom") .buildDirectory(temporaryFolder.getAbsolutePath()) .build(); + imageConfiguration = imageConfiguration.toBuilder() + .build(imageConfiguration.getBuild().toBuilder().openshiftS2iBuildNameSuffix("-custom").build()) + .build(); final ImageName imageName = new ImageName("registry/name:tag"); // When - final String result = computeS2IBuildName(buildServiceConfig, imageName); + final String result = computeS2IBuildName(imageConfiguration, buildServiceConfig, imageName); // Then assertThat(result).isEqualTo("name-custom"); } @@ -216,7 +218,7 @@ void createBuildStrategy_withDockerBuildStrategyAndPullSecret_shouldReturnValidB @Test void createBuildOutput_withDefaults_shouldReturnImageStreamTag() { // When - final BuildOutput result = createBuildOutput(new BuildServiceConfig(), new ImageName("my-app-image")); + final BuildOutput result = createBuildOutput(imageConfiguration, new ImageName("my-app-image")); // Then assertThat(result) .extracting(BuildOutput::getTo) @@ -228,12 +230,16 @@ void createBuildOutput_withDefaults_shouldReturnImageStreamTag() { void createBuildOutput_withOutputKindDockerAndPushSecret_shouldReturnDocker() { // Given final BuildServiceConfig buildServiceConfig = BuildServiceConfig.builder() - .buildOutputKind("DockerImage") - .openshiftPushSecret("my-push-secret") .buildDirectory(temporaryFolder.getAbsolutePath()) .build(); + imageConfiguration = imageConfiguration.toBuilder() + .build(imageConfiguration.getBuild().toBuilder() + .openshiftBuildOutputKind("DockerImage") + .openshiftPushSecret("my-push-secret") + .build()) + .build(); // When - final BuildOutput result = createBuildOutput(buildServiceConfig, new ImageName("my-app-image")); + final BuildOutput result = createBuildOutput(imageConfiguration, new ImageName("my-app-image")); // Then assertThat(result) .hasFieldOrPropertyWithValue("pushSecret.name", "my-push-secret") diff --git a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildServiceIntegrationTest.java b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildServiceIntegrationTest.java index 257a25d55e..8bb579f4b9 100644 --- a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildServiceIntegrationTest.java +++ b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/openshift/OpenshiftBuildServiceIntegrationTest.java @@ -41,7 +41,6 @@ import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; -import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.resource.ContainerResourcesConfig; import org.eclipse.jkube.kit.config.resource.ResourceConfig; import org.eclipse.jkube.kit.config.service.BuildServiceConfig; @@ -102,12 +101,6 @@ class OpenshiftBuildServiceIntegrationTest { private BuildServiceConfig.BuildServiceConfigBuilder defaultConfig; - private BuildServiceConfig.BuildServiceConfigBuilder defaultConfigSecret; - - private BuildServiceConfig.BuildServiceConfigBuilder dockerImageConfigSecret; - - private BuildServiceConfig.BuildServiceConfigBuilder dockerImageConfig; - private ResourceConfig resourceConfig; @BeforeEach @@ -148,24 +141,15 @@ void init(@TempDir Path temporaryFolder) throws Exception { .name(projectName) .build(BuildConfiguration.builder() .from(projectName) + .openshiftS2iBuildNameSuffix("-s2i-suffix2") + .openshiftBuildRecreateMode("none") .build() ).build(); defaultConfig = BuildServiceConfig.builder() .buildDirectory(baseDir) - .buildRecreateMode(BuildRecreateMode.none) - .s2iBuildNameSuffix("-s2i-suffix2") .resourceConfig(resourceConfig) .jKubeBuildStrategy(JKubeBuildStrategy.s2i); - - defaultConfigSecret = defaultConfig.build().toBuilder().openshiftPullSecret("pullsecret-fabric8"); - - dockerImageConfig = defaultConfig.build().toBuilder().buildOutputKind("DockerImage"); - - dockerImageConfigSecret = defaultConfig.build().toBuilder() - .openshiftPullSecret("pullsecret-fabric8") - .openshiftPushSecret("pushsecret-fabric8") - .buildOutputKind("DockerImage"); } @AfterEach @@ -205,7 +189,7 @@ void build_withAssembly_shouldSucceed() throws Exception { // Given final BuildServiceConfig config = withBuildServiceConfig(defaultConfig.build()); final WebServerEventCollector collector = prepareMockServer(config, true, false, false, false); - image.setBuild(BuildConfiguration.builder() + image.setBuild(image.getBuild().toBuilder() .from(projectName) .assembly(AssemblyConfiguration.builder() .layer(Assembly.builder().id("one").build()) @@ -258,9 +242,12 @@ void build_withDockerfileModeAndAssembly_shouldSucceed() throws Exception { @Test void successfulBuildNoS2iSuffix() throws Exception { - final BuildServiceConfig config = withBuildServiceConfig(defaultConfig.s2iBuildNameSuffix(null).build()); + image = image.toBuilder() + .build(image.getBuild().toBuilder().openshiftS2iBuildNameSuffix(null).build()) + .build(); + BuildServiceConfig buildServiceConfig = withBuildServiceConfig(defaultConfig.build()); final WebServerEventCollector collector = prepareMockServer( - config, true, false, false, false); + buildServiceConfig, true, false, false, false); new OpenshiftBuildService(jKubeServiceHub).build(image); @@ -274,10 +261,13 @@ void successfulBuildNoS2iSuffix() throws Exception { @Test void dockerBuild() throws Exception { + image = image.toBuilder() + .build(image.getBuild().toBuilder() + .openshiftS2iBuildNameSuffix("-docker") + .build()) + .build(); final BuildServiceConfig dockerConfig = withBuildServiceConfig(BuildServiceConfig.builder() .buildDirectory(baseDir) - .buildRecreateMode(BuildRecreateMode.none) - .s2iBuildNameSuffix("-docker") .jKubeBuildStrategy(JKubeBuildStrategy.docker) .resourceConfig(resourceConfig).build()); final WebServerEventCollector collector = prepareMockServer(dockerConfig, true, false, false, false); @@ -295,11 +285,12 @@ void dockerBuild() throws Exception { void dockerBuildWithMultiComponentImageName() throws Exception { final BuildServiceConfig dockerConfig = withBuildServiceConfig(BuildServiceConfig.builder() .buildDirectory(baseDir) - .buildRecreateMode(BuildRecreateMode.none) - .s2iBuildNameSuffix("-docker") .jKubeBuildStrategy(JKubeBuildStrategy.docker) .resourceConfig(resourceConfig).build()); - image.setName("docker.io/registry/component1/component2/name:tag"); + image = image.toBuilder() + .name("docker.io/registry/component1/component2/name:tag") + .build(image.getBuild().toBuilder().openshiftS2iBuildNameSuffix("-docker").build()) + .build(); final WebServerEventCollector collector = prepareMockServer("component1-component2-name", dockerConfig, true, false, false, false); @@ -316,10 +307,12 @@ void dockerBuildWithMultiComponentImageName() throws Exception { void dockerBuildNoS2iSuffix() throws Exception { final BuildServiceConfig dockerConfig = withBuildServiceConfig(BuildServiceConfig.builder() .buildDirectory(baseDir) - .buildRecreateMode(BuildRecreateMode.none) .jKubeBuildStrategy(JKubeBuildStrategy.docker) .resourceConfig(resourceConfig) .build()); + image = image.toBuilder() + .build(image.getBuild().toBuilder().openshiftS2iBuildNameSuffix(null).build()) + .build(); final WebServerEventCollector collector = prepareMockServer(dockerConfig, true, false, false, false); new OpenshiftBuildService(jKubeServiceHub).build(image); @@ -335,26 +328,25 @@ void dockerBuildNoS2iSuffix() throws Exception { void dockerBuildFromExt() throws Exception { final BuildServiceConfig dockerConfig = withBuildServiceConfig(BuildServiceConfig.builder() .buildDirectory(baseDir) - .buildRecreateMode(BuildRecreateMode.none) - .s2iBuildNameSuffix("-docker") .jKubeBuildStrategy(JKubeBuildStrategy.docker) .resourceConfig(resourceConfig) .build()); - final WebServerEventCollector collector = prepareMockServer(dockerConfig, true, false, false, false); - - OpenshiftBuildService service = new OpenshiftBuildService(jKubeServiceHub); Map fromExt = ImmutableMap.of("name", "app:1.2-1", "kind", "ImageStreamTag", "namespace", "my-project"); - ImageConfiguration fromExtImage = ImageConfiguration.builder() + image = ImageConfiguration.builder() .name(projectName) .build(BuildConfiguration.builder() .fromExt(fromExt) .nocache(Boolean.TRUE) + .openshiftS2iBuildNameSuffix("-docker") .build() ).build(); + final WebServerEventCollector collector = prepareMockServer(dockerConfig, true, false, false, false); - service.build(fromExtImage); + OpenshiftBuildService service = new OpenshiftBuildService(jKubeServiceHub); + + service.build(image); assertThat(mockServer.getRequestCount()).isGreaterThan(8); collector.assertEventsRecordedInOrder("build-config-check", "new-build-config", "pushed"); @@ -365,7 +357,12 @@ void dockerBuildFromExt() throws Exception { @Test void successfulBuildSecret() throws Exception { - final BuildServiceConfig config = withBuildServiceConfig(defaultConfigSecret.build()); + final BuildServiceConfig config = withBuildServiceConfig(defaultConfig.build()); + image = image.toBuilder() + .build(image.getBuild().toBuilder() + .openshiftPullSecret("pullsecret-fabric8") + .build()) + .build(); final WebServerEventCollector collector = prepareMockServer(config, true, false, false, false); new OpenshiftBuildService(jKubeServiceHub).build(image); @@ -429,7 +426,13 @@ void successfulBuildWithResourceConfig() throws Exception { @Test void successfulDockerImageOutputBuild() throws Exception { - final BuildServiceConfig config = withBuildServiceConfig(dockerImageConfig.build()); + final BuildServiceConfig config = withBuildServiceConfig(defaultConfig.build()); + image = image.toBuilder() + .build(image.getBuild() + .toBuilder() + .openshiftBuildOutputKind("DockerImage") + .build()) + .build(); final WebServerEventCollector collector = prepareMockServer(config, true, false, false, false); new OpenshiftBuildService(jKubeServiceHub).build(image); @@ -445,7 +448,14 @@ void successfulDockerImageOutputBuild() throws Exception { @Test void successfulDockerImageOutputBuildSecret() throws Exception { - final BuildServiceConfig config = withBuildServiceConfig(dockerImageConfigSecret.build()); + final BuildServiceConfig config = withBuildServiceConfig(defaultConfig.build()); + image = image.toBuilder() + .build(image.getBuild().toBuilder() + .openshiftPullSecret("pullsecret-fabric8") + .openshiftPushSecret("pushsecret-fabric8") + .openshiftBuildOutputKind("DockerImage") + .build()) + .build(); final WebServerEventCollector collector = prepareMockServer(config, true, false, false, false); new OpenshiftBuildService(jKubeServiceHub).build(image); @@ -484,11 +494,11 @@ private WebServerEventCollector prepareMockServer( final long buildDelay = 50L; final String s2iBuildNameSuffix = Optional - .ofNullable(config.getS2iBuildNameSuffix()) + .ofNullable(image.getBuild().getOpenshiftS2iBuildNameSuffix()) .orElseGet(() -> config.getJKubeBuildStrategy() == JKubeBuildStrategy.s2i ? "-s2i" : ""); - final String buildOutputKind = Optional.ofNullable(config.getBuildOutputKind()).orElse("ImageStreamTag"); + final String buildOutputKind = Optional.ofNullable(image.getBuild().getOpenshiftBuildOutputKind()).orElse("ImageStreamTag"); BuildConfig bc = new BuildConfigBuilder() .withNewMetadata() @@ -504,7 +514,7 @@ private WebServerEventCollector prepareMockServer( .build(); BuildConfig bcSecret = null; - if (config.getOpenshiftPullSecret() != null) { + if (image.getBuild().getOpenshiftPullSecret() != null) { bcSecret = new BuildConfigBuilder() .withNewMetadata() .withName(resourceName + s2iBuildNameSuffix + "pullSecret") @@ -512,10 +522,10 @@ private WebServerEventCollector prepareMockServer( .withNewSpec() .withStrategy(new BuildStrategyBuilder().withType("Docker") .withNewDockerStrategy() - .withNewPullSecret(config.getOpenshiftPullSecret()) + .withNewPullSecret(image.getBuild().getOpenshiftPullSecret()) .endDockerStrategy().build()) .withNewOutput() - .withNewPushSecret().withName(config.getOpenshiftPushSecret()).endPushSecret() + .withNewPushSecret().withName(image.getBuild().getOpenshiftPushSecret()).endPushSecret() .withNewTo().withKind(buildOutputKind).endTo() .endOutput() .endSpec() diff --git a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java index 3e6dcc6c06..79477a169b 100644 --- a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java +++ b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java @@ -46,7 +46,6 @@ import org.eclipse.jkube.kit.config.access.ClusterAccess; import org.eclipse.jkube.kit.config.access.ClusterConfiguration; import org.eclipse.jkube.kit.config.image.build.RegistryAuthConfiguration; -import org.eclipse.jkube.kit.config.resource.BuildRecreateMode; import org.eclipse.jkube.kit.config.resource.PlatformMode; import org.eclipse.jkube.kit.config.resource.ProcessorConfig; import org.eclipse.jkube.kit.config.resource.ResourceConfig; @@ -408,7 +407,7 @@ protected void doExecute() throws MojoExecutionException { .buildServiceConfig(buildServiceConfigBuilder().build()) .offline(offline) .build(); - resolvedImages = ConfigHelper.initImageConfiguration(getBuildTimestamp(getPluginContext(), CONTEXT_KEY_BUILD_TIMESTAMP, project.getBuild().getDirectory(), DOCKER_BUILD_TIMESTAMP), images, imageConfigResolver, log, filter, new DefaultGeneratorManager(generatorContextBuilder().build()), false, jkubeServiceHub.getConfiguration()); + resolvedImages = resolveImages(); executeInternal(); } catch (IOException | DependencyResolutionRequiredException exp) { logException(exp); @@ -487,6 +486,14 @@ protected DockerAccessFactory.DockerAccessContext getDockerAccessContext() { .build(); } + protected List resolveImages() throws IOException { + return ConfigHelper.initImageConfiguration(getBuildTimestamp(getPluginContext(), CONTEXT_KEY_BUILD_TIMESTAMP, project.getBuild().getDirectory(), DOCKER_BUILD_TIMESTAMP), + images, imageConfigResolver, log, filter, + new DefaultGeneratorManager(generatorContextBuilder().build()), + false, + jkubeServiceHub.getConfiguration()); + } + /** * Get all images to use. Can be restricted via -Djkube.image.filter to pick a one or more images. * The values are taken as comma separated list. @@ -544,9 +551,7 @@ private void buildAndTag(List imageConfigs) protected BuildServiceConfig.BuildServiceConfigBuilder buildServiceConfigBuilder() { return BuildServiceConfig.builder() - .buildRecreateMode(BuildRecreateMode.fromParameter(buildRecreate)) .jKubeBuildStrategy(getJKubeBuildStrategy()) - .forcePull(forcePull) .imagePullManager(ImagePullManager.createImagePullManager(imagePullPolicy, autoPull, project.getProperties())) .buildDirectory(project.getBuild().getDirectory()) .resourceConfig(resources) diff --git a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ResourceMojo.java b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ResourceMojo.java index c492335690..a1b7e1aee1 100644 --- a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ResourceMojo.java +++ b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ResourceMojo.java @@ -250,7 +250,7 @@ private KubernetesList generateResources() throws IOException { return jkubeServiceHub.getResourceService().generateResources(getPlatformMode(), enricherManager, log); } - private ProcessorConfig extractEnricherConfig() throws IOException { + private ProcessorConfig extractEnricherConfig() { return ProfileUtil.blendProfileWithConfiguration(ProfileUtil.ENRICHER_CONFIG, profile, jkubeServiceHub.getResourceServiceConfig().getResourceDirs(), enricher); } diff --git a/openshift-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojo.java b/openshift-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojo.java index 93e802476e..3cf915f9c8 100644 --- a/openshift-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojo.java +++ b/openshift-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojo.java @@ -18,12 +18,18 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; +import org.eclipse.jkube.generator.api.DefaultGeneratorManager; import org.eclipse.jkube.generator.api.GeneratorContext; +import org.eclipse.jkube.kit.build.api.helper.ConfigHelper; +import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; import org.eclipse.jkube.kit.config.resource.RuntimeMode; -import org.eclipse.jkube.kit.config.service.BuildServiceConfig; import org.eclipse.jkube.maven.plugin.mojo.OpenShift; +import java.io.IOException; +import java.util.List; + +import static org.eclipse.jkube.kit.common.util.BuildReferenceDateUtil.getBuildTimestamp; import static org.eclipse.jkube.kit.config.resource.RuntimeMode.KUBERNETES; /** @@ -88,16 +94,6 @@ protected void doExecute() throws MojoExecutionException { super.doExecute(); } - @Override - protected BuildServiceConfig.BuildServiceConfigBuilder buildServiceConfigBuilder() { - return super.buildServiceConfigBuilder() - .openshiftPullSecret(openshiftPullSecret) - .s2iBuildNameSuffix(s2iBuildNameSuffix) - .s2iImageStreamLookupPolicyLocal(s2iImageStreamLookupPolicyLocal) - .openshiftPushSecret(openshiftPushSecret) - .buildOutputKind(buildOutputKind); - } - @Override protected GeneratorContext.GeneratorContextBuilder generatorContextBuilder() { return super.generatorContextBuilder() @@ -117,4 +113,9 @@ protected JKubeBuildStrategy getJKubeBuildStrategy() { return JKubeBuildStrategy.s2i; } + @Override + protected List resolveImages() throws IOException { + return ConfigHelper.initImageConfiguration(getBuildTimestamp(getPluginContext(), CONTEXT_KEY_BUILD_TIMESTAMP, project.getBuild().getDirectory(), DOCKER_BUILD_TIMESTAMP), images, imageConfigResolver, log, filter, new DefaultGeneratorManager(generatorContextBuilder().build()), false, jkubeServiceHub.getConfiguration(), + forcePull, s2iBuildNameSuffix, s2iImageStreamLookupPolicyLocal, openshiftPullSecret, openshiftPushSecret, buildOutputKind, buildRecreate); + } } diff --git a/openshift-maven-plugin/plugin/src/test/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojoTest.java b/openshift-maven-plugin/plugin/src/test/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojoTest.java new file mode 100644 index 0000000000..cebec5a316 --- /dev/null +++ b/openshift-maven-plugin/plugin/src/test/java/org/eclipse/jkube/maven/plugin/mojo/build/OpenshiftBuildMojoTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at: + * + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.jkube.maven.plugin.mojo.build; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collections; +import java.util.Properties; + +import org.apache.maven.model.Build; +import org.apache.maven.project.MavenProject; +import org.eclipse.jkube.kit.build.api.helper.ImageConfigResolver; +import org.eclipse.jkube.kit.common.JKubeConfiguration; +import org.eclipse.jkube.kit.common.JavaProject; +import org.eclipse.jkube.kit.common.KitLogger; +import org.eclipse.jkube.kit.config.image.ImageConfiguration; +import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; + +import org.eclipse.jkube.kit.config.resource.ProcessorConfig; +import org.eclipse.jkube.kit.config.resource.RuntimeMode; +import org.eclipse.jkube.kit.config.service.JKubeServiceHub; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class OpenshiftBuildMojoTest { + private OpenshiftBuildMojo openShiftBuildMojo; + + @TempDir + private File temporaryFolder; + + @BeforeEach + void setUp() throws IOException { + MavenProject mavenProject = mock(MavenProject.class); + Build mavenBuild = mock(Build.class); + when(mavenProject.getProperties()).thenReturn(new Properties()); + when(mavenProject.getBasedir()).thenReturn(temporaryFolder); + when(mavenProject.getBuild()).thenReturn(mavenBuild); + when(mavenBuild.getDirectory()).thenReturn(temporaryFolder.toPath().resolve("target").toFile().getAbsolutePath()); + JavaProject javaProject = JavaProject.builder() + .artifactId("test-project") + .groupId("org.example") + .version("0.0.1") + .properties(new Properties()) + .buildDirectory(temporaryFolder.toPath().resolve("target").toFile()) + .outputDirectory(temporaryFolder.toPath().resolve("target").resolve("docker").toFile()) + .build(); + openShiftBuildMojo = new OpenshiftBuildMojo(); + openShiftBuildMojo.project = mavenProject; + openShiftBuildMojo.javaProject = javaProject; + openShiftBuildMojo.log = new KitLogger.SilentLogger(); + openShiftBuildMojo.generator = new ProcessorConfig(); + openShiftBuildMojo.resourceDir = temporaryFolder.toPath().resolve("src").resolve("main").resolve("jkube").toFile(); + Files.createDirectories(openShiftBuildMojo.resourceDir.toPath()); + openShiftBuildMojo.imageConfigResolver = new ImageConfigResolver(); + openShiftBuildMojo.jkubeServiceHub = JKubeServiceHub.builder() + .configuration(JKubeConfiguration.builder() + .project(javaProject) + .build()) + .log(new KitLogger.SilentLogger()) + .platformMode(RuntimeMode.OPENSHIFT) + .build(); + openShiftBuildMojo.images = Collections.singletonList(ImageConfiguration.builder() + .name("foo/bar:latest") + .build(BuildConfiguration.builder() + .from("foo/base:latest") + .build()) + .build()); + } + + @Test + void postProcessImages_whenNoS2IBuildConfigProvidedViaMojoParams_thenImageConfigurationIsMergedWithDefaultValues() throws IOException { + // When + // Then + assertThat(openShiftBuildMojo.resolveImages()) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", false) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", null) + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", true) + .hasFieldOrPropertyWithValue("openshiftPullSecret", null) + .hasFieldOrPropertyWithValue("openshiftPushSecret", null) + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", null) + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", null); + } + + @Test + void postProcessImages_whenS2IBuildConfigProvidedViaMojoParams_thenReturnMergedImageConfigWithOpenShiftS2IBuildParams() throws IOException { + // Given + openShiftBuildMojo.s2iImageStreamLookupPolicyLocal = true; + openShiftBuildMojo.forcePull = true; + openShiftBuildMojo.buildOutputKind = "DockerImage"; + openShiftBuildMojo.openshiftPushSecret = "push-secret"; + openShiftBuildMojo.openshiftPullSecret = "pull-secret"; + openShiftBuildMojo.s2iBuildNameSuffix = "-custom"; + openShiftBuildMojo.buildRecreate = "bc"; + + // When + // Then + assertThat(openShiftBuildMojo.resolveImages()) + .singleElement() + .extracting(ImageConfiguration::getBuild) + .hasFieldOrPropertyWithValue("openshiftForcePull", true) + .hasFieldOrPropertyWithValue("openshiftS2iBuildNameSuffix", "-custom") + .hasFieldOrPropertyWithValue("openshiftS2iImageStreamLookupPolicyLocal", true) + .hasFieldOrPropertyWithValue("openshiftPullSecret", "pull-secret") + .hasFieldOrPropertyWithValue("openshiftPushSecret", "push-secret") + .hasFieldOrPropertyWithValue("openshiftBuildOutputKind", "DockerImage") + .hasFieldOrPropertyWithValue("openshiftBuildRecreateMode", "bc"); + } +}