From e76aaf00b97c7053b34c137507642ac7343279d7 Mon Sep 17 00:00:00 2001 From: Alex Soto Date: Tue, 18 Sep 2018 15:07:50 +0200 Subject: [PATCH] feat(#1382): Allow to provide additional fragment filename mappings --- .../maven/core/config/MappingConfig.java | 24 ++++++++ .../maven/core/config/ResourceConfig.java | 1 - .../maven/core/util/AsciiDocParser.java | 2 +- .../core/util/PropertiesMappingParser.java | 52 +++++++++++++++++ .../kubernetes/KindFilenameMapperUtil.java | 27 ++++++++- .../kubernetes/KubernetesResourceUtil.java | 10 ++++ .../util/PropertiesMappingParserTest.java | 37 ++++++++++++ .../KindFilenameMapperUtilTest.java | 56 +++++++++++++++++++ .../KubernetesResourceUtilTest.java | 40 ++++++++++++- parent/pom.xml | 7 +++ plugin/pom.xml | 6 ++ .../maven/plugin/mojo/build/ResourceMojo.java | 22 +++++++- .../plugin/mojo/build/MappingConfigTest.java | 36 ++++++++++++ .../mojo/build/mapping-mojo-config.xml | 18 ++++++ 14 files changed, 331 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/io/fabric8/maven/core/config/MappingConfig.java create mode 100644 core/src/main/java/io/fabric8/maven/core/util/PropertiesMappingParser.java create mode 100644 core/src/test/java/io/fabric8/maven/core/util/PropertiesMappingParserTest.java create mode 100644 plugin/src/test/java/io/fabric8/maven/plugin/mojo/build/MappingConfigTest.java create mode 100644 plugin/src/test/resources/mojo/build/mapping-mojo-config.xml diff --git a/core/src/main/java/io/fabric8/maven/core/config/MappingConfig.java b/core/src/main/java/io/fabric8/maven/core/config/MappingConfig.java new file mode 100644 index 0000000000..c0f109a80b --- /dev/null +++ b/core/src/main/java/io/fabric8/maven/core/config/MappingConfig.java @@ -0,0 +1,24 @@ +package io.fabric8.maven.core.config; + +import org.apache.maven.plugins.annotations.Parameter; + +public class MappingConfig { + + @Parameter(required = true) + private String kind; + + @Parameter(required = true) + private String filenames; + + public String getKind() { + return kind; + } + + public String getFilenames() { + return filenames; + } + + public String[] getFilenamesAsArray() { + return filenames.split(",\\s*"); + } +} diff --git a/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java b/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java index 0cf55ddd73..727958d78d 100644 --- a/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java +++ b/core/src/main/java/io/fabric8/maven/core/config/ResourceConfig.java @@ -36,7 +36,6 @@ public class ResourceConfig { @Parameter private MetaDataConfig annotations = new MetaDataConfig(); - ; @Parameter private List volumes; diff --git a/core/src/main/java/io/fabric8/maven/core/util/AsciiDocParser.java b/core/src/main/java/io/fabric8/maven/core/util/AsciiDocParser.java index 88b6c7f832..72d48dc7b6 100644 --- a/core/src/main/java/io/fabric8/maven/core/util/AsciiDocParser.java +++ b/core/src/main/java/io/fabric8/maven/core/util/AsciiDocParser.java @@ -57,7 +57,7 @@ public class AsciiDocParser { * This method returns an @code{IllegalArgumentException} if does not contain two columns. * * @param table definition in AsciiDoc format. - * @return A serialization of all columns, being pair elements the first column and the odd elements the second column. In previous example @code{"cm","ConfigMap","cronjob","CronJob"} + * @return A serialization of all columns. */ public Map> serializeKindFilenameTable(final InputStream table) { diff --git a/core/src/main/java/io/fabric8/maven/core/util/PropertiesMappingParser.java b/core/src/main/java/io/fabric8/maven/core/util/PropertiesMappingParser.java new file mode 100644 index 0000000000..8edd44ea1f --- /dev/null +++ b/core/src/main/java/io/fabric8/maven/core/util/PropertiesMappingParser.java @@ -0,0 +1,52 @@ +package io.fabric8.maven.core.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +public class PropertiesMappingParser { + + /** + * This method reads properties file to load custom mapping between kinds and filenames. + * + *
+     * ConfigMap=cm, configmap
+     * Service=service
+     * 
+ * + * @param mapping + * stream of a properties file setting mappings between kinds and filenames. + * + * @return Serialization of all elements as a map + */ + public Map> parse(final InputStream mapping) { + + final Properties mappingProperties = new Properties(); + try { + mappingProperties.load(mapping); + + final Map> serializedContent = new HashMap<>(); + + final Set kinds = mappingProperties.stringPropertyNames(); + + for (String kind : kinds) { + final String filenames = mappingProperties.getProperty(kind); + final String[] filenameTypes = filenames.split(","); + final List scannedFiletypes = new ArrayList<>(); + for (final String filenameType : filenameTypes) { + scannedFiletypes.add(filenameType.trim()); + } + serializedContent.put(kind, scannedFiletypes); + } + + return serializedContent; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtil.java b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtil.java index b365589349..bd686dbeb6 100644 --- a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtil.java +++ b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtil.java @@ -17,6 +17,11 @@ package io.fabric8.maven.core.util.kubernetes; import io.fabric8.maven.core.util.AsciiDocParser; +import io.fabric8.maven.core.util.EnvUtil; +import io.fabric8.maven.core.util.PropertiesMappingParser; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.List; @@ -27,10 +32,20 @@ public class KindFilenameMapperUtil { public static Map> loadMappings() { final String location = "/META-INF/fabric8/kind-filename-type-mapping-default.adoc"; + final String locationMappingProperties = + EnvUtil.getEnvVarOrSystemProperty("fabric8.mapping", "/META-INF/fabric8/kind-filename-type-mapping-default.properties"); - try (final InputStream mappingFile = loadContent(location)) { + try (final InputStream mappingFile = loadContent(location); final InputStream mappingPropertiesFile = loadContent(locationMappingProperties)) { final AsciiDocParser asciiDocParser = new AsciiDocParser(); - return asciiDocParser.serializeKindFilenameTable(mappingFile); + final Map> defaultMapping = asciiDocParser.serializeKindFilenameTable(mappingFile); + + if (mappingPropertiesFile != null) { + PropertiesMappingParser propertiesMappingParser = new PropertiesMappingParser(); + defaultMapping.putAll(propertiesMappingParser.parse(mappingPropertiesFile)); + } + + return defaultMapping; + } catch (IOException e) { throw new IllegalStateException(e); } @@ -40,7 +55,13 @@ private static InputStream loadContent(String location) { InputStream resourceAsStream = KindFilenameMapperUtil.class.getResourceAsStream(location); if (resourceAsStream == null) { - throw new IllegalArgumentException(String.format("%s cannot be found in classpath", location)); + final File locationFile = new File(location); + + try { + return new FileInputStream(locationFile); + } catch (FileNotFoundException e) { + return null; + } } return resourceAsStream; diff --git a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java index 90804ba880..f7983149b0 100644 --- a/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java +++ b/core/src/main/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtil.java @@ -191,6 +191,15 @@ public boolean accept(File dir, String name) { protected final static void initializeKindFilenameMapper() { final Map> mappings = KindFilenameMapperUtil.loadMappings(); + updateKindFilenameMapper(mappings); + } + + protected final static void remove(String kind, String filename) { + FILENAME_TO_KIND_MAPPER.remove(filename); + KIND_TO_FILENAME_MAPPER.remove(kind); + } + + public final static void updateKindFilenameMapper(final Map> mappings) { final Set>> entries = mappings.entrySet(); @@ -206,6 +215,7 @@ protected final static void initializeKindFilenameMapper() { KIND_TO_FILENAME_MAPPER.put(kind, filenameTypes.get(filenameTypes.size() - 1)); } + } private static final String FILENAME_PATTERN = "^(?.*?)(-(?[^-]+))?\\.(?yaml|yml|json)$"; diff --git a/core/src/test/java/io/fabric8/maven/core/util/PropertiesMappingParserTest.java b/core/src/test/java/io/fabric8/maven/core/util/PropertiesMappingParserTest.java new file mode 100644 index 0000000000..e0bb426549 --- /dev/null +++ b/core/src/test/java/io/fabric8/maven/core/util/PropertiesMappingParserTest.java @@ -0,0 +1,37 @@ +package io.fabric8.maven.core.util; + +import java.io.ByteArrayInputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PropertiesMappingParserTest { + + private static final String MAPPING_PROPERTIES = "ConfigMap=cm, configmap"; + + @Test + public void should_read_mappings_from_properties_file() { + + // Given + + final PropertiesMappingParser propertiesMappingParser = new PropertiesMappingParser(); + + // When + + final Map> serializedContent = + propertiesMappingParser.parse(new ByteArrayInputStream(MAPPING_PROPERTIES.getBytes())); + + // Then + + final Map> expectedSerlializedContent = new HashMap<>(); + expectedSerlializedContent.put("ConfigMap", Arrays.asList("cm", "configmap")); + + assertThat(serializedContent) + .containsAllEntriesOf(expectedSerlializedContent); + } + +} diff --git a/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtilTest.java b/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtilTest.java index c89f497a7b..7f43d4b10b 100644 --- a/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtilTest.java +++ b/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KindFilenameMapperUtilTest.java @@ -16,16 +16,31 @@ package io.fabric8.maven.core.util.kubernetes; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; public class KindFilenameMapperUtilTest { + private static final String MAPPING_PROPERTIES = "Var=foo, bar"; + private static final String OVERRIDE_MAPPING_PROPERTIES = "ConfigMap=foo, bar"; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + @Test public void should_load_default_mapping_file() { @@ -43,6 +58,47 @@ public void should_load_default_mapping_file() { } + @Test + public void should_load_mappings_from_custom_properties_file() throws IOException { + + // Given + + final File customMappings = temporaryFolder.newFile("custom.properties"); + Files.write(customMappings.toPath(), MAPPING_PROPERTIES.getBytes()); + System.setProperty("fabric8.mapping", customMappings.getAbsolutePath()); + + // When + + final Map> mappings = KindFilenameMapperUtil.loadMappings(); + + // Then + final Map> expectedSerlializedContent = new HashMap<>(); + expectedSerlializedContent.put("ConfigMap", Arrays.asList("cm", "configmap")); + expectedSerlializedContent.put("CronJob", Arrays.asList("cj", "cronjob")); + expectedSerlializedContent.put("Var", Arrays.asList("foo", "bar")); + assertThat(mappings).containsAllEntriesOf(expectedSerlializedContent); + + } + + @Test + public void should_load_mappings_and_override_from_custom_properties_file() throws IOException { + + // Given + + final File customMappings = temporaryFolder.newFile("custom.properties"); + Files.write(customMappings.toPath(), OVERRIDE_MAPPING_PROPERTIES.getBytes()); + System.setProperty("fabric8.mapping", customMappings.getAbsolutePath()); + + // When + final Map> mappings = KindFilenameMapperUtil.loadMappings(); + + // Then + final Map> expectedSerlializedContent = new HashMap<>(); + expectedSerlializedContent.put("ConfigMap", Arrays.asList("foo", "bar")); + expectedSerlializedContent.put("CronJob", Arrays.asList("cj", "cronjob")); + assertThat(mappings).containsAllEntriesOf(expectedSerlializedContent); + + } } diff --git a/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtilTest.java b/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtilTest.java index ea252fa588..5ae598ff4e 100644 --- a/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtilTest.java +++ b/core/src/test/java/io/fabric8/maven/core/util/kubernetes/KubernetesResourceUtilTest.java @@ -16,7 +16,11 @@ package io.fabric8.maven.core.util.kubernetes; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.junit.After; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +28,7 @@ public class KubernetesResourceUtilTest { @Test - public void should_load_kid_filename_mapper_in_bimap_fashion() { + public void should_load_kind_filename_mapper_in_bimap_fashion() { // Given @@ -45,4 +49,38 @@ public void should_load_kid_filename_mapper_in_bimap_fashion() { } + @Test + public void should_update_kind_filename_mapper_in_bimap_fashion() { + + // Given + + final Map> updated = new HashMap<>(); + updated.put("Var", Arrays.asList("foo")); + + // When + + KubernetesResourceUtil.updateKindFilenameMapper(updated); + + final Map filenameToKindMapper = KubernetesResourceUtil.FILENAME_TO_KIND_MAPPER; + final Map kindToFilenameMapper = KubernetesResourceUtil.KIND_TO_FILENAME_MAPPER; + + // Then + assertThat(filenameToKindMapper) + .containsEntry("cm", "ConfigMap") + .containsEntry("configmap", "ConfigMap") + .containsEntry("secret", "Secret") + .containsEntry("foo", "Var"); + + assertThat(kindToFilenameMapper) + .containsEntry("ConfigMap", "configmap") + .containsEntry("Secret", "secret") + .containsEntry("Var", "foo"); + + } + + @After + public void cleanCustomAdditions() { + KubernetesResourceUtil.remove("Var", "foo"); + } + } diff --git a/parent/pom.xml b/parent/pom.xml index 3bdc92863b..f2de1c5398 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -499,6 +499,13 @@ test + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + 3.3.0 + test + + diff --git a/plugin/pom.xml b/plugin/pom.xml index 2514eaa4cc..7c239e1614 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -206,6 +206,12 @@ json-path-assert + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + test + + diff --git a/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/ResourceMojo.java b/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/ResourceMojo.java index 1a7d3ba007..575e6aa771 100644 --- a/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/ResourceMojo.java +++ b/plugin/src/main/java/io/fabric8/maven/plugin/mojo/build/ResourceMojo.java @@ -15,12 +15,14 @@ */ package io.fabric8.maven.plugin.mojo.build; +import io.fabric8.maven.core.config.MappingConfig; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -238,6 +240,9 @@ public class ResourceMojo extends AbstractFabric8Mojo { // The image configuration after resolving and customization private List resolvedImages; + // Mapping for kind filenames + private List mappings; + // Services private HandlerHub handlerHub; @@ -392,8 +397,9 @@ private static File writeResource(File resourceFileBase, Object entity, Resource public void executeInternal() throws MojoExecutionException, MojoFailureException { clusterAccess = new ClusterAccess(namespace); - + updateKindFilenameMappings(); try { + lateInit(); // Resolve the Docker image build configuration @@ -420,6 +426,16 @@ public void executeInternal() throws MojoExecutionException, MojoFailureExceptio } } + private void updateKindFilenameMappings() { + if (mappings != null) { + final Map> mappingKindFilename = new HashMap<>(); + for(MappingConfig mappingConfig : this.mappings) { + mappingKindFilename.put(mappingConfig.getKind(), Arrays.asList(mappingConfig.getFilenamesAsArray())); + } + KubernetesResourceUtil.updateKindFilenameMapper(mappingKindFilename); + } + } + private void validateIfRequired(File resourceDir, ResourceClassifier classifier) throws MojoExecutionException, MojoFailureException { try { if (!skipResourceValidation) { @@ -1095,4 +1111,8 @@ protected void writeResources(KubernetesList resources, ResourceClassifier class projectHelper.attachArtifact(project, json.getArtifactType(), classifier.getValue(), file); } } + + protected List getMappings() { + return mappings; + } } diff --git a/plugin/src/test/java/io/fabric8/maven/plugin/mojo/build/MappingConfigTest.java b/plugin/src/test/java/io/fabric8/maven/plugin/mojo/build/MappingConfigTest.java new file mode 100644 index 0000000000..5712ba096c --- /dev/null +++ b/plugin/src/test/java/io/fabric8/maven/plugin/mojo/build/MappingConfigTest.java @@ -0,0 +1,36 @@ +package io.fabric8.maven.plugin.mojo.build; + +import java.io.File; +import org.apache.maven.plugin.testing.MojoRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; + +@Ignore("I have not been able to make it run due classpath problems. " + + "I have tried to fix but I have not find any way to ignore the conflict library from all transitive dependencies." + + "conflict with plexus-io is the root cause coming as dependency from DMP plugin. But excluding it is not an option" + + "since it is used too.") +public class MappingConfigTest { + + @Rule + public MojoRule rule = new MojoRule(); + + private final static String BASIC_TEST_FILE_PATH = "src/test/resources/mojo/build/mapping-mojo-config.xml"; + + @Test + public void testResourceMojoKindFilenameMappingsEmbeddedConfiguration() throws Exception { + + try { + ResourceMojo mojo = getResourceMojo(); + } catch(Exception ex) { + throw ex; + } + + } + + private ResourceMojo getResourceMojo() throws Exception { + File pluginConfig = new File( ".", BASIC_TEST_FILE_PATH ); + return( (ResourceMojo) this.rule.lookupMojo("resource", pluginConfig) ); + } + +} diff --git a/plugin/src/test/resources/mojo/build/mapping-mojo-config.xml b/plugin/src/test/resources/mojo/build/mapping-mojo-config.xml new file mode 100644 index 0000000000..6bfad97129 --- /dev/null +++ b/plugin/src/test/resources/mojo/build/mapping-mojo-config.xml @@ -0,0 +1,18 @@ + + + + + io.fabric8 + fabric8-maven-plugin + + + + Var + foo, bar + + + + + + + \ No newline at end of file