|
| 1 | +from aws_cdk import Stack |
| 2 | +from aws_cdk import aws_emrserverless as emrs |
| 3 | +from aws_cdk import aws_iam as iam # Duration, |
| 4 | +from aws_cdk import custom_resources as custom |
| 5 | +from constructs import Construct |
| 6 | + |
| 7 | + |
| 8 | +class EmrServerlessJobRunStack(Stack): |
| 9 | + def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: |
| 10 | + super().__init__(scope, construct_id, **kwargs) |
| 11 | + |
| 12 | + # Create a serverless Spark app |
| 13 | + serverless_app = emrs.CfnApplication( |
| 14 | + self, |
| 15 | + "spark_app", |
| 16 | + release_label="emr-6.9.0", |
| 17 | + type="SPARK", |
| 18 | + name="cdk-spark", |
| 19 | + ) |
| 20 | + |
| 21 | + # We need an execution role to run the job, this one has no access to anything |
| 22 | + # But will be granted PassRole access by the Lambda that's starting the job. |
| 23 | + role = iam.Role( |
| 24 | + scope=self, |
| 25 | + id="spark_job_execution_role", |
| 26 | + assumed_by=iam.ServicePrincipal("emr-serverless.amazonaws.com"), |
| 27 | + ) |
| 28 | + |
| 29 | + # Create a custom resource that starts a job run |
| 30 | + myjobrun = custom.AwsCustomResource( |
| 31 | + self, |
| 32 | + "serverless-job-run", |
| 33 | + on_create={ |
| 34 | + "service": "EMRServerless", |
| 35 | + "action": "startJobRun", |
| 36 | + "parameters": { |
| 37 | + "applicationId": serverless_app.attr_application_id, |
| 38 | + "executionRoleArn": role.role_arn, |
| 39 | + "name": "cdkJob", |
| 40 | + "jobDriver": {"sparkSubmit": {"entryPoint": "local:///usr/lib/spark/examples/src/main/python/pi.py"}}, |
| 41 | + }, |
| 42 | + "physical_resource_id": custom.PhysicalResourceId.from_response( |
| 43 | + "jobRunId" |
| 44 | + ), |
| 45 | + }, |
| 46 | + policy=custom.AwsCustomResourcePolicy.from_sdk_calls( |
| 47 | + resources=custom.AwsCustomResourcePolicy.ANY_RESOURCE |
| 48 | + ), |
| 49 | + ) |
| 50 | + |
| 51 | + # Ensure the Lambda can call startJobRun with the earlier-created role |
| 52 | + myjobrun.grant_principal.add_to_policy( |
| 53 | + iam.PolicyStatement( |
| 54 | + effect=iam.Effect.ALLOW, |
| 55 | + resources=[role.role_arn], |
| 56 | + actions=["iam:PassRole"], |
| 57 | + conditions={ |
| 58 | + "StringLike": { |
| 59 | + "iam:PassedToService": "emr-serverless.amazonaws.com" |
| 60 | + } |
| 61 | + }, |
| 62 | + ) |
| 63 | + ) |
0 commit comments