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

com.boozallen.aiops.mda.generator.SparkApplicationGenerator Maven / Gradle / Ivy

package com.boozallen.aiops.mda.generator;

/*-
 * #%L
 * aiSSEMBLE::Foundation::MDA
 * %%
 * Copyright (C) 2021 Booz Allen
 * %%
 * This software package is licensed under the Booz Allen Public License. All Rights Reserved.
 * #L%
 */

import com.boozallen.aiops.mda.ManualActionNotificationService;
import com.boozallen.aiops.mda.generator.common.DataFlowStrategy;
import com.boozallen.aiops.mda.generator.common.SparkStorageEnum;
import com.boozallen.aiops.mda.generator.common.VelocityProperty;
import com.boozallen.aiops.mda.generator.config.deployment.spark.SparkDependencyConfiguration;
import com.boozallen.aiops.mda.generator.util.PipelineUtils;
import com.boozallen.aiops.mda.metamodel.AIOpsModelInstanceRepostory;
import com.boozallen.aiops.mda.metamodel.element.Pipeline;
import com.boozallen.aiops.mda.metamodel.element.java.JavaPipeline;
import com.boozallen.aiops.mda.metamodel.element.python.PythonPipeline;
import com.boozallen.aiops.mda.metamodel.element.BaseFileStoreDecorator;
import com.boozallen.aiops.mda.metamodel.element.FileStore;
import org.apache.velocity.VelocityContext;
import org.technologybrewery.fermenter.mda.generator.GenerationContext;
import org.technologybrewery.fermenter.mda.metamodel.ModelInstanceRepositoryManager;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SparkApplicationGenerator extends AbstractResourcesGenerator {
    /*--~-~-~~
     * Usages:
     * | Target                           | Template                                                          | Generated File                          |
     * |----------------------------------|-------------------------------------------------------------------|-----------------------------------------|
     * | sparkApplicationDebugScript      | deployment/spark-operator/run-debug.sh.vm                         | apps/run-debug.sh                       |
     * | sparkApplicationValuesFile       | deployment/spark-operator/spark-application-base-values.yaml.vm   | apps/${pipelineName}-base-values.yaml   |
     * | sparkApplicationCIValuesFile     | deployment/spark-operator/spark-application-ci-values.yaml.vm     | apps/${pipelineName}-ci-values.yaml     |
     * | sparkApplicationDebugValuesFile  | deployment/spark-operator/spark-application-debug-values.yaml.vm  | apps/${pipelineName}-debug-values.yaml  |
     * | sparkApplicationDevValuesFile    | deployment/spark-operator/spark-application-dev-values.yaml.vm    | apps/${pipelineName}-dev-values.yaml    |
     * | sparkApplicationTestValuesFile   | deployment/spark-operator/spark-application-test-values.yaml.vm   | apps/${pipelineName}-test-values.yaml   |
     */

    protected ManualActionNotificationService manualActionNotificationService = new ManualActionNotificationService();

    private final SparkDependencyConfiguration config = SparkDependencyConfiguration.getInstance();
    protected static final String DOCKER_PROJECT_REPOSITORY_URL = "dockerProjectRepositoryUrl";

    private void handlePySpark(VelocityContext vc, GenerationContext context) {
        Pipeline pipeline = PipelineUtils.getTargetedPipeline(context, metadataContext);
        PythonPipeline pythonTargetPipeline = new PythonPipeline(pipeline);

        String fileName = replace("pipelineName", context.getOutputFile(), pythonTargetPipeline.deriveArtifactIdFromCamelCase());
        context.setOutputFile(fileName);

        vc.put(VelocityProperty.SPARK_APPLICATION_TYPE, "Python");
        vc.put(VelocityProperty.MAIN_APPLICATION_FILE, pythonTargetPipeline.getKababCaseName() + "/" +
                pythonTargetPipeline.getSnakeCaseName() + "_driver.py");
    }

    private void handleSpark(VelocityContext vc, GenerationContext context) {
        Pipeline pipeline = PipelineUtils.getTargetedPipeline(context, metadataContext);
        JavaPipeline javaTargetPipeline = new JavaPipeline(pipeline);

        String fileName = replace("pipelineName", context.getOutputFile(), javaTargetPipeline.deriveArtifactIdFromCamelCase());
        context.setOutputFile(fileName);

        vc.put(VelocityProperty.SPARK_APPLICATION_TYPE, "Java");
        vc.put(VelocityProperty.IS_JAVA_PIPELINE, true);
        vc.put(VelocityProperty.MAIN_APPLICATION_FILE, context.getArtifactId() + ".jar");
        vc.put(VelocityProperty.SPARK_MAIN_CLASS, context.getBasePackage() + "." + javaTargetPipeline.getCapitalizedName() + "Driver");
    }

    @Override
    public void generate(GenerationContext context) {
        AIOpsModelInstanceRepostory metamodelRepository = ModelInstanceRepositoryManager
                .getMetamodelRepository(AIOpsModelInstanceRepostory.class);

        VelocityContext vc = getNewVelocityContext(context);
        Pipeline pipeline = PipelineUtils.getTargetedPipeline(context, metadataContext);
        DataFlowStrategy dfs = new DataFlowStrategy(Collections.singletonList(pipeline));
        List extensions = new ArrayList<>();
        if (dfs.isDeltaSupportNeeded()) {
            extensions.add("io.delta.sql.DeltaSparkSessionExtension");
        }
        if (dfs.isSedonaSupportNeeded()) {
            extensions.add("org.apache.sedona.sql.SedonaSqlExtensions");
        }
        if ("test".equalsIgnoreCase(context.getArtifactType())) {
            vc.put(VelocityProperty.IS_TEST_RESOURCE, true);
        }

        vc.put(VelocityProperty.ENABLE_PYSPARK_SUPPORT, dfs.isPySparkSupportNeeded());
        vc.put(VelocityProperty.ENABLE_RDBMS_SUPPORT, dfs.isRdbmsSupportNeeded());
        vc.put(VelocityProperty.ENABLE_NEO4J_SUPPORT, dfs.isNeo4jSupportNeeded());
        vc.put(VelocityProperty.ENABLE_DELTA_SUPPORT, dfs.isDeltaSupportNeeded());
        vc.put(VelocityProperty.ENABLE_ELASTICSEARCH_SUPPORT, dfs.isElasticsearchSupportNeeded());
        vc.put(VelocityProperty.ENABLE_HIVE_SUPPORT, dfs.isHiveSupportNeeded());
        vc.put(VelocityProperty.ENABLE_SEDONA_SUPPORT, dfs.isSedonaSupportNeeded());
        vc.put(VelocityProperty.ENABLE_DATA_LINEAGE_SUPPORT, dfs.isDataLineageNeeded());
        vc.put(VelocityProperty.SPARK_EXTENSIONS, String.join(",", extensions));

        vc.put("versionSpark", config.getSparkVersion());
        vc.put("versionDelta", config.getDeltaVersion());
        vc.put("versionElasticsearch", config.getElasticSearchVersion());
        vc.put("versionSedona", config.getSedonaVersion());
        vc.put("versionGeotools", config.getGeotoolsVersion());
        vc.put("versionPostgresql", config.getPostgresqlVersion());
        vc.put("versionMysqlConnector", config.getMysqlConnectorVersion());
        vc.put("versionHadoop", config.getHadoopVersion());
        vc.put("versionNeo4j", config.getNeo4jVersion());
        vc.put("versionAwsSdkBundle", config.getAwsSdkBundleVersion());

        if (pipeline.getType().getImplementation().equalsIgnoreCase("data-delivery-spark")) {
            handleSpark(vc, context);
        } else if (pipeline.getType().getImplementation().equalsIgnoreCase("data-delivery-pyspark")) {
            handlePySpark(vc, context);
        } else {
            throw new IllegalArgumentException("Invalid implementation form: " + pipeline.getType().getImplementation());
        }

        final String projectName = context.getRootArtifactId();
        String dockerProjectRepositoryUrl = context.getPropertyVariables().get(DOCKER_PROJECT_REPOSITORY_URL);

        vc.put(VelocityProperty.SPARK_APPLICATION_NAME, context.getArtifactId());
        vc.put(VelocityProperty.PROJECT_NAME, projectName);
        vc.put(VelocityProperty.PIPELINE, pipeline.getName());
        vc.put(VelocityProperty.DOCKER_PROJECT_REPOSITORY_URL, dockerProjectRepositoryUrl);

        List fileStores = pipeline.getFileStores();
        boolean enableFileStore = !fileStores.isEmpty();
        vc.put(VelocityProperty.ENABLE_FILE_STORE, enableFileStore);
        if(enableFileStore){
            List decoratedStores = new ArrayList<>();
            for(FileStore fileStore : fileStores){
                BaseFileStoreDecorator decoratedStore = new BaseFileStoreDecorator(fileStore);
                decoratedStores.add(decoratedStore);
            }
            vc.put(VelocityProperty.FILE_STORES, decoratedStores);
        }

        if (!"test".equalsIgnoreCase(context.getArtifactType()) && SparkStorageEnum.S3LOCAL == metamodelRepository.getDeploymentConfigurationManager().getSparkDeploymentConfiguration().getStorageType()) {
            vc.put(VelocityProperty.USE_S3_LOCAL, true);
            manualActionNotificationService.addDeployPomMessage(context, "s3local-deploy-v2", "s3-local");
            manualActionNotificationService.addPipelineInvocationServiceDeployment(context);
            manualActionNotificationService.addNoticeToUpdateKafkaConfig(context, "pipeline-invocation");
            manualActionNotificationService.addNoticeToUpdateS3LocalConfig(context, "spark-infrastructure", Arrays.asList("warehouse/"));

        }

        generateFile(context, vc);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy