All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodic.kubernetes.confcenter.ConfigMapPropertySource Maven / Gradle / Ivy

package org.zodic.kubernetes.confcenter;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.client.KubernetesClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;
import org.zodic.kubernetes.base.constants.KubernetesConstants;

public class ConfigMapPropertySource extends MapPropertySource {

    private static final Logger LOG = LoggerFactory.getLogger(ConfigMapPropertySource.class);

    private static final String APPLICATION_YML = "application.yml";

    private static final String APPLICATION_YAML = "application.yaml";

    private static final String APPLICATION_PROPERTIES = "application.properties";

    private static final String PREFIX = "configmap";

    public ConfigMapPropertySource(KubernetesClient client, String name) {
        this(client, name, null, (Environment)null);
    }

    public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, String[] profiles) {
        this(client, name, namespace, createEnvironmentWithActiveProfiles(profiles));
    }

    private static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) {
        StandardEnvironment environment = new StandardEnvironment();
        environment.setActiveProfiles(activeProfiles);
        return environment;
    }

    public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, Environment environment) {
        super(getName(client, name, namespace), asObjectMap(getData(client, name, namespace, environment)));
    }

    private static String getName(KubernetesClient client, String name, String namespace) {
        return new StringBuilder().append(PREFIX).append(KubernetesConstants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
            .append(KubernetesConstants.PROPERTY_SOURCE_NAME_SEPARATOR)
            .append(namespace == null || namespace.isEmpty() ? client.getNamespace() : namespace).toString();
    }

    private static Map getData(KubernetesClient client, String name, String namespace,
        Environment environment) {
        try {
            Map result = new HashMap<>();
            ConfigMap map = StrUtil.isEmpty(namespace) ? client.configMaps().withName(name).get()
                : client.configMaps().inNamespace(namespace).withName(name).get();

            if (map != null) {
                result.putAll(processAllEntries(map.getData(), environment));
            }

            if (environment != null) {
                for (String activeProfile : environment.getActiveProfiles()) {

                    String mapNameWithProfile = name + "-" + activeProfile;

                    ConfigMap mapWithProfile =
                        StrUtil.isEmpty(namespace) ? client.configMaps().withName(mapNameWithProfile).get()
                            : client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get();

                    if (mapWithProfile != null) {
                        result.putAll(processAllEntries(mapWithProfile.getData(), environment));
                    }

                }
            }

            return result;

        } catch (Exception e) {
            LOG.warn("Can't read configMap with name: [{}] in namespace:[{}]. Ignoring",
                name, namespace);
        }

        return new HashMap<>();
    }

    private static Map processAllEntries(Map input, Environment environment) {

        Set> entrySet = input.entrySet();
        if (entrySet.size() == 1) {
            /*
             * We handle the case where the configmap contains a single "file"
             * in this case we don't care what the name of t he file is
             * */
            Entry singleEntry = entrySet.iterator().next();
            String propertyName = singleEntry.getKey();
            String propertyValue = singleEntry.getValue();
            if (propertyName.endsWith(".yml") || propertyName.endsWith(".yaml")) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("The single property with name: [{}] will be treated as a yaml file.",
                        propertyName);
                }

                return PropertySourceUtil.yamlParserGenerator(environment).andThen(PropertySourceUtil.PROPERTIES_TO_MAP).apply(propertyValue);
            } else if (propertyName.endsWith(".properties")) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(
                        "The single property with name: [{}] will be treated as a configReloadInfo file",
                        propertyName);
                }

                return PropertySourceUtil.KEY_VALUE_TO_PROPERTIES.andThen(PropertySourceUtil.PROPERTIES_TO_MAP).apply(propertyValue);
            } else {
                return defaultProcessAllEntries(input, environment);
            }
        }

        return defaultProcessAllEntries(input, environment);
    }

    private static Map defaultProcessAllEntries(Map input, Environment environment) {

        return input.entrySet().stream().map(e -> extractProperties(e.getKey(), e.getValue(), environment))
            .filter(m -> !m.isEmpty()).flatMap(m -> m.entrySet().stream())
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
    }

    private static Map extractProperties(String resourceName, String content, Environment environment) {

        if (resourceName.equals(APPLICATION_YAML) || resourceName.equals(APPLICATION_YML)) {
            return PropertySourceUtil.yamlParserGenerator(environment).andThen(PropertySourceUtil.PROPERTIES_TO_MAP).apply(content);
        } else if (resourceName.equals(APPLICATION_PROPERTIES)) {
            return PropertySourceUtil.KEY_VALUE_TO_PROPERTIES.andThen(PropertySourceUtil.PROPERTIES_TO_MAP).apply(content);
        }

        return new HashMap() {
            private static final long serialVersionUID = 7939706201871437599L;

            {
                put(resourceName, content);
            }
        };
    }

    private static Map asObjectMap(Map source) {
        return source.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy