dump java object,it will add one of elements about string type \n

Issue #1067 open
s HFwas created an issue
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.gitlab4j.api.models.RepositoryFile;
import org.springframework.util.CollectionUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName TemplateUtil
 **/
public class ConfigTemplateUtil {

    private static final Yaml YAML;

    static {
        //初始化yaml转换器
        DumperOptions options = new DumperOptions();
        options.setIndent(2);
        options.setPrettyFlow(true);
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);

        Representer representer = new Representer() {
            @Override
            protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
                if (propertyValue == null) {
                    return null;
                } else {
                    return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
                }
            }
        };
        representer.addClassTag(Deployment.class, Tag.MAP);
        representer.addClassTag(Service.class, Tag.MAP);
        representer.addClassTag(ConfigMap.class, Tag.MAP);
        representer.addClassTag(Values.class, Tag.MAP);
        representer.addClassTag(Chart.class, Tag.MAP);
        YAML = new Yaml(representer, options);
    }

    public static List<RepositoryFile> getYaml(TemplateDTO templateDTO) {
        RepositoryFile deploy = deployYaml(templateDTO);
        List<RepositoryFile> files = new ArrayList<>(List.of(deploy));
        if (templateDTO.getPorts().stream().anyMatch(i -> null != i.getTarget())){
            files.add(serviceYaml(templateDTO));
        }
        if (!CollectionUtils.isEmpty(templateDTO.getConfig())){
            files.add(configMapYaml(templateDTO));
        }
        return files;
    }

    public static List<RepositoryFile> getHelmYaml(HelmDTO helmDTO) {
        List<RepositoryFile> files = new ArrayList<>();
        TemplateDTO rootTemplateDTO = helmDTO.getTemplateDTOS().get(0);
        rootTemplateDTO.check();
        String rootTemplateDTOPath =  rootTemplateDTO.getPath();
        if (CollUtil.isNotEmpty(helmDTO.getTemplateDTOS())){
            List<String> names = helmDTO.getTemplateDTOS().stream().map(helm -> helm.getName()).collect(Collectors.toList());
            Chart chart = helmDTO.getChart();

            // 根目录下总的chart和values.yaml
            List<ChartDependency> dependencies = new ArrayList<>();
            names.stream().forEach(name-> {
                ChartDependency chartDependency = new ChartDependency();
                chartDependency.setName(name);
                String condition = name.concat(".enabled");
                chartDependency.setCondition(condition);
                dependencies.add(chartDependency);
            });
            chart.setDependencies(dependencies);
            String rootPath = rootTemplateDTOPath.endsWith("/") ? rootTemplateDTOPath : rootTemplateDTOPath.concat("/");
            RepositoryFile rootChartYaml = chartYaml(chart, rootPath);
            files.add(rootChartYaml);
            RepositoryFile rootValuesYaml = valuesYaml(helmDTO.getTemplateDTOS().get(0), rootPath, names);
            files.add(rootValuesYaml);

            for (TemplateDTO templateDTO : helmDTO.getTemplateDTOS()) {
                templateDTO.check();
                String path = templateDTO.getPath();
                // 单服务helm模版
                if (helmDTO.getTemplateDTOS().size() == 1) {
                    templateDTO.setPath(path.concat("templates/"));
                // 多服务helm模版
                } else {
                    templateDTO.setPath(templateDTO.getPath() + "charts/" + templateDTO.getName() + "/templates/");
                    path = rootTemplateDTOPath + "charts/" + templateDTO.getName() + "/";
                    chart.setDependencies(null);
                    RepositoryFile chartYaml = chartYaml(chart, path);
                    RepositoryFile valuesYaml = valuesYaml(templateDTO, path,null);
                    files.add(chartYaml);
                    files.add(valuesYaml);
                }

                templateDTO.setName("{{ .Values.name }}");
                templateDTO.setNamespace("{{ .Values.namespace }}");
                templateDTO.setImage("{{ .Values.image.repository }}/{{ .Values.image.name }}:{{ .Values.image.tag }}");
                templateDTO.setStrategy("{{ .Values.image.imagePullPolicy }}");
                templateDTO.setLimitCpu("{{ .Values.limitCpu }}");
                templateDTO.setLimitMemory("{{ .Values.limitMemory }}");
                templateDTO.setRequestCpu("{{ .Values.requestCpu }}");
                templateDTO.setRequestMemory("{{ .Values.requestMemory }}");
                templateDTO.setStrategy("{{ .Values.strategy }}");
                templateDTO.setServiceType("{{ .Values.serviceType }}");
                List<RepositoryFile> yaml = getYaml(templateDTO);
                files.addAll(yaml);
            }
        }
        return files;
    }

    private static RepositoryFile configMapYaml(TemplateDTO templateDTO) {
        ConfigMap configMap = new ConfigMap(templateDTO);
        String dump = YAML.dump(configMap);
        RepositoryFile file = new RepositoryFile();
        file.setContent(dump);
        file.setFileName("configmap.yaml");
        file.setFilePath(templateDTO.getPath() + file.getFileName());
        return file;
    }

    private static RepositoryFile serviceYaml(TemplateDTO templateDTO) {
        Service service = new Service(templateDTO);
        String dump = YAML.dump(service);
        RepositoryFile file = new RepositoryFile();
        file.setContent(dump);
        file.setFileName("service.yaml");
        file.setFilePath(templateDTO.getPath() + file.getFileName());
        return file;
    }

    private static RepositoryFile deployYaml(TemplateDTO templateDTO) {
        Deployment deployment = new Deployment(templateDTO);
        String dump = YAML.dump(deployment);
        RepositoryFile file = new RepositoryFile();
        file.setContent(dump);
        file.setFileName("deployment.yaml");
        file.setFilePath(templateDTO.getPath() + file.getFileName());
        return file;
    }

    private static RepositoryFile chartYaml(Chart chart,String path) {
        Chart newchart = new Chart(chart);
        String dump = YAML.dump(newchart);
        RepositoryFile file = new RepositoryFile();
        file.setContent(dump);
        file.setFileName("chart.yaml");
        file.setFilePath(path + file.getFileName());
        return file;
    }

    private static RepositoryFile valuesYaml(TemplateDTO templateDTO, String path, List<String> names) {
        Values values = new Values(templateDTO);
        String dump = YAML.dump(values);
        String parentChartDump;
        if (CollUtil.isNotEmpty(names)){
            String jsonString = JSON.toJSONString(values);
            JSONObject jsonObject = JSONObject.parseObject(jsonString, Feature.OrderedField);

            for (String name : names) {
                JSONObject object = new JSONObject(true);
                object.put("enabled",Boolean.TRUE);
                jsonObject.put(name,object);
            }
            String dumpppp = jsonObject.toJSONString();
            String yamlDump = jsonConverToYaml(dumpppp);
            parentChartDump = yamlDump;
        }else{
            parentChartDump = dump;
        }

        RepositoryFile file = new RepositoryFile();
        file.setContent(parentChartDump);
        file.setFileName("values.yaml");
        file.setFilePath(path + file.getFileName());
        return file;
    }

    public static String jsonConverToYaml(String jsonString) {
        String replaceAll = StrUtil.EMPTY;
        try {
            JsonNode jsonNode = new ObjectMapper().readTree(jsonString);
            String string = new YAMLMapper().writeValueAsString(jsonNode);
            //因为writeValueAsString生成的yaml字符串会带有 ---\n 所以进行替换操作
            replaceAll = string.replaceAll("---\n", "");
        }catch (Exception e){
            e.printStackTrace();
        }
        return replaceAll;
    }


    public static void main(String[] args) {
        HelmDTO helmDTO = new HelmDTO();

        Chart chart = new Chart();
        chart.setName("eww");
        chart.setDescription("ddaaaa");
        chart.setVersion("1.2.3");
        List<TemplateDTO> templateDTOS = new ArrayList<>();
        TemplateDTO templateDTO = new TemplateDTO();
        templateDTO.setBranch("main");
        templateDTO.setGitlabId(649);
        templateDTO.setImage("10.10.102.213:8443/devshop/devops-app:2.1.2");
        templateDTO.setLimitCpu("1");
        templateDTO.setLimitMemory("2Mi");
        templateDTO.setName("eww");
        templateDTO.setNamespace("devops");
        templateDTO.setPath("aaa");
        templateDTO.setReplicas(1);
        templateDTO.setRequestCpu("0.5");
        templateDTO.setRequestMemory("1Mi");
        templateDTO.setServiceType("ClusterIP");
        templateDTO.setStrategy("Always");

        PortDTO portDTO = new PortDTO();
        portDTO.setType("TCP");
        portDTO.setPort(8080);
        portDTO.setTarget(8080);
        templateDTO.setPorts(Arrays.asList());
        templateDTOS.add(templateDTO);

        helmDTO.setChart(chart);
        helmDTO.setTemplateDTOS(templateDTOS);
        List<RepositoryFile> helmYaml = getHelmYaml(helmDTO);
        System.out.println(helmYaml);
    }

}

deployYaml method

Deployment deployment = new Deployment(templateDTO);
        String dump = YAML.dump(deployment);

deployment object

dump,

how to solve \n problem?

Comments (8)

  1. s HFwas reporter

    after yaml.dump, value of spec.containers.image will add \n, it will be expect

    {{ .Values.image.repository }}/{{ .Values.image.name }}:{{ .Values.image.tag }}

    not

    {{ .Values.image.repository }}/{{ .Values.image.name }}:{{ .Values.image.tag

    }}

  2. Andrey Somov

    Indeed in the flow context it should not add new line. The folded style (which adds lines) is only in the block context.
    As a work around you can try to increase the line limit to a big number:
    DumperOptions.setWidth(2000);

  3. Andrey Somov

    It will take some time to fix it. I would like to kindly ask you to test the fix once it is provided.

  4. Log in to comment