Skip to content

Commit

Permalink
feat(fabric8io#1382): Allow to provide additional fragment filename m…
Browse files Browse the repository at this point in the history
…appings (fabric8io#1387)
  • Loading branch information
lordofthejars committed Jan 16, 2019
1 parent cc61d85 commit b93309b
Show file tree
Hide file tree
Showing 22 changed files with 523 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ After this we will switch probably to real [Semantic Versioning 2.0.0](http://se
* Fix 1021: Avoids empty deployment selector value in generated yaml resource
* Fix 1383: Check if instanceof Openshift before casting and handle failures.
* Fix 1390: Provides better exception message in case of invalid `application.yml` in Spring Boot
* Fix 1382: Allow to provide additional fragment filename mappings

###3.5.41 (2018-08-01)
* Feature 1032: Improvements of the Vert.x Generator and enrichers
Expand Down
28 changes: 28 additions & 0 deletions core/src/main/java/io/fabric8/maven/core/config/MappingConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.fabric8.maven.core.config;

public class MappingConfig {

private String kind;

private String filenameTypes;

public String getKind() {
return kind;
}

public String getFilenameTypes() {
return filenameTypes;
}

public String[] getFilenamesAsArray() {
if (this.filenameTypes == null) {
return new String[0];
}
return filenameTypes.split(",\\s*");
}

public boolean isValid() {
return kind != null && filenameTypes != null && filenameTypes.length() > 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public class ResourceConfig {

@Parameter
private MetaDataConfig annotations = new MetaDataConfig();
;

@Parameter
private List<VolumeConfig> volumes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, List<String>> serializeKindFilenameTable(final InputStream table) {

Expand Down
Original file line number Diff line number Diff line change
@@ -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.
*
* <pre>
* ConfigMap=cm, configmap
* Service=service
* </pre>
*
* @param mapping
* stream of a properties file setting mappings between kinds and filenames.
*
* @return Serialization of all elements as a map
*/
public Map<String, List<String>> parse(final InputStream mapping) {

final Properties mappingProperties = new Properties();
try {
mappingProperties.load(mapping);

final Map<String, List<String>> serializedContent = new HashMap<>();

final Set<String> kinds = mappingProperties.stringPropertyNames();

for (String kind : kinds) {
final String filenames = mappingProperties.getProperty(kind);
final String[] filenameTypes = filenames.split(",");
final List<String> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,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;
Expand All @@ -26,10 +31,20 @@ public class KindFilenameMapperUtil {
public static Map<String, List<String>> 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<String, List<String>> 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);
}
Expand All @@ -39,7 +54,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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,15 @@ public boolean accept(File dir, String name) {

protected final static void initializeKindFilenameMapper() {
final Map<String, List<String>> 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<String, List<String>> mappings) {

final Set<Map.Entry<String, List<String>>> entries = mappings.entrySet();

Expand All @@ -205,6 +214,7 @@ protected final static void initializeKindFilenameMapper() {
KIND_TO_FILENAME_MAPPER.put(kind, filenameTypes.get(filenameTypes.size() - 1));

}

}

private static final String FILENAME_PATTERN = "^(?<name>.*?)(-(?<type>[^-]+))?\\.(?<ext>yaml|yml|json)$";
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, List<String>> serializedContent =
propertiesMappingParser.parse(new ByteArrayInputStream(MAPPING_PROPERTIES.getBytes()));

// Then

final Map<String, List<String>> expectedSerlializedContent = new HashMap<>();
expectedSerlializedContent.put("ConfigMap", Arrays.asList("cm", "configmap"));

assertThat(serializedContent)
.containsAllEntriesOf(expectedSerlializedContent);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,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() {

Expand All @@ -42,6 +57,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<String, List<String>> mappings = KindFilenameMapperUtil.loadMappings();

// Then
final Map<String, List<String>> 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<String, List<String>> mappings = KindFilenameMapperUtil.loadMappings();

// Then
final Map<String, List<String>> expectedSerlializedContent = new HashMap<>();
expectedSerlializedContent.put("ConfigMap", Arrays.asList("foo", "bar"));
expectedSerlializedContent.put("CronJob", Arrays.asList("cj", "cronjob"));
assertThat(mappings).containsAllEntriesOf(expectedSerlializedContent);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@
*/
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;

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

Expand All @@ -44,4 +48,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<String, List<String>> updated = new HashMap<>();
updated.put("Var", Arrays.asList("foo"));

// When

KubernetesResourceUtil.updateKindFilenameMapper(updated);

final Map<String, String> filenameToKindMapper = KubernetesResourceUtil.FILENAME_TO_KIND_MAPPER;
final Map<String, String> 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");
}

}
28 changes: 27 additions & 1 deletion doc/src/main/asciidoc/inc/_appendix.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,30 @@
== Kind/Filename Type Mapping

[[appendix-kind-mapping]]
include::classpath:/META-INF/fabric8/kind-filename-type-mapping-default.adoc[]
include::classpath:/META-INF/fabric8/kind-filename-type-mapping-default.adoc[]

== Custom Kind/Filename Mapping

You can add your custom `Kind/Filename` mappings.
To do it you have two approaches:

* Setting an environment variable or system property called `fabric8.mapping` pointing out to a `.properties` files with pairs `<kind>=>filename1>, <filename2>`
By default if no environment variable nor system property is set, scan for a file located at classpath `/META-INF/fabric8/kind-filename-type-mapping-default.properties`.

* By embedding in MOJO configuration the mapping:

[source, xml]
----
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>fabric8-maven-plugin</artifactId>
<configuration>
<mappings>
<mapping>
<kind>Var</kind>
<filenameTypes>foo, bar</filenameTypes>
</mapping>
</mappings>
</configuration>
</plugin>
----
Loading

0 comments on commit b93309b

Please sign in to comment.