gobblin.service.modules.core.IdentityFlowToJobSpecCompilerTest.java Source code

Java tutorial

Introduction

Here is the source code for gobblin.service.modules.core.IdentityFlowToJobSpecCompilerTest.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 gobblin.service.modules.core;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.typesafe.config.Config;

import gobblin.configuration.ConfigurationKeys;
import gobblin.runtime.api.FlowSpec;
import gobblin.runtime.api.JobSpec;
import gobblin.runtime.api.Spec;
import gobblin.runtime.api.SpecExecutorInstanceProducer;
import gobblin.runtime.api.TopologySpec;
import gobblin.runtime.spec_executorInstance.InMemorySpecExecutorInstanceProducer;
import gobblin.service.ServiceConfigKeys;
import gobblin.service.modules.flow.IdentityFlowToJobSpecCompiler;
import gobblin.util.ConfigUtils;
import gobblin.util.PathUtils;

public class IdentityFlowToJobSpecCompilerTest {
    private static final Logger logger = LoggerFactory.getLogger(IdentityFlowToJobSpecCompilerTest.class);

    private static final String TEST_TEMPLATE_CATALOG_PATH = "/tmp/gobblinTestTemplateCatalog_"
            + System.currentTimeMillis();
    private static final String TEST_TEMPLATE_CATALOG_URI = "file://" + TEST_TEMPLATE_CATALOG_PATH;

    private static final String TEST_TEMPLATE_NAME = "test.template";
    private static final String TEST_TEMPLATE_URI = "FS:///test.template";

    private static final String TEST_SOURCE_NAME = "testSource";
    private static final String TEST_SINK_NAME = "testSink";
    private static final String TEST_FLOW_GROUP = "testFlowGroup";
    private static final String TEST_FLOW_NAME = "testFlowName";

    private static final String SPEC_STORE_PARENT_DIR = "/tmp/orchestrator/";
    private static final String SPEC_DESCRIPTION = "Test Orchestrator";
    private static final String SPEC_VERSION = "1";
    private static final String TOPOLOGY_SPEC_STORE_DIR = "/tmp/orchestrator/topologyTestSpecStore_"
            + System.currentTimeMillis();
    private static final String FLOW_SPEC_STORE_DIR = "/tmp/orchestrator/flowTestSpecStore_"
            + System.currentTimeMillis();

    private IdentityFlowToJobSpecCompiler compilerWithTemplateCalague;
    private IdentityFlowToJobSpecCompiler compilerWithoutTemplateCalague;

    @BeforeClass
    public void setup() throws Exception {
        // Create dir for template catalog
        setupDir(TEST_TEMPLATE_CATALOG_PATH);

        // Create template to use in test
        List<String> templateEntries = new ArrayList<>();
        templateEntries.add("testProperty1 = \"testValue1\"");
        templateEntries.add("testProperty2 = \"test.Value1\"");
        templateEntries.add("testProperty3 = 100");
        FileUtils.writeLines(new File(TEST_TEMPLATE_CATALOG_PATH + "/" + TEST_TEMPLATE_NAME), templateEntries);

        // Initialize compiler with template catalog
        Properties compilerWithTemplateCatalogProperties = new Properties();
        compilerWithTemplateCatalogProperties.setProperty(
                ServiceConfigKeys.TEMPLATE_CATALOGS_FULLY_QUALIFIED_PATH_KEY, TEST_TEMPLATE_CATALOG_URI);
        this.compilerWithTemplateCalague = new IdentityFlowToJobSpecCompiler(
                ConfigUtils.propertiesToConfig(compilerWithTemplateCatalogProperties));

        // Add a topology to compiler
        this.compilerWithTemplateCalague.onAddSpec(initTopologySpec());

        // Initialize compiler without template catalog
        this.compilerWithoutTemplateCalague = new IdentityFlowToJobSpecCompiler(
                ConfigUtils.propertiesToConfig(new Properties()));

        // Add a topology to compiler
        this.compilerWithoutTemplateCalague.onAddSpec(initTopologySpec());
    }

    private void setupDir(String dir) throws Exception {
        FileUtils.forceMkdir(new File(dir));
    }

    private void cleanUpDir(String dir) throws Exception {
        File specStoreDir = new File(dir);
        if (specStoreDir.exists()) {
            FileUtils.deleteDirectory(specStoreDir);
        }
    }

    private TopologySpec initTopologySpec() {
        Properties properties = new Properties();
        properties.put("specStore.fs.dir", TOPOLOGY_SPEC_STORE_DIR);
        properties.put("specExecInstance.capabilities", TEST_SOURCE_NAME + ":" + TEST_SINK_NAME);
        Config config = ConfigUtils.propertiesToConfig(properties);
        SpecExecutorInstanceProducer specExecutorInstanceProducer = new InMemorySpecExecutorInstanceProducer(
                config);

        TopologySpec.Builder topologySpecBuilder = TopologySpec
                .builder(computeTopologySpecURI(SPEC_STORE_PARENT_DIR, TOPOLOGY_SPEC_STORE_DIR)).withConfig(config)
                .withDescription(SPEC_DESCRIPTION).withVersion(SPEC_VERSION)
                .withSpecExecutorInstanceProducer(specExecutorInstanceProducer);
        return topologySpecBuilder.build();
    }

    private FlowSpec initFlowSpec() {
        return initFlowSpec(TEST_FLOW_GROUP, TEST_FLOW_NAME, TEST_SOURCE_NAME, TEST_SINK_NAME);
    }

    private FlowSpec initFlowSpec(String flowGroup, String flowName, String source, String destination) {
        Properties properties = new Properties();
        properties.put(ConfigurationKeys.JOB_SCHEDULE_KEY, "* * * * *");
        properties.put(ConfigurationKeys.FLOW_GROUP_KEY, flowGroup);
        properties.put(ConfigurationKeys.FLOW_NAME_KEY, flowName);
        properties.put(ServiceConfigKeys.FLOW_SOURCE_IDENTIFIER_KEY, source);
        properties.put(ServiceConfigKeys.FLOW_DESTINATION_IDENTIFIER_KEY, destination);
        Config config = ConfigUtils.propertiesToConfig(properties);

        FlowSpec.Builder flowSpecBuilder = null;
        try {
            flowSpecBuilder = FlowSpec.builder(computeTopologySpecURI(SPEC_STORE_PARENT_DIR, FLOW_SPEC_STORE_DIR))
                    .withConfig(config).withDescription("dummy description").withVersion("1")
                    .withTemplate(new URI(TEST_TEMPLATE_URI));
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        return flowSpecBuilder.build();
    }

    public URI computeTopologySpecURI(String parent, String current) {
        // Make sure this is relative
        return PathUtils.relativizePath(new Path(current), new Path(parent)).toUri();
    }

    @AfterClass
    public void cleanUp() throws Exception {
        // Cleanup Template Catalog
        try {
            cleanUpDir(TEST_TEMPLATE_CATALOG_PATH);
        } catch (Exception e) {
            logger.warn("Could not completely cleanup Template catalog dir");
        }

        // Cleanup ToplogySpec Dir
        try {
            cleanUpDir(TOPOLOGY_SPEC_STORE_DIR);
        } catch (Exception e) {
            logger.warn("Could not completely cleanup ToplogySpec catalog dir");
        }

        // Cleanup FlowSpec Dir
        try {
            cleanUpDir(FLOW_SPEC_STORE_DIR);
        } catch (Exception e) {
            logger.warn("Could not completely cleanup FlowSpec catalog dir");
        }
    }

    @Test
    public void testCompilerWithTemplateCatalog() {
        FlowSpec flowSpec = initFlowSpec();

        // Run compiler on flowSpec
        Map<Spec, SpecExecutorInstanceProducer> specExecutorMapping = this.compilerWithTemplateCalague
                .compileFlow(flowSpec);

        // Assert pre-requisites
        Assert.assertNotNull(specExecutorMapping, "Expected non null mapping.");
        Assert.assertTrue(specExecutorMapping.size() == 1, "Exepected 1 executor for FlowSpec.");

        // Assert FlowSpec compilation
        Spec spec = specExecutorMapping.keySet().iterator().next();
        Assert.assertTrue(spec instanceof JobSpec, "Expected JobSpec compiled from FlowSpec.");

        // Assert JobSpec properties
        JobSpec jobSpec = (JobSpec) spec;
        Assert.assertEquals(jobSpec.getConfig().getString("testProperty1"), "testValue1");
        Assert.assertEquals(jobSpec.getConfig().getString("testProperty2"), "test.Value1");
        Assert.assertEquals(jobSpec.getConfig().getString("testProperty3"), "100");
        Assert.assertEquals(jobSpec.getConfig().getString(ServiceConfigKeys.FLOW_SOURCE_IDENTIFIER_KEY),
                TEST_SOURCE_NAME);
        Assert.assertFalse(jobSpec.getConfig().hasPath(ConfigurationKeys.JOB_SCHEDULE_KEY));
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.JOB_NAME_KEY), TEST_FLOW_NAME);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.JOB_GROUP_KEY), TEST_FLOW_GROUP);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.FLOW_NAME_KEY), TEST_FLOW_NAME);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.FLOW_GROUP_KEY), TEST_FLOW_GROUP);
        Assert.assertTrue(jobSpec.getConfig().hasPath(ConfigurationKeys.FLOW_EXECUTION_ID_KEY));
    }

    @Test
    public void testCompilerWithoutTemplateCatalog() {
        FlowSpec flowSpec = initFlowSpec();

        // Run compiler on flowSpec
        Map<Spec, SpecExecutorInstanceProducer> specExecutorMapping = this.compilerWithoutTemplateCalague
                .compileFlow(flowSpec);

        // Assert pre-requisites
        Assert.assertNotNull(specExecutorMapping, "Expected non null mapping.");
        Assert.assertTrue(specExecutorMapping.size() == 1, "Exepected 1 executor for FlowSpec.");

        // Assert FlowSpec compilation
        Spec spec = specExecutorMapping.keySet().iterator().next();
        Assert.assertTrue(spec instanceof JobSpec, "Expected JobSpec compiled from FlowSpec.");

        // Assert JobSpec properties
        JobSpec jobSpec = (JobSpec) spec;
        Assert.assertTrue(!jobSpec.getConfig().hasPath("testProperty1"));
        Assert.assertTrue(!jobSpec.getConfig().hasPath("testProperty2"));
        Assert.assertTrue(!jobSpec.getConfig().hasPath("testProperty3"));
        Assert.assertEquals(jobSpec.getConfig().getString(ServiceConfigKeys.FLOW_SOURCE_IDENTIFIER_KEY),
                TEST_SOURCE_NAME);
        Assert.assertFalse(jobSpec.getConfig().hasPath(ConfigurationKeys.JOB_SCHEDULE_KEY));
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.JOB_NAME_KEY), TEST_FLOW_NAME);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.JOB_GROUP_KEY), TEST_FLOW_GROUP);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.FLOW_NAME_KEY), TEST_FLOW_NAME);
        Assert.assertEquals(jobSpec.getConfig().getString(ConfigurationKeys.FLOW_GROUP_KEY), TEST_FLOW_GROUP);
        Assert.assertTrue(jobSpec.getConfig().hasPath(ConfigurationKeys.FLOW_EXECUTION_ID_KEY));
    }

    @Test
    public void testNoJobSpecCompilation() {
        FlowSpec flowSpec = initFlowSpec(TEST_FLOW_GROUP, TEST_FLOW_NAME, "unsupportedSource", "unsupportedSink");

        // Run compiler on flowSpec
        Map<Spec, SpecExecutorInstanceProducer> specExecutorMapping = this.compilerWithTemplateCalague
                .compileFlow(flowSpec);

        // Assert pre-requisites
        Assert.assertNotNull(specExecutorMapping, "Expected non null mapping.");
        Assert.assertTrue(specExecutorMapping.size() == 0, "Exepected 1 executor for FlowSpec.");
    }
}