Skip to content

Commit

Permalink
refactor (jkube-kit) : Move ConfigMap related helper methods in Kuber…
Browse files Browse the repository at this point in the history
…netesResourceUtil

Related to fabric8io/kubernetes-client#4184

Move creation of ConfigMap from file related logic to
KubernetesResourceUtil. This would later be replaced by
KubernetesClient's KubernetesResourceUtil methods on next upgrade.

Signed-off-by: Rohan Kumar <rohaan@redhat.com>
  • Loading branch information
rohanKanojia authored and manusa committed Jan 4, 2023
1 parent 09b656e commit 751a8aa
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,17 @@
import java.lang.reflect.Method;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -31,6 +40,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.stream.Stream;

import io.fabric8.kubernetes.client.utils.Serialization;
import org.eclipse.jkube.kit.common.KitLogger;
Expand Down Expand Up @@ -619,6 +629,95 @@ public static HasMetadata mergeResources(HasMetadata item1, HasMetadata item2, K
return item1;
}

/**
* Create a ConfigMap entry based on file contents
*
* @param key key for entry
* @param file file path whose contents would be used in value of entry
* @return an entry containing key and value
* @deprecated Should be replaced with Fabric8 Kubernetes Client's methods
* @throws IOException in case of error while reading file
*/
@Deprecated
public static Map.Entry<String, String> createConfigMapEntry(final String key, final Path file) throws IOException {
final byte[] bytes = Files.readAllBytes(file);
if (isFileWithBinaryContent(file)) {
final String value = Base64.getEncoder().encodeToString(bytes);
return new AbstractMap.SimpleEntry<>(key, value);
} else {
return new AbstractMap.SimpleEntry<>(key, new String(bytes));
}
}

/**
* Whether a file is binary file or not
*
* @param file file to check
* @return boolean value indicating whether file is binary file or not
* @deprecated Should be replaced with Fabric8 Kubernetes Client's methods
* @throws IOException in case of failure while reading file
*/
@Deprecated
public static boolean isFileWithBinaryContent(final Path file) throws IOException {
final byte[] bytes = Files.readAllBytes(file);
try {
StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT)
.decode(ByteBuffer.wrap(bytes));
return false;
} catch (CharacterCodingException e) {
return true;
}
}

/**
* Add ConfigMap entries from a directory to current ConfigMap
* @param configMapBuilder ConfigMap builder object
* @param path path to directory
* @deprecated Should be replaced with Fabric8 Kubernetes Client's methods
* @throws IOException in case of failure while reading directory
*/
@Deprecated
public static void addNewEntriesFromDirectoryToExistingConfigMap(ConfigMapBuilder configMapBuilder, final Path path)
throws IOException {
try (Stream<Path> files = Files.list(path)) {
files.filter(p -> !Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)).forEach(file -> {
try {
addNewEntryToExistingConfigMap(configMapBuilder, createConfigMapEntry(file.getFileName().toString(), file), file);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
});
}
}

/**
* Add single entry to ConfigMap
*
* @param configMapBuilder ConfigMap builder object
* @param entry key value pair which will be added to data/binaryData
* @param file file which needs to be processed
* @deprecated Should be replaced with Fabric8 Kubernetes Client's methods
* @throws IOException in case of failure while reading file
*/
@Deprecated
public static void addNewEntryToExistingConfigMap(ConfigMapBuilder configMapBuilder, Map.Entry<String, String> entry, final Path file)
throws IOException {
if (isFileWithBinaryContent(file)) {
configMapBuilder.addToBinaryData(entry.getKey(), entry.getValue());
} else {
configMapBuilder.addToData(entry.getKey(), entry.getValue());
}
}

public static void addNewConfigMapEntriesToExistingConfigMap(ConfigMapBuilder configMapBuilder, String key, Path filePath) throws IOException {
if (Files.isDirectory(filePath, LinkOption.NOFOLLOW_LINKS)) {
addNewEntriesFromDirectoryToExistingConfigMap(configMapBuilder, filePath);
} else {
addNewEntryToExistingConfigMap(configMapBuilder, createConfigMapEntry(key, filePath), filePath);
}
}

protected static HasMetadata mergeConfigMaps(ConfigMap cm1, ConfigMap cm2, KitLogger log, boolean switchOnLocalCustomisation) {
ConfigMap cm1OrCopy = cm1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
*/
package org.eclipse.jkube.kit.enricher.api.util;

import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
Expand All @@ -24,6 +26,7 @@
import io.fabric8.kubernetes.api.model.batch.v1.Job;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicy;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.config.resource.GroupArtifactVersion;
import org.junit.jupiter.api.BeforeAll;
Expand All @@ -39,6 +42,8 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand All @@ -53,6 +58,8 @@
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.DEFAULT_RESOURCE_VERSIONING;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.FILENAME_TO_KIND_MAPPER;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.KIND_TO_FILENAME_MAPPER;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.addNewConfigMapEntriesToExistingConfigMap;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.createConfigMapEntry;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.getNameWithSuffix;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.initializeKindFilenameMapper;
import static org.junit.jupiter.params.provider.Arguments.arguments;
Expand Down Expand Up @@ -395,6 +402,91 @@ void updateKindFilenameMappings_whenAddsCronTabMapping_updatesKindToFileNameMapp
assertThat(FILENAME_TO_KIND_MAPPER).containsKey("foo");
}

@Test
void createConfigMapEntry_whenKeyAndPathProvided_thenShouldCreateEntryWithFileContents() throws IOException {
// Given
URL fileUrl = getClass().getResource("/kubernetes-resource-util/configmap-directory/test.properties");
assertThat(fileUrl).isNotNull();

// When
Map.Entry<String, String> entry = createConfigMapEntry("custom-key", Paths.get(fileUrl.getFile()));

// Then
assertThat(entry)
.satisfies(e -> assertThat(e.getKey()).isEqualTo("custom-key"))
.satisfies(e -> assertThat(e.getValue()).isEqualTo("db.url=jdbc:mysql://localhost:3306/sample_db"));
}

@Test
void createConfigMapEntry_whenBinaryFileProvided_thenShouldCreateEntryWithFileContents() throws IOException {
// Given
URL fileUrl = getClass().getResource("/kubernetes-resource-util/test.bin");
assertThat(fileUrl).isNotNull();

// When
Map.Entry<String, String> entry = createConfigMapEntry("custom-key", Paths.get(fileUrl.getFile()));

// Then
assertThat(entry)
.satisfies(e -> assertThat(e.getKey()).isEqualTo("custom-key"))
.satisfies(e -> assertThat(e.getValue()).isEqualTo("wA=="));
}

@Test
void addNewConfigMapEntriesToExistingConfigMap_whenFileProvided_thenShouldCreateConfigMapWithFile() throws IOException {
// Given
URL fileUrl = getClass().getResource("/kubernetes-resource-util/configmap-directory/test.properties");
assertThat(fileUrl).isNotNull();
ConfigMapBuilder configMapBuilder = new ConfigMapBuilder();

// When
addNewConfigMapEntriesToExistingConfigMap(configMapBuilder, "custom-key", Paths.get(fileUrl.getFile()));

// Then
assertThat(configMapBuilder.build())
.asInstanceOf(InstanceOfAssertFactories.type(ConfigMap.class))
.extracting(ConfigMap::getData)
.asInstanceOf(InstanceOfAssertFactories.MAP)
.containsEntry("custom-key", "db.url=jdbc:mysql://localhost:3306/sample_db");
}

@Test
void addNewConfigMapEntriesToExistingConfigMap_whenBinaryFileProvided_thenShouldCreateConfigMapWithBinaryContent() throws IOException {
// Given
URL fileUrl = getClass().getResource("/kubernetes-resource-util/test.bin");
assertThat(fileUrl).isNotNull();
ConfigMapBuilder configMapBuilder = new ConfigMapBuilder();

// When
addNewConfigMapEntriesToExistingConfigMap(configMapBuilder, "custom-key", Paths.get(fileUrl.getFile()));

// Then
assertThat(configMapBuilder.build())
.asInstanceOf(InstanceOfAssertFactories.type(ConfigMap.class))
.extracting(ConfigMap::getBinaryData)
.asInstanceOf(InstanceOfAssertFactories.MAP)
.containsEntry("custom-key", "wA==");
}

@Test
void addNewConfigMapEntriesToExistingConfigMap_whenDirectoryProvided_thenShouldCreateConfigMapWithFilesInDir() throws IOException {
// Given
URL fileUrl = getClass().getResource("/kubernetes-resource-util/configmap-directory");
assertThat(fileUrl).isNotNull();
ConfigMapBuilder configMapBuilder = new ConfigMapBuilder();

// When
addNewConfigMapEntriesToExistingConfigMap(configMapBuilder, "custom-key", Paths.get(fileUrl.getFile()));

// Then
assertThat(configMapBuilder.build())
.asInstanceOf(InstanceOfAssertFactories.type(ConfigMap.class))
.extracting(ConfigMap::getData)
.asInstanceOf(InstanceOfAssertFactories.MAP)
.containsEntry("test.properties", "db.url=jdbc:mysql://localhost:3306/sample_db")
.containsEntry("prod.properties", "db.url=jdbc:mysql://prod.example.com:3306/sample_db");
}

private static PodSpec defaultPodSpec() {
return new PodSpecBuilder()
.addNewContainer()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
db.url=jdbc:mysql://prod.example.com:3306/sample_db
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
db.url=jdbc:mysql://localhost:3306/sample_db
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,16 @@
*/
package org.eclipse.jkube.enricher.generic;

import static java.util.Collections.singletonMap;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.addNewConfigMapEntriesToExistingConfigMap;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.addNewEntryToExistingConfigMap;
import static org.eclipse.jkube.kit.enricher.api.util.KubernetesResourceUtil.createConfigMapEntry;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import org.eclipse.jkube.kit.config.resource.ConfigMapEntry;
import org.eclipse.jkube.kit.config.resource.PlatformMode;
Expand Down Expand Up @@ -85,46 +79,14 @@ private void addConfigMapFromAnnotations(final Map<String, String> annotations,
final String key = entry.getKey();

if (key.startsWith(PREFIX_ANNOTATION) || key.startsWith(CONFIGMAP_PREFIX_ANNOTATION)) {
addConfigMapEntryFromDirOrFile(configMapBuilder, getOutput(key), entry.getValue());
Path filePath = Paths.get(entry.getValue());
addNewConfigMapEntriesToExistingConfigMap(configMapBuilder, getOutput(key), filePath);
it.remove();
}
}
}

private void addConfigMapEntryFromDirOrFile(final ConfigMapBuilder configMapBuilder, final String key,
final String dirOrFilePath) throws IOException {
final Path path = Paths.get(dirOrFilePath);

if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)) {
try (Stream<Path> files = Files.list(path)) {
files.filter(p -> !Files.isDirectory(p, LinkOption.NOFOLLOW_LINKS)).forEach(file -> {
try {
addConfigMapEntryFromFile(configMapBuilder, file.getFileName().toString(), file);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
});
}
} else {
addConfigMapEntryFromFile(configMapBuilder, key, path);
}
}

private void addConfigMapEntryFromFile(final ConfigMapBuilder configMapBuilder, final String key, final Path file)
throws IOException {
final byte[] bytes = Files.readAllBytes(file);
try {
StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT)
.decode(ByteBuffer.wrap(bytes));
final String value = new String(bytes);
configMapBuilder.addToData(singletonMap(key, value));
} catch (CharacterCodingException e) {
final String value = Base64.getEncoder().encodeToString(bytes);
configMapBuilder.addToBinaryData(singletonMap(key, value));
}
}

private String getOutput(String key) {
if (key.startsWith(PREFIX_ANNOTATION)) {
Expand Down Expand Up @@ -168,10 +130,12 @@ private io.fabric8.kubernetes.api.model.ConfigMap createConfigMapFromConfigurati
} else {
final String file = configMapEntry.getFile();
if (file != null) {
final Path filePath = Paths.get(file);
if (name == null) {
name = Paths.get(file).getFileName().toString();
name = filePath.getFileName().toString();
}
addConfigMapEntryFromDirOrFile(configMapBuilder, name, file);
Map.Entry<String, String> fileEntry = createConfigMapEntry(name, filePath);
addNewEntryToExistingConfigMap(configMapBuilder, fileEntry, filePath);
}
}
}
Expand Down

0 comments on commit 751a8aa

Please sign in to comment.