com.netflix.spinnaker.kork.artifacts.parsing.JinjaArtifactExtractor.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.spinnaker.kork.artifacts.parsing.JinjaArtifactExtractor.java

Source

/*
 * Copyright 2019 Google, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netflix.spinnaker.kork.artifacts.parsing;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hubspot.jinjava.Jinjava;
import com.netflix.spinnaker.kork.artifacts.model.Artifact;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Translates String messages into Spinnaker artifacts using a supplied Jinja template
 */
@Slf4j
public class JinjaArtifactExtractor implements ArtifactExtractor {
    private final JinjavaFactory jinjavaFactory;
    private final ObjectMapper objectMapper;
    private final String jinjaTemplate;

    private static final TypeReference<List<Artifact>> artifactListReference = new TypeReference<List<Artifact>>() {
    };
    private static final TypeReference<Map<String, ?>> stringMapReference = new TypeReference<Map<String, ?>>() {
    };

    private JinjaArtifactExtractor(String jinjaTemplate, JinjavaFactory jinjavaFactory, ObjectMapper objectMapper) {
        this.jinjaTemplate = jinjaTemplate;
        this.jinjavaFactory = jinjavaFactory;
        this.objectMapper = objectMapper;
    }

    public List<Artifact> getArtifacts(String messagePayload) {
        if (StringUtils.isEmpty(messagePayload)) {
            return Collections.emptyList();
        }
        return readArtifactList(jinjaTransform(messagePayload));
    }

    private String jinjaTransform(String messagePayload) {
        if (StringUtils.isEmpty(jinjaTemplate)) {
            return messagePayload;
        }
        Jinjava jinja = jinjavaFactory.create();
        Map<String, ?> context = readMapValue(messagePayload);
        return jinja.render(jinjaTemplate, context);
    }

    private Map<String, ?> readMapValue(String messagePayload) {
        try {
            return objectMapper.readValue(messagePayload, stringMapReference);
        } catch (IOException ioe) {
            log.error(messagePayload);
            throw new RuntimeException(ioe);
        }
    }

    private List<Artifact> readArtifactList(String hydratedTemplate) {
        try {
            return objectMapper.readValue(hydratedTemplate, artifactListReference);
        } catch (IOException ioe) {
            // Failure to parse artifacts from the message indicates either
            // the message payload does not match the provided template or
            // there is no template and no artifacts are expected
            log.warn("Unable to parse artifact from {}", hydratedTemplate, ioe);
        }
        return Collections.emptyList();
    }

    @RequiredArgsConstructor
    public static class Factory {
        private final JinjavaFactory jinjavaFactory;
        private final ObjectMapper objectMapper = new ObjectMapper();

        public JinjaArtifactExtractor create(InputStream templateStream) {
            String template = readTemplateStream(templateStream);
            return this.create(template);
        }

        public JinjaArtifactExtractor create(String template) {
            return new JinjaArtifactExtractor(template, jinjavaFactory, objectMapper);
        }

        private String readTemplateStream(InputStream templateStream) {
            if (templateStream == null) {
                return "";
            } else {
                try {
                    return IOUtils.toString(templateStream, Charset.forName("UTF-8"));
                } catch (IOException ioe) {
                    throw new RuntimeException(ioe);
                }
            }
        }
    }
}