-
Notifications
You must be signed in to change notification settings - Fork 212
Add EMR client to spark connector #1790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
70588d6
Create Spark Connector
vamsimanohar 2b8ceb7
Add spark client and engine
rupal-bq f595ff4
Remove vars
rupal-bq 95a86d5
Merge branch 'main' into create-spark-connector
rupal-bq 51700bd
Merge branch 'main' into create-spark-connector
rupal-bq d0d5042
Spark connector draft
rupal-bq 5ac01b2
nit
rupal-bq 4fcf4ba
Fix checkstyle errors
rupal-bq 52a044d
nit
rupal-bq 69ca116
Fix license header
rupal-bq 901e762
Add spark storage test
rupal-bq 1b81453
Update comments
rupal-bq 106218e
Fix checkstyle in comments
rupal-bq 6da93f3
Merge branch 'main' into create-spark-connector
rupal-bq b953aa6
Update tests
rupal-bq 2f899cd
Add emr client
rupal-bq 8ebab1a
Set default values for flint args
rupal-bq 7dcad73
Validate emr auth type
rupal-bq 23f195f
Add default constants for flint
rupal-bq 63e3f6d
Update unit tests
rupal-bq 0df37a8
Address PR comments
rupal-bq 99d561a
tests draft
rupal-bq 776bc36
Refactor class name
rupal-bq 0eb5e53
Merge branch 'main' into create-spark-connector
rupal-bq 680268a
Merge branch 'create-spark-connector' into emr-client
rupal-bq 890c8c7
Rename classes and update tests
rupal-bq 9fc496a
Update scan operator test
rupal-bq be15dae
Address PR comment
rupal-bq e74e036
Fix Connection pool shut down issue
rupal-bq dbf0367
Update emr unit tests
rupal-bq b8209bd
Merge branch 'create-spark-connector' into emr-client
rupal-bq 2f73d40
Merge branch 'main' into emr-client
rupal-bq 7f8c2ab
Update doc and tests
rupal-bq cd9a4fe
nit
rupal-bq 9e34ce3
Update EMR clinet impl tests
rupal-bq c029ae5
Address PR comments
rupal-bq 9d249ee
Make spark & flint jars configurable
rupal-bq f9d7382
Address comments
rupal-bq c6e0076
Add spark application id in logs
rupal-bq cc6d8cb
nit
rupal-bq 5bbda31
Delete result when not required
rupal-bq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| .. highlight:: sh | ||
|
|
||
| ==================== | ||
| Spark Connector | ||
| ==================== | ||
|
|
||
| .. rubric:: Table of contents | ||
|
|
||
| .. contents:: | ||
| :local: | ||
| :depth: 1 | ||
|
|
||
|
|
||
| Introduction | ||
| ============ | ||
|
|
||
| This page covers spark connector properties for dataSource configuration | ||
| and the nuances associated with spark connector. | ||
|
|
||
|
|
||
| Spark Connector Properties in DataSource Configuration | ||
| ======================================================== | ||
| Spark Connector Properties. | ||
|
|
||
| * ``spark.connector`` [Required]. | ||
| * This parameters provides the spark client information for connection. | ||
| * ``spark.sql.application`` [Optional]. | ||
| * This parameters provides the spark sql application jar. Default value is ``s3://spark-datasource/sql-job.jar``. | ||
| * ``emr.cluster`` [Required]. | ||
| * This parameters provides the emr cluster id information. | ||
| * ``emr.auth.type`` [Required] | ||
| * This parameters provides the authentication type information. | ||
| * Spark emr connector currently supports ``awssigv4`` authentication mechanism and following parameters are required. | ||
| * ``emr.auth.region``, ``emr.auth.access_key`` and ``emr.auth.secret_key`` | ||
| * ``spark.datasource.flint.*`` [Optional] | ||
| * This parameters provides the Opensearch domain host information for flint integration. | ||
| * ``spark.datasource.flint.integration`` [Optional] | ||
| * Default value for integration jar is ``s3://spark-datasource/flint-spark-integration-assembly-0.1.0-SNAPSHOT.jar``. | ||
| * ``spark.datasource.flint.host`` [Optional] | ||
| * Default value for host is ``localhost``. | ||
| * ``spark.datasource.flint.port`` [Optional] | ||
| * Default value for port is ``9200``. | ||
| * ``spark.datasource.flint.scheme`` [Optional] | ||
| * Default value for scheme is ``http``. | ||
| * ``spark.datasource.flint.auth`` [Optional] | ||
| * Default value for auth is ``false``. | ||
| * ``spark.datasource.flint.region`` [Optional] | ||
| * Default value for auth is ``us-west-2``. | ||
|
|
||
| Example spark dataSource configuration | ||
| ======================================== | ||
|
|
||
| AWSSigV4 Auth:: | ||
|
|
||
| [{ | ||
| "name" : "my_spark", | ||
| "connector": "spark", | ||
| "properties" : { | ||
| "spark.connector": "emr", | ||
| "emr.cluster" : "{{clusterId}}", | ||
| "emr.auth.type" : "awssigv4", | ||
| "emr.auth.region" : "us-east-1", | ||
| "emr.auth.access_key" : "{{accessKey}}" | ||
| "emr.auth.secret_key" : "{{secretKey}}" | ||
| "spark.datasource.flint.host" : "{{opensearchHost}}", | ||
| "spark.datasource.flint.port" : "{{opensearchPort}}", | ||
| "spark.datasource.flint.scheme" : "{{opensearchScheme}}", | ||
| "spark.datasource.flint.auth" : "{{opensearchAuth}}", | ||
| "spark.datasource.flint.region" : "{{opensearchRegion}}", | ||
| } | ||
| }] | ||
|
|
||
|
|
||
| Spark SQL Support | ||
| ================== | ||
|
|
||
| `sql` Function | ||
| ---------------------------- | ||
| Spark connector offers `sql` function. This function can be used to run spark sql query. | ||
| The function takes spark sql query as input. Argument should be either passed by name or positionArguments should be either passed by name or position. | ||
| `source=my_spark.sql('select 1')` | ||
| or | ||
| `source=my_spark.sql(query='select 1')` | ||
| Example:: | ||
|
|
||
| > source=my_spark.sql('select 1') | ||
| +---+ | ||
| | 1 | | ||
| |---+ | ||
| | 1 | | ||
| +---+ | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
spark/src/main/java/org/opensearch/sql/spark/client/EmrClientImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.spark.client; | ||
|
|
||
| import static org.opensearch.sql.spark.data.constants.SparkConstants.SPARK_INDEX_NAME; | ||
| import static org.opensearch.sql.spark.data.constants.SparkConstants.SPARK_SQL_APPLICATION_JAR; | ||
|
|
||
| import com.amazonaws.services.elasticmapreduce.AmazonElasticMapReduce; | ||
| import com.amazonaws.services.elasticmapreduce.model.ActionOnFailure; | ||
| import com.amazonaws.services.elasticmapreduce.model.AddJobFlowStepsRequest; | ||
| import com.amazonaws.services.elasticmapreduce.model.AddJobFlowStepsResult; | ||
| import com.amazonaws.services.elasticmapreduce.model.DescribeStepRequest; | ||
| import com.amazonaws.services.elasticmapreduce.model.HadoopJarStepConfig; | ||
| import com.amazonaws.services.elasticmapreduce.model.StepConfig; | ||
| import com.amazonaws.services.elasticmapreduce.model.StepStatus; | ||
| import com.google.common.annotations.VisibleForTesting; | ||
| import java.io.IOException; | ||
| import lombok.SneakyThrows; | ||
| import org.apache.logging.log4j.LogManager; | ||
| import org.apache.logging.log4j.Logger; | ||
| import org.json.JSONObject; | ||
| import org.opensearch.sql.spark.helper.FlintHelper; | ||
| import org.opensearch.sql.spark.response.SparkResponse; | ||
|
|
||
| public class EmrClientImpl implements SparkClient { | ||
| private final AmazonElasticMapReduce emr; | ||
| private final String emrCluster; | ||
| private final FlintHelper flint; | ||
| private final String sparkApplicationJar; | ||
| private static final Logger logger = LogManager.getLogger(EmrClientImpl.class); | ||
| private SparkResponse sparkResponse; | ||
|
|
||
| /** | ||
| * Constructor for EMR Client Implementation. | ||
| * | ||
| * @param emr EMR helper | ||
| * @param flint Opensearch args for flint integration jar | ||
| * @param sparkResponse Response object to help with retrieving results from Opensearch index | ||
| */ | ||
| public EmrClientImpl(AmazonElasticMapReduce emr, String emrCluster, FlintHelper flint, | ||
| SparkResponse sparkResponse, String sparkApplicationJar) { | ||
| this.emr = emr; | ||
| this.emrCluster = emrCluster; | ||
| this.flint = flint; | ||
| this.sparkResponse = sparkResponse; | ||
| this.sparkApplicationJar = | ||
| sparkApplicationJar == null ? SPARK_SQL_APPLICATION_JAR : sparkApplicationJar; | ||
| } | ||
|
|
||
| @Override | ||
| public JSONObject sql(String query) throws IOException { | ||
| runEmrApplication(query); | ||
| return sparkResponse.getResultFromOpensearchIndex(); | ||
| } | ||
|
|
||
| @VisibleForTesting | ||
| void runEmrApplication(String query) { | ||
|
|
||
| HadoopJarStepConfig stepConfig = new HadoopJarStepConfig() | ||
| .withJar("command-runner.jar") | ||
| .withArgs("spark-submit", | ||
| "--class","org.opensearch.sql.SQLJob", | ||
| "--jars", | ||
| flint.getFlintIntegrationJar(), | ||
| sparkApplicationJar, | ||
| query, | ||
| SPARK_INDEX_NAME, | ||
| flint.getFlintHost(), | ||
| flint.getFlintPort(), | ||
| flint.getFlintScheme(), | ||
| flint.getFlintAuth(), | ||
| flint.getFlintRegion() | ||
| ); | ||
|
|
||
| StepConfig emrstep = new StepConfig() | ||
| .withName("Spark Application") | ||
| .withActionOnFailure(ActionOnFailure.CONTINUE) | ||
| .withHadoopJarStep(stepConfig); | ||
|
|
||
| AddJobFlowStepsRequest request = new AddJobFlowStepsRequest() | ||
| .withJobFlowId(emrCluster) | ||
| .withSteps(emrstep); | ||
|
|
||
| AddJobFlowStepsResult result = emr.addJobFlowSteps(request); | ||
| logger.info("EMR step ID: " + result.getStepIds()); | ||
|
|
||
| String stepId = result.getStepIds().get(0); | ||
| DescribeStepRequest stepRequest = new DescribeStepRequest() | ||
| .withClusterId(emrCluster) | ||
| .withStepId(stepId); | ||
|
|
||
| waitForStepExecution(stepRequest); | ||
| sparkResponse.setValue(stepId); | ||
| } | ||
|
|
||
| @SneakyThrows | ||
| private void waitForStepExecution(DescribeStepRequest stepRequest) { | ||
| // Wait for the step to complete | ||
| boolean completed = false; | ||
| while (!completed) { | ||
| // Get the step status | ||
| StepStatus statusDetail = emr.describeStep(stepRequest).getStep().getStatus(); | ||
| // Check if the step has completed | ||
| if (statusDetail.getState().equals("COMPLETED")) { | ||
| completed = true; | ||
| logger.info("EMR step completed successfully."); | ||
| } else if (statusDetail.getState().equals("FAILED") | ||
| || statusDetail.getState().equals("CANCELLED")) { | ||
| logger.error("EMR step failed or cancelled."); | ||
| throw new RuntimeException("Spark SQL application failed."); | ||
| } else { | ||
| // Sleep for some time before checking the status again | ||
| Thread.sleep(2500); | ||
|
rupal-bq marked this conversation as resolved.
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| } | ||
20 changes: 20 additions & 0 deletions
20
spark/src/main/java/org/opensearch/sql/spark/data/constants/SparkConstants.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.spark.data.constants; | ||
|
|
||
| public class SparkConstants { | ||
| public static final String EMR = "emr"; | ||
| public static final String STEP_ID_FIELD = "stepId.keyword"; | ||
| public static final String SPARK_SQL_APPLICATION_JAR = "s3://spark-datasource/sql-job.jar"; | ||
| public static final String SPARK_INDEX_NAME = ".query_execution_result"; | ||
| public static final String FLINT_INTEGRATION_JAR = | ||
| "s3://spark-datasource/flint-spark-integration-assembly-0.1.0-SNAPSHOT.jar"; | ||
| public static final String FLINT_DEFAULT_HOST = "localhost"; | ||
| public static final String FLINT_DEFAULT_PORT = "9200"; | ||
| public static final String FLINT_DEFAULT_SCHEME = "http"; | ||
| public static final String FLINT_DEFAULT_AUTH = "-1"; | ||
| public static final String FLINT_DEFAULT_REGION = "us-west-2"; | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.