diff --git a/CHANGELOG.md b/CHANGELOG.md index 87b9aae2dd..d53c79d3b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Usage: * Fix #473: Debug goals work with QuarkusGenerator generated container images * Fix #484: cacheFrom configuration parameter is missing * Fix #181: Refactor PortForwardService to use Kubernetes Client Port Forwarding instead of kubectl binary +* Fix #515: Properties now get resolved in CustomResource fragments ### 1.0.2 (2020-10-30) * Fix #429: Added quickstart for Micronaut framework diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/DockerFileUtil.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/DockerFileUtil.java index 29b250d8de..619abd456d 100644 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/DockerFileUtil.java +++ b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/DockerFileUtil.java @@ -17,6 +17,7 @@ import com.google.gson.JsonObject; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jkube.kit.common.util.JKubeFileInterpolator; import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.yaml.snakeyaml.Yaml; @@ -107,7 +108,7 @@ public static List extractLines(File dockerFile, String keyword, Prope try (BufferedReader reader = new BufferedReader(new FileReader(dockerFile))) { String line; while ((line = reader.readLine()) != null) { - String lineInterpolated = JKubeDockerfileInterpolator.interpolate(line, properties, filter); + String lineInterpolated = JKubeFileInterpolator.interpolate(line, properties, filter); String[] lineParts = lineInterpolated.split("\\s+"); if (lineParts.length > 0 && lineParts[0].equalsIgnoreCase(keyword)) { ret.add(lineParts); @@ -127,14 +128,7 @@ public static List extractLines(File dockerFile, String keyword, Prope * @throws IOException if there's a problem while performin IO operations. */ public static String interpolate(File dockerFile, Properties properties, String filter) throws IOException { - StringBuilder ret = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(dockerFile))) { - String line; - while ((line = reader.readLine()) != null) { - ret.append(JKubeDockerfileInterpolator.interpolate(line, properties, resolveDockerfileFilter(filter))).append(System.lineSeparator()); - } - } - return ret.toString(); + return JKubeFileInterpolator.interpolate(dockerFile, properties, resolveDockerfileFilter(filter)); } private static Reader getFileReaderFromDir(File file) { diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolator.java b/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolator.java similarity index 89% rename from jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolator.java rename to jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolator.java index 6248f4d5cb..87197bddc1 100644 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolator.java +++ b/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolator.java @@ -11,17 +11,21 @@ * Contributors: * Red Hat, Inc. - initial API and implementation */ -package org.eclipse.jkube.kit.build.api.helper; +package org.eclipse.jkube.kit.common.util; import org.apache.commons.lang3.StringUtils; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; -public class JKubeDockerfileInterpolator { +public class JKubeFileInterpolator { - private JKubeDockerfileInterpolator() { } + private JKubeFileInterpolator() { } /** * Replace properties in a string @@ -65,6 +69,17 @@ protected static Map getExpressionMarkersFromFilter(String filte return expressionMarkers; } + public static String interpolate(File file, Properties properties, String filter) throws IOException { + StringBuilder ret = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + ret.append(JKubeFileInterpolator.interpolate(line, properties, filter)).append(System.lineSeparator()); + } + } + return ret.toString(); + } + private static String checkForPropertiesInLine(String line, Properties properties, Map delimiters) { // Provided properties for (String property : properties.stringPropertyNames()) { diff --git a/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/ResourceUtil.java b/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/ResourceUtil.java index 9bf2d8b127..bae80a278a 100644 --- a/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/ResourceUtil.java +++ b/jkube-kit/common/src/main/java/org/eclipse/jkube/kit/common/util/ResourceUtil.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.google.gson.JsonObject; import org.apache.commons.io.FilenameUtils; +import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.ResourceFileType; import org.apache.commons.lang3.StringUtils; @@ -33,6 +34,9 @@ * @author roland */ public class ResourceUtil { + private ResourceUtil() { } + + private static final String CUSTOM_RESOURCE_OUTPUT_DIR = "custom-resources"; public static boolean jsonEquals(JsonObject first, JsonObject second) { final ObjectMapper mapper = new ObjectMapper(); @@ -112,6 +116,25 @@ public static File getFinalResourceDir(File resourceDir, String environment) { return resourceDir; } + public static boolean hasCustomResourceManifests(File customResourceManifestDir) { + if (customResourceManifestDir != null) { + String[] customResourceManifests = customResourceManifestDir.list(); + if (customResourceManifests != null) { + return customResourceManifests.length > 0; + } + } + return false; + } + + public static File getCustomResourceManifestDir(JavaProject javaProject) { + File projectOutputDir = javaProject.getOutputDirectory(); + if (projectOutputDir != null && projectOutputDir.isDirectory()) { + File jkubeManifestOutputDir = new File(projectOutputDir, "META-INF/jkube"); + return new File(jkubeManifestOutputDir, CUSTOM_RESOURCE_OUTPUT_DIR); + } + return null; + } + } diff --git a/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolatorTest.java b/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolatorTest.java similarity index 66% rename from jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolatorTest.java rename to jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolatorTest.java index 19f72f0d43..59600f0c66 100644 --- a/jkube-kit/build/api/src/test/java/org/eclipse/jkube/kit/build/api/helper/JKubeDockerfileInterpolatorTest.java +++ b/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/JKubeFileInterpolatorTest.java @@ -11,21 +11,25 @@ * Contributors: * Red Hat, Inc. - initial API and implementation */ -package org.eclipse.jkube.kit.build.api.helper; +package org.eclipse.jkube.kit.common.util; import org.junit.Test; +import java.io.File; +import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Properties; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class JKubeDockerfileInterpolatorTest { +import static org.assertj.core.api.Assertions.assertThat; + +public class JKubeFileInterpolatorTest { @Test public void testLongDelimitersInContext() { // Given @@ -34,7 +38,7 @@ public void testLongDelimitersInContext() { p.setProperty("test.label", "test"); // When - String result = JKubeDockerfileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); + String result = JKubeFileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); // Then assertEquals("This is a test for long delimiters in context.", result); @@ -48,7 +52,7 @@ public void testLongDelimitersWithNoStartContext() { p.setProperty("test.label", "test"); // When - String result = JKubeDockerfileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); + String result = JKubeFileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); // Then assertEquals("test for long delimiters in context.", result); @@ -62,7 +66,7 @@ public void testLongDelimitersWithNoEndContext() { p.setProperty("test.label", "test"); // When - String result = JKubeDockerfileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); + String result = JKubeFileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); // Then assertEquals("This is a test", result); @@ -75,7 +79,7 @@ public void testLongDelimitersWithNoContext() { Properties p = new Properties(); p.setProperty("test.label", "test"); // When - String result = JKubeDockerfileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); + String result = JKubeFileInterpolator.interpolate(src, p, Collections.singletonMap("", "")); // Then assertEquals("test", result); @@ -88,7 +92,7 @@ public void testSimpleSubstitution() { p.setProperty("key", "value"); // When - String result = JKubeDockerfileInterpolator.interpolate("This is a test ${key}.", p, Collections.singletonMap("${", "}")); + String result = JKubeFileInterpolator.interpolate("This is a test ${key}.", p, Collections.singletonMap("${", "}")); // Then assertEquals("This is a test value.", result); @@ -102,7 +106,7 @@ public void testSimpleSubstitution_TwoExpressions() { p.setProperty("key2", "value2"); // When - String result = JKubeDockerfileInterpolator.interpolate("${key}-${key2}", p, Collections.singletonMap("${", "}")); + String result = JKubeFileInterpolator.interpolate("${key}-${key2}", p, Collections.singletonMap("${", "}")); // Then assertEquals("value-value2", result); @@ -115,7 +119,7 @@ public void testBrokenExpression_LeaveItAlone() { p.setProperty("key", "value"); // When - String result = JKubeDockerfileInterpolator.interpolate("This is a test ${key.", p, Collections.singletonMap("${", "}")); + String result = JKubeFileInterpolator.interpolate("This is a test ${key.", p, Collections.singletonMap("${", "}")); // Then assertEquals("This is a test ${key.", result); @@ -129,7 +133,7 @@ public void testShouldFailOnExpressionCycleParsed() { props.setProperty("key2", "${key1}"); // When - JKubeDockerfileInterpolator.interpolate("${key1}", props, Collections.singletonMap("${", "}")); + JKubeFileInterpolator.interpolate("${key1}", props, Collections.singletonMap("${", "}")); fail("Should detect expression cycle and fail."); } @@ -142,7 +146,7 @@ public void testShouldFailOnExpressionCycleDirect() { props.setProperty("key2", "key1"); // When - JKubeDockerfileInterpolator.interpolate("${key1}", props, Collections.singletonMap("${", "}")); + JKubeFileInterpolator.interpolate("${key1}", props, Collections.singletonMap("${", "}")); fail("Should detect expression cycle and fail."); } @@ -154,7 +158,7 @@ public void testShouldResolveByMy_getVar_Method() { properties.put("${var}", "testVar"); // When - String result = JKubeDockerfileInterpolator.interpolate("this is a ${var}", properties, Collections.singletonMap("${", "}")); + String result = JKubeFileInterpolator.interpolate("this is a ${var}", properties, Collections.singletonMap("${", "}")); // Then assertEquals("this is a testVar", result); @@ -164,7 +168,7 @@ public void testShouldResolveByMy_getVar_Method() { public void testShouldResolveByEnvar() { // Given Properties p = new Properties(); - String result = JKubeDockerfileInterpolator.interpolate("this is a ${env.HOME} ${env.PATH}", p, Collections.singletonMap("${env.", "}")); + String result = JKubeFileInterpolator.interpolate("this is a ${env.HOME} ${env.PATH}", p, Collections.singletonMap("${env.", "}")); // When + Then assertNotEquals("this is a ${HOME} ${PATH}", result); @@ -178,7 +182,7 @@ public void testNotEscapeWithLongEscapeStrAtStart() { p.setProperty("key", "value"); // When - String result = JKubeDockerfileInterpolator.interpolate("@{key} This is a test.", p, Collections.singletonMap("@{", "}")); + String result = JKubeFileInterpolator.interpolate("@{key} This is a test.", p, Collections.singletonMap("@{", "}")); // Then assertEquals("value This is a test.", result); @@ -187,7 +191,7 @@ public void testNotEscapeWithLongEscapeStrAtStart() { @Test public void testNPEFree() { // When - String result = JKubeDockerfileInterpolator.interpolate(null, new Properties(), Collections.emptyMap()); + String result = JKubeFileInterpolator.interpolate(null, new Properties(), Collections.emptyMap()); // Then assertNull(result); @@ -203,9 +207,9 @@ public void testLinkedInterpolators() { p.put("test2", "x"); // When - String result1 = JKubeDockerfileInterpolator.interpolate(EXPR, p, Collections.singletonMap("${", "}")); + String result1 = JKubeFileInterpolator.interpolate(EXPR, p, Collections.singletonMap("${", "}")); p.put("test2.label", "zz"); - String result2 = JKubeDockerfileInterpolator.interpolate(EXPR2, p, Collections.singletonMap("${", "}")); + String result2 = JKubeFileInterpolator.interpolate(EXPR2, p, Collections.singletonMap("${", "}")); // Then assertEquals("pANDx", result1); @@ -223,8 +227,8 @@ public void testDominance() { p1.put("test2.label", "dominant"); // When + Then - assertEquals("pANDx", JKubeDockerfileInterpolator.interpolate(EXPR, p1,Collections.singletonMap("${", "}"))); - assertEquals("pdominantANDx", JKubeDockerfileInterpolator.interpolate(EXPR2, p1, Collections.singletonMap("${", "}"))); + assertEquals("pANDx", JKubeFileInterpolator.interpolate(EXPR, p1,Collections.singletonMap("${", "}"))); + assertEquals("pdominantANDx", JKubeFileInterpolator.interpolate(EXPR2, p1, Collections.singletonMap("${", "}"))); } @Test(expected = IllegalArgumentException.class) @@ -234,7 +238,7 @@ public void testCyclesWithLinked() { p.put("key1", "${key2}"); p.put("key2", "${key2}"); // When - JKubeDockerfileInterpolator.interpolate("${key2}", p, Collections.singletonMap("${", "}")); + JKubeFileInterpolator.interpolate("${key2}", p, Collections.singletonMap("${", "}")); } @Test(expected = IllegalArgumentException.class) @@ -244,7 +248,7 @@ public void testCyclesWithLinked_betweenRootAndOther() { p.put("key1", "${key2}"); p.put("key2", "${key1}"); // When - JKubeDockerfileInterpolator.interpolate("${key1}", p, Collections.singletonMap("${", "}")); + JKubeFileInterpolator.interpolate("${key1}", p, Collections.singletonMap("${", "}")); } @Test @@ -253,7 +257,7 @@ public void testGetExpressionMarkersFromFilterWithDefaultFilter() { String filter = "${*}"; // When - Map result = JKubeDockerfileInterpolator.getExpressionMarkersFromFilter(filter); + Map result = JKubeFileInterpolator.getExpressionMarkersFromFilter(filter); // Then assertEquals(Collections.singletonMap("${", "}"), result); @@ -265,7 +269,7 @@ public void testGetExpressionMarkersFromFilterWithSingleCharacterFilter() { String filter = "@"; // When - Map result = JKubeDockerfileInterpolator.getExpressionMarkersFromFilter(filter); + Map result = JKubeFileInterpolator.getExpressionMarkersFromFilter(filter); // Then assertEquals(Collections.singletonMap("@", "@"), result); @@ -277,7 +281,7 @@ public void testGetExpressionMarkersFromFilterWithFalseFilter() { String filter = "false"; // When - Map result = JKubeDockerfileInterpolator.getExpressionMarkersFromFilter(filter); + Map result = JKubeFileInterpolator.getExpressionMarkersFromFilter(filter); // Then assertTrue(result.isEmpty()); @@ -289,9 +293,23 @@ public void testGetExpressionMarkersFromFilterWithBlankFilter() { String filter = ""; // When - Map result = JKubeDockerfileInterpolator.getExpressionMarkersFromFilter(filter); + Map result = JKubeFileInterpolator.getExpressionMarkersFromFilter(filter); // Then assertTrue(result.isEmpty()); } + + @Test + public void testInterpolateFile() throws IOException { + // Given + Properties properties = new Properties(); + properties.put("org.name", "Eclipse Foundation"); + File inputFile = new File(getClass().getResource("/test-file.txt").getFile()); + + // When + String result = JKubeFileInterpolator.interpolate(inputFile, properties, "${*}"); + + // Then + assertThat(result).contains("This project is maintained by Eclipse Foundation"); + } } diff --git a/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/ResourceUtilTest.java b/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/ResourceUtilTest.java index 8e37d5483e..b4e37c0413 100644 --- a/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/ResourceUtilTest.java +++ b/jkube-kit/common/src/test/java/org/eclipse/jkube/kit/common/util/ResourceUtilTest.java @@ -15,9 +15,18 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import mockit.Expectations; +import mockit.Mocked; +import org.eclipse.jkube.kit.common.JavaProject; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** @@ -26,6 +35,9 @@ */ public class ResourceUtilTest { + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Test public void simple() { JsonParser parser = new JsonParser(); @@ -35,4 +47,63 @@ public void simple() { assertTrue(ResourceUtil.jsonEquals(first, same)); assertFalse(ResourceUtil.jsonEquals(first, different)); } + + @Test + public void testHasCustomResourceManifests(@Mocked File customResourceManifestDir) { + // Given + new Expectations() {{ + customResourceManifestDir.list(); + result = new String[] {"/foo/bar/first-cr.yaml"}; + }}; + + // When + boolean result = ResourceUtil.hasCustomResourceManifests(customResourceManifestDir); + + // Then + assertTrue(result); + } + + @Test + public void testHasCustomResourceManifestsWithEmptyFragmentDir(@Mocked File customResourceManifestDir) { + // Given + new Expectations() {{ + customResourceManifestDir.list(); + result = new String[0]; + }}; + + // When + boolean result = ResourceUtil.hasCustomResourceManifests(customResourceManifestDir); + + // Then + assertFalse(result); + } + + @Test + public void testHasCustomResourceManifestsWithNullFragmentDir() { + assertFalse(ResourceUtil.hasCustomResourceManifests(null)); + } + + @Test + public void testGetCustomResourceManifestDir(@Mocked JavaProject javaProject) { + // Given + new Expectations() {{ + javaProject.getOutputDirectory(); + result = folder.getRoot(); + }}; + + // When + File customResourceManifestDir = ResourceUtil.getCustomResourceManifestDir(javaProject); + + // Then + assertNotNull(customResourceManifestDir); + } + + @Test + public void testGetCustomResourceManifestDirWhenOutputDirectoryNull(@Mocked JavaProject javaProject) { + // Given + When + File customResourceManifestDir = ResourceUtil.getCustomResourceManifestDir(javaProject); + + // Then + assertNull(customResourceManifestDir); + } } diff --git a/jkube-kit/common/src/test/resources/test-file.txt b/jkube-kit/common/src/test/resources/test-file.txt new file mode 100644 index 0000000000..81456f0a9d --- /dev/null +++ b/jkube-kit/common/src/test/resources/test-file.txt @@ -0,0 +1 @@ +This project is maintained by ${org.name} \ No newline at end of file diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/ApplyService.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/ApplyService.java index 9da540b615..f68f7c6575 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/ApplyService.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/ApplyService.java @@ -471,13 +471,13 @@ public void applyCustomResource(File customResourceFile, String namespace, Custo KubernetesClientUtil.doCreateCustomResource(kubernetesClient, context, namespace, customResourceFile); log.info("Created Custom Resource: %s %s", KubernetesHelper.getFullyQualifiedApiGroupWithKind(context), name); } else { - cr = KubernetesClientUtil.doGetCustomResource(kubernetesClient, context, namespace, name); - if (cr == null) { + Map crFromServer = KubernetesClientUtil.doGetCustomResource(kubernetesClient, context, namespace, name); + if (crFromServer == null) { KubernetesClientUtil.doCreateCustomResource(kubernetesClient, context, namespace, customResourceFile); - log.info("Created Custom Resource: %s", KubernetesHelper.getFullyQualifiedApiGroupWithKind(context), name); + log.info("Created Custom Resource: %s %s", KubernetesHelper.getFullyQualifiedApiGroupWithKind(context), name); } else { - KubernetesClientUtil.doEditCustomResource(kubernetesClient, context, namespace, name, customResourceFile); - log.info("Updated Custom Resource: %s", KubernetesHelper.getFullyQualifiedApiGroupWithKind(context), name); + KubernetesClientUtil.doEditCustomResource(kubernetesClient, context, namespace, name, cr); + log.info("Updated Custom Resource: %s %s", KubernetesHelper.getFullyQualifiedApiGroupWithKind(context), name); } } } @@ -1381,13 +1381,12 @@ public void setRollingUpgradePreserveScale(boolean rollingUpgradePreserveScale) this.rollingUpgradePreserveScale = rollingUpgradePreserveScale; } - public void processCustomEntities(List customResourceDefinitions, File resourceDir, String environment, List remotes) throws Exception { + public void processCustomEntities(List customResourceDefinitions, File customResourceOutputDir, List remotes) throws Exception { if(customResourceDefinitions == null) return; List crdContexts = KubernetesClientUtil.getCustomResourceDefinitionContext(kubernetesClient ,customResourceDefinitions); - File resourceDirFinal = ResourceUtil.getFinalResourceDir(resourceDir, environment); - Map fileToCrdMap = getCustomResourcesFileToNameMap(resourceDirFinal, remotes, log); + Map fileToCrdMap = getCustomResourcesFileToNameMap(customResourceOutputDir, remotes, log); for(CustomResourceDefinitionContext customResourceDefinitionContext : crdContexts) { for(Map.Entry entry : fileToCrdMap.entrySet()) { @@ -1415,15 +1414,14 @@ public void applyNamespaceOrProjectIfPresent(Collection entities) { } public void applyEntities(String fileName, Set entities, KitLogger serviceLogger, - long serviceUrlWaitTimeSeconds, ResourceConfig resources, File resourceDir, - String environment) throws Exception { + long serviceUrlWaitTimeSeconds, ResourceConfig resources, File customResourceManifestDir) throws Exception { // Apply Namespace/Project first applyNamespaceOrProjectIfPresent(entities); // Apply all items applyStandardEntities(fileName, entities); logExposeServiceUrl(entities, serviceLogger, serviceUrlWaitTimeSeconds); processCustomEntities(resources != null ? resources.getCustomResourceDefinitions() : null, - resourceDir, environment, resources != null ? resources.getRemotes() : null); + customResourceManifestDir, resources != null ? resources.getRemotes() : null); } private void logExposeServiceUrl(Set entities, KitLogger serviceLogger, long serviceUrlWaitTimeSeconds) throws InterruptedException { diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesClientUtil.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesClientUtil.java index 6269a7b63b..50c696a6b7 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesClientUtil.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesClientUtil.java @@ -241,11 +241,11 @@ public static Map doCreateCustomResource(KubernetesClient kubern } } - public static Map doEditCustomResource(KubernetesClient kubernetesClient, CustomResourceDefinitionContext crdContext, String namespace, String name, File customResourceFile) throws IOException { + public static Map doEditCustomResource(KubernetesClient kubernetesClient, CustomResourceDefinitionContext crdContext, String namespace, String name, Map customResource) throws IOException { if ("Namespaced".equals(crdContext.getScope())) { - return kubernetesClient.customResource(crdContext).edit(namespace, name, new FileInputStream(customResourceFile.getAbsolutePath())); + return kubernetesClient.customResource(crdContext).edit(namespace, name, customResource); } else { - return kubernetesClient.customResource(crdContext).edit(name, doGetCustomResourceAsString(customResourceFile)); + return kubernetesClient.customResource(crdContext).edit(name, customResource); } } diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesUndeployService.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesUndeployService.java index 0ea870fe88..483d3cc6f2 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesUndeployService.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/KubernetesUndeployService.java @@ -39,6 +39,8 @@ import static org.eclipse.jkube.kit.common.util.KubernetesHelper.getCustomResourcesFileToNameMap; import static org.eclipse.jkube.kit.common.util.KubernetesHelper.loadResources; import static org.eclipse.jkube.kit.common.util.KubernetesHelper.unmarshalCustomResourceFile; +import static org.eclipse.jkube.kit.common.util.ResourceUtil.getCustomResourceManifestDir; +import static org.eclipse.jkube.kit.common.util.ResourceUtil.hasCustomResourceManifests; import static org.eclipse.jkube.kit.config.service.kubernetes.KubernetesClientUtil.getCustomResourceDefinitionContext; public class KubernetesUndeployService implements UndeployService { @@ -56,18 +58,19 @@ public void undeploy(File resourceDir, ResourceConfig resourceConfig, File... ma final List manifests = Stream.of(manifestFiles) .filter(Objects::nonNull).filter(File::exists).filter(File::isFile) .collect(Collectors.toList()); + File customResourceManifestDir = getCustomResourceManifestDir(jKubeServiceHub.getConfiguration().getProject()); final List entities = new ArrayList<>(); for (File manifest : manifests) { entities.addAll(loadResources(manifest)); } - if (entities.isEmpty()) { + if (entities.isEmpty() && !hasCustomResourceManifests(customResourceManifestDir)) { logger.warn("No such generated manifests found for this project, ignoring."); return; } Collections.reverse(entities); final String currentNamespace = currentNamespace(entities); + undeployCustomResources(currentNamespace, customResourceManifestDir, resourceConfig); undeployResources(currentNamespace, entities); - undeployCustomResources(currentNamespace, resourceDir, resourceConfig); } private void undeployResources(String namespace, List entities) { diff --git a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/ApplyServiceTest.java b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/ApplyServiceTest.java index 82e6b985f3..3a48dc128e 100644 --- a/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/ApplyServiceTest.java +++ b/jkube-kit/config/service/src/test/java/org/eclipse/jkube/kit/config/service/ApplyServiceTest.java @@ -139,7 +139,7 @@ public void testApplyEntities() throws Exception { .once(); // When - applyService.applyEntities(fileName, entities, log, 5, null, null, null); + applyService.applyEntities(fileName, entities, log, 5, null, null); // Then collector.assertEventsRecordedInOrder("new-rc", "new-configmap", "new-service", "new-deploy", "new-pod"); @@ -253,7 +253,7 @@ public void testProcessCustomEntities() throws Exception { .once(); // When - applyService.processCustomEntities(crdNames, crFragmentDir, null, Collections.emptyList()); + applyService.processCustomEntities(crdNames, crFragmentDir, Collections.emptyList()); // Then collector.assertEventsRecordedInOrder("get-crd-virtualservice", "get-crd-gateway", "post-cr-virtualservice", "post-cr-gateway"); @@ -278,27 +278,27 @@ public void testProcessCustomEntitiesReplaceCustomResources() throws Exception { .always(); mockServer.expect().get() .withPath("/apis/networking.istio.io/v1alpha3/namespaces/default/virtualservices/reviews-route") - .andReply(collector.record("get-cr-virtualservice").andReturn(HTTP_OK, "{}")) - .once(); + .andReply(collector.record("get-cr-virtualservice").andReturn(HTTP_OK, "{\"metadata\":{\"resourceVersion\":\"1001\"}}")) + .times(2); mockServer.expect().put() .withPath("/apis/networking.istio.io/v1alpha3/namespaces/default/virtualservices/reviews-route") .andReply(collector.record("put-cr-virtualservice").andReturn(HTTP_OK, "{}")) .once(); mockServer.expect().get() .withPath("/apis/networking.istio.io/v1alpha3/namespaces/default/gateways/mygateway-https") - .andReply(collector.record("get-cr-gateway").andReturn(HTTP_OK, "{}")) - .once(); + .andReply(collector.record("get-cr-gateway").andReturn(HTTP_OK, "{\"metadata\":{\"resourceVersion\":\"1002\"}}")) + .times(2); mockServer.expect().put() .withPath("/apis/networking.istio.io/v1alpha3/namespaces/default/gateways/mygateway-https") .andReply(collector.record("put-cr-gateway").andReturn(HTTP_OK, "{}")) .once(); // When - applyService.processCustomEntities(crdNames, crFragmentDir, null, Collections.emptyList()); + applyService.processCustomEntities(crdNames, crFragmentDir, Collections.emptyList()); // Then collector.assertEventsRecordedInOrder("get-crd-virtualservice", "get-crd-gateway", "get-cr-virtualservice", "put-cr-virtualservice", "get-cr-gateway", "put-cr-gateway"); - assertEquals(7, mockServer.getMockServer().getRequestCount()); + assertEquals(9, mockServer.getMockServer().getRequestCount()); } @Test @@ -336,7 +336,7 @@ public void testProcessCustomEntitiesRecreateModeTrue() throws Exception { applyService.setRecreateMode(true); // When - applyService.processCustomEntities(crdNames, crFragmentDir, null, Collections.emptyList()); + applyService.processCustomEntities(crdNames, crFragmentDir, Collections.emptyList()); applyService.setRecreateMode(false); // Then @@ -351,7 +351,7 @@ public void testProcessCustomEntitiesWithNullCustomResourceList() throws Excepti File crFragmentDir = new File(getClass().getResource("/gateway-cr.yml").getFile()).getParentFile(); // When - applyService.processCustomEntities(null, crFragmentDir, null, Collections.emptyList()); + applyService.processCustomEntities(null, crFragmentDir, Collections.emptyList()); // Then assertEquals(1, mockServer.getMockServer().getRequestCount()); // This one is just /apis check diff --git a/jkube-kit/enricher/api/src/main/java/org/eclipse/jkube/kit/enricher/api/BaseEnricher.java b/jkube-kit/enricher/api/src/main/java/org/eclipse/jkube/kit/enricher/api/BaseEnricher.java index c9e230ef6e..0306bff596 100644 --- a/jkube-kit/enricher/api/src/main/java/org/eclipse/jkube/kit/enricher/api/BaseEnricher.java +++ b/jkube-kit/enricher/api/src/main/java/org/eclipse/jkube/kit/enricher/api/BaseEnricher.java @@ -54,6 +54,9 @@ public class BaseEnricher implements Enricher { private static final String SWITCH_TO_DEPLOYMENT = "jkube.build.switchToDeployment"; public static final String CREATE_EXTERNAL_URLS = "jkube.createExternalUrls"; public static final String JKUBE_DOMAIN = "jkube.domain"; + public static final String RESOURCE_DIR = "jkube.resourceDir"; + public static final String RESOURCE_OUTPUT_DIR = "jkube.targetDir"; + public static final String ENVIRONMENT = "jkube.environment"; protected KitLogger log; diff --git a/jkube-kit/enricher/generic/src/main/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricher.java b/jkube-kit/enricher/generic/src/main/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricher.java new file mode 100644 index 0000000000..17713afe1a --- /dev/null +++ b/jkube-kit/enricher/generic/src/main/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricher.java @@ -0,0 +1,118 @@ +/** + * 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.enricher.generic; + +import io.fabric8.kubernetes.api.model.KubernetesListBuilder; +import org.eclipse.jkube.kit.common.util.JKubeFileInterpolator; +import org.eclipse.jkube.kit.common.util.ResourceUtil; +import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; +import org.eclipse.jkube.kit.config.resource.PlatformMode; +import org.eclipse.jkube.kit.config.resource.ResourceConfig; +import org.eclipse.jkube.kit.enricher.api.BaseEnricher; +import org.eclipse.jkube.kit.enricher.api.JKubeEnricherContext; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.eclipse.jkube.kit.common.util.KubernetesHelper.getCustomResourcesFileToNameMap; + +public class CustomResourceEnricher extends BaseEnricher { + private static final String CUSTOM_RESOURCE_OUTPUT_DIR = "custom-resources"; + + public CustomResourceEnricher(JKubeEnricherContext jKubeEnricherContext) { + super(jKubeEnricherContext, "jkube-customresource"); + } + + @Override + public void create(PlatformMode platformMode, final KubernetesListBuilder listBuilder) { + String resourceSourceDirProperty = getValueFromConfig(RESOURCE_DIR, "src/main/jkube"); + String resourceOutputDirProperty = getValueFromConfig(RESOURCE_OUTPUT_DIR, "META-INF/jkube"); + String environment = getValueFromConfig(ENVIRONMENT, ""); + File resourceInputDirFile = new File(getContext().getProject().getBaseDirectory(), resourceSourceDirProperty); + File resourceDirFinal = ResourceUtil.getFinalResourceDir(resourceInputDirFile, environment); + File resourceOutputDirFile = new File(getContext().getProject().getOutputDirectory(), resourceOutputDirProperty + File.separator + CUSTOM_RESOURCE_OUTPUT_DIR); + + processCustomResourceInFragmentDir(resourceDirFinal, resourceOutputDirFile); + } + + List processCustomResourceInFragmentDir(File resourceDirFinal, File resourceOutputDirFile) { + if (resourceDirFinal.exists()) { + try { + return findAndProcessCustomResourceFragmentsInFragmentsDir(resourceDirFinal, resourceOutputDirFile); + } catch (IOException ioException) { + log.error("Error in processing CustomResource fragments: %s", ioException.getMessage()); + } + } + return Collections.emptyList(); + } + + private List findAndProcessCustomResourceFragmentsInFragmentsDir(File resourceDirFinal, File resourceOutputDirFile) throws IOException { + Map fileToCustomResourceNameMap = getCustomResourcesFileToNameMap(resourceDirFinal, getRemoteFragments(), log); + if (!fileToCustomResourceNameMap.isEmpty()) { + createCustomResourceOutputDirIfNotPresent(resourceOutputDirFile); + return writeInterpolatedCustomResourcesToOutputDirectory(resourceOutputDirFile, fileToCustomResourceNameMap); + } + return Collections.emptyList(); + } + + private List writeInterpolatedCustomResourcesToOutputDirectory(File resourceOutputDir, Map fileToCrNameMap) throws IOException { + List writtenCustomResourceFragments = new ArrayList<>(); + for (Map.Entry fileToCrName : fileToCrNameMap.entrySet()) { + File customResourceOutputFile = new File(resourceOutputDir, fileToCrName.getKey().getName()); + writeCustomResourceFragment(fileToCrName, customResourceOutputFile); + writtenCustomResourceFragments.add(customResourceOutputFile); + } + return writtenCustomResourceFragments; + } + + private void writeCustomResourceFragment(Map.Entry fileToCrName, File customResourceOutputFile) throws IOException { + createCustomResourceFragmentInOutputDirIfNotPresent(customResourceOutputFile); + String interpolatedCustomResourceAsStr = JKubeFileInterpolator.interpolate(fileToCrName.getKey(), getContext().getProperties(), BuildConfiguration.DEFAULT_FILTER); + try (FileWriter customResourceFileWriter = new FileWriter(customResourceOutputFile)) { + log.info("Processing CustomResource fragment %s", fileToCrName.getKey()); + customResourceFileWriter.write(interpolatedCustomResourceAsStr); + } + } + + private void createCustomResourceOutputDirIfNotPresent(File customResourceOutputDir) { + if (!customResourceOutputDir.exists()) { + boolean isCreated = customResourceOutputDir.mkdirs(); + if (!isCreated) { + log.error("Error in creating file: %s", customResourceOutputDir.getAbsolutePath()); + } + } + } + + private void createCustomResourceFragmentInOutputDirIfNotPresent(File customResourceOutputFile) throws IOException { + if (!customResourceOutputFile.exists()) { + boolean isFileCreated = customResourceOutputFile.createNewFile(); + if (!isFileCreated) { + log.warn("Not able to create %s", customResourceOutputFile.getAbsolutePath()); + } + } + } + + private List getRemoteFragments() { + ResourceConfig resourceConfig = getContext().getConfiguration().getResource(); + if (resourceConfig != null) { + return resourceConfig.getRemotes(); + } + return Collections.emptyList(); + } +} diff --git a/jkube-kit/enricher/generic/src/main/resources/META-INF/jkube/enricher-default b/jkube-kit/enricher/generic/src/main/resources/META-INF/jkube/enricher-default index a4bd4d00af..d03a1caf8f 100644 --- a/jkube-kit/enricher/generic/src/main/resources/META-INF/jkube/enricher-default +++ b/jkube-kit/enricher/generic/src/main/resources/META-INF/jkube/enricher-default @@ -104,3 +104,6 @@ org.eclipse.jkube.enricher.generic.IngressEnricher # Merge JAVA_OPTIONS environment variables from Image Build Configurations and enriched Containers org.eclipse.jkube.enricher.generic.ContainerEnvJavaOptionsMergeEnricher + +# Process Custom Resources +org.eclipse.jkube.enricher.generic.CustomResourceEnricher \ No newline at end of file diff --git a/jkube-kit/enricher/generic/src/test/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricherTest.java b/jkube-kit/enricher/generic/src/test/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricherTest.java new file mode 100644 index 0000000000..c91fb9443e --- /dev/null +++ b/jkube-kit/enricher/generic/src/test/java/org/eclipse/jkube/enricher/generic/CustomResourceEnricherTest.java @@ -0,0 +1,183 @@ +/** + * 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.enricher.generic; + +import mockit.Expectations; +import mockit.Mocked; +import org.eclipse.jkube.kit.config.resource.PlatformMode; +import org.eclipse.jkube.kit.enricher.api.JKubeEnricherContext; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class CustomResourceEnricherTest { + @Mocked + private JKubeEnricherContext context; + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + private void setupExpectations(Properties properties) { + new Expectations() {{ + context.getProperties(); + result = properties; + + context.getConfiguration().getResource(); + result = null; + }}; + } + + @Test + public void testProcessCustomResourceInFragmentDirWithNonExistentFragmentDir() { + // Given + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + File sourceDir = new File("i-dont-exist/src/main/jkube"); + File targetDir = new File("i-dont-exist/target/classes/"); + + // When + List resultFragments = customResourceEnricher.processCustomResourceInFragmentDir(sourceDir, targetDir); + + // Then + assertNotNull(resultFragments); + assertEquals(0, resultFragments.size()); + } + + @Test + public void testProcessCustomResourceInFragmentDirWithEmptyFragmentDir() throws IOException { + // Given + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + File sourceDir = folder.newFolder("source-fragments"); + File targetDir = folder.newFolder("target-fragments"); + + // When + List resultFragments = customResourceEnricher.processCustomResourceInFragmentDir(sourceDir, targetDir); + + // Then + assertNotNull(resultFragments); + assertEquals(0, resultFragments.size()); + } + + @Test + public void testProcessCustomResourceInFragmentDirWithNoInterpolationArgs() throws IOException { + // Given + setupExpectations(new Properties()); + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + File sourceDir = new File(getClass().getResource("/test-custom-resource-standard").getFile()); + File targetDir = folder.getRoot(); + + // When + List resultFragments = customResourceEnricher.processCustomResourceInFragmentDir(sourceDir, targetDir); + + // Then + assertNotNull(resultFragments); + assertEquals(1, resultFragments.size()); + String fileAsStr = new String(Files.readAllBytes(resultFragments.get(0).toPath())); + String[] lines = fileAsStr.split(System.lineSeparator()); + assertEquals("apiVersion: org.eclipse.jkube/v1alpha1", lines[0]); + assertEquals("kind: EclipseJKubeTest", lines[1]); + assertEquals("metadata:", lines[2]); + assertEquals(" name: example-eclipsejkubetest", lines[3]); + assertEquals("spec:", lines[4]); + assertEquals(" replicas: 3", lines[5]); + } + + @Test + public void testProcessCustomResourceInFragmentDirWithInterpolationArgs() throws IOException { + // Given + Properties properties = new Properties(); + properties.put("jkube.replicas", "3"); + setupExpectations(properties); + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + File sourceDir = new File(getClass().getResource("/test-custom-resource-interpolated").getFile()); + File targetDir = folder.getRoot(); + + // When + List resultFragments = customResourceEnricher.processCustomResourceInFragmentDir(sourceDir, targetDir); + + // Then + assertNotNull(resultFragments); + assertEquals(1, resultFragments.size()); + String fileAsStr = new String(Files.readAllBytes(resultFragments.get(0).toPath())); + String[] lines = fileAsStr.split(System.lineSeparator()); + assertEquals("apiVersion: org.eclipse.jkube/v1alpha1", lines[0]); + assertEquals("kind: EclipseJKubeTest", lines[1]); + assertEquals("metadata:", lines[2]); + assertEquals(" name: example-eclipsejkubetest", lines[3]); + assertEquals("spec:", lines[4]); + assertEquals(" replicas: 3", lines[5]); + } + + @Test + public void testProcessCustomResourceInFragmentDirShouldCreateOutputDirWhenAbsent() { + // Given + setupExpectations(new Properties()); + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + File sourceDir = new File(getClass().getResource("/test-custom-resource-standard").getFile()); + File targetDir = new File(folder.getRoot(), "custom-resource-output"); + + // When + List resultFragments = customResourceEnricher.processCustomResourceInFragmentDir(sourceDir, targetDir); + + // Then + assertNotNull(resultFragments); + assertEquals(1, resultFragments.size()); + assertTrue(targetDir.exists()); + assertEquals(targetDir, resultFragments.get(0).getParentFile()); + } + + @Test + public void testCreate() throws IOException { + // Given + File projectBaseDir = folder.newFolder("create-test"); + File fragmentDir = new File(projectBaseDir, "src/main/jkube"); + File customResourceFragmentDir = new File(getClass().getResource("/test-custom-resource-standard").getFile()); + File crFragment = new File(customResourceFragmentDir, "test-cr.yml"); + boolean fragmentDirCreated = fragmentDir.mkdirs(); + Files.copy(crFragment.toPath(), new File(fragmentDir, crFragment.getName()).toPath()); + File targetDir = new File(projectBaseDir, "target/classes"); + boolean targetDirCreated = targetDir.mkdirs(); + new Expectations() {{ + context.getProject().getBaseDirectory(); + result = projectBaseDir; + context.getProject().getOutputDirectory(); + result = targetDir; + context.getProperties(); + result = new Properties(); + }}; + CustomResourceEnricher customResourceEnricher = new CustomResourceEnricher(context); + + // When + customResourceEnricher.create(PlatformMode.kubernetes, null); + + // Then + File customResourceOutputDir = new File(targetDir, "META-INF/jkube/custom-resources"); + assertTrue(fragmentDirCreated); + assertTrue(targetDirCreated); + assertTrue(customResourceOutputDir.exists()); + assertTrue(customResourceOutputDir.isDirectory()); + assertEquals(1, Objects.requireNonNull(customResourceOutputDir.listFiles()).length); + } + +} diff --git a/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-interpolated/test-cr.yml b/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-interpolated/test-cr.yml new file mode 100644 index 0000000000..0c6af6ce5e --- /dev/null +++ b/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-interpolated/test-cr.yml @@ -0,0 +1,6 @@ +apiVersion: org.eclipse.jkube/v1alpha1 +kind: EclipseJKubeTest +metadata: + name: example-eclipsejkubetest +spec: + replicas: ${jkube.replicas} \ No newline at end of file diff --git a/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-standard/test-cr.yml b/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-standard/test-cr.yml new file mode 100644 index 0000000000..2bb8759bfe --- /dev/null +++ b/jkube-kit/enricher/generic/src/test/resources/test-custom-resource-standard/test-cr.yml @@ -0,0 +1,6 @@ +apiVersion: org.eclipse.jkube/v1alpha1 +kind: EclipseJKubeTest +metadata: + name: example-eclipsejkubetest +spec: + replicas: 3 \ No newline at end of file diff --git a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ApplyMojo.java b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ApplyMojo.java index 5686385775..d51ee548ea 100644 --- a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ApplyMojo.java +++ b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/ApplyMojo.java @@ -35,6 +35,7 @@ import java.net.URL; import java.util.Set; +import static org.eclipse.jkube.kit.common.util.ResourceUtil.getCustomResourceManifestDir; import static org.eclipse.jkube.kit.config.service.ApplyService.getNamespaceForApplyService; /** @@ -196,7 +197,7 @@ public void executeInternal() throws MojoExecutionException { protected void applyEntities(final KubernetesClient kubernetes, final String namespace, String fileName, final Set entities) throws Exception { KitLogger serviceLogger = createLogger("[[G]][SVC][[G]] [[s]]"); applyService.applyEntities(fileName, entities, - serviceLogger, serviceUrlWaitTimeSeconds, resources, resourceDir, environment); + serviceLogger, serviceUrlWaitTimeSeconds, resources, getCustomResourceManifestDir(MavenUtil.convertMavenProjectToJKubeProject(project, session))); } protected void initServices(KubernetesClient kubernetes) { 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 9c82db24eb..533aac86ab 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 @@ -83,6 +83,8 @@ public class ResourceMojo extends AbstractJKubeMojo { // Filename for holding the build timestamp public static final String DOCKER_BUILD_TIMESTAMP = "docker/build.timestamp"; + private static final String CUSTOM_RESOURCE_OUTPUT_DIR = "custom-resources"; + private static final String DOCKER_IMAGE_USER = "docker.image.user"; /** * The generated kubernetes and openshift manifests @@ -230,8 +232,10 @@ public void executeInternal() throws MojoExecutionException, MojoFailureExceptio // Extract and generate resources which can be a mix of Kubernetes and OpenShift resources final ResourceClassifier resourceClassifier = getResourceClassifier(); final KubernetesList resourceList = generateResources(); - final File resourceClassifierDir = new File(this.targetDir, resourceClassifier.getValue()); - validateIfRequired(resourceClassifierDir, resourceClassifier); + final File kubernetesResourceClassifierDir = new File(this.targetDir, resourceClassifier.getValue()); + final File customResourceClassifierDir = new File(this.targetDir, CUSTOM_RESOURCE_OUTPUT_DIR); + validateIfRequired(kubernetesResourceClassifierDir, resourceClassifier); + validateIfRequired(customResourceClassifierDir, resourceClassifier); final File artifact = jkubeServiceHub.getResourceService().writeResources(resourceList, resourceClassifier, log); // Attach it to the Maven reactor so that it will also get deployed projectHelper.attachArtifact(project, this.resourceFileType.getArtifactType(), resourceClassifier.getValue(), artifact); diff --git a/kubernetes-maven-plugin/plugin/src/main/resources/META-INF/jkube/profiles-default.yml b/kubernetes-maven-plugin/plugin/src/main/resources/META-INF/jkube/profiles-default.yml index dbb578d115..d7af555072 100644 --- a/kubernetes-maven-plugin/plugin/src/main/resources/META-INF/jkube/profiles-default.yml +++ b/kubernetes-maven-plugin/plugin/src/main/resources/META-INF/jkube/profiles-default.yml @@ -35,6 +35,7 @@ - jkube-maven-scm - jkube-serviceaccount - jkube-maven-issue-mgmt + - jkube-customresource # TODO: Documents and verify enrichers below - jkube-debug - jkube-remove-build-annotations