user189198
user189198

Reputation:

Passing event data from Amazon EventBridge into an AWS Fargate task

Objective

I'd like to pass event data from Amazon EventBridge directly into an AWS Fargate task. However, it doesn't seem like this is currently possible.

Workaround

As a work-around, I've inserted an extra resource in between AWS Fargate and EventBridge. AWS Step Functions allows you to specify ContainerOverrides, in which the Environment property allows you to configure environment variables that will be passed into the Fargate task, from the EventBridge event.

Unfortunately, this workaround increases the solution complexity and cost unnecessarily.

Question: Is there a way to pass event data from EventBridge directly into an AWS Fargate (ECS) task, that I am simply unaware of?

Upvotes: 10

Views: 10805

Answers (2)

Aakash
Aakash

Reputation: 3171

To pass data from Eventbridge Event to ECS Task for e.g with a Launch Type FARGATE you can use Input Transformation. For example let's say we have an S3 bucket configured to send all event notifications to eventbridge and we have an eventbridge rule that looks like this.

{
      "detail": {
        "bucket": {
          "name": ["mybucket"]
        }
      },
      "detail-type": ["Object Created"],
      "source": ["aws.s3"]
}

Now let's say we would like to pass the bucket name, object key, and the object version id to our ecs task running on fargate you can create a aws_cloudwatch_event_target resource in terraform with an input transformer below.

resource "aws_cloudwatch_event_target" "EventBridgeECSTaskTarget"{
  target_id = "EventBridgeECSTaskTarget"
  rule = aws_cloudwatch_event_rule.myeventbridgerule.name
  arn = "arn:aws:ecs:us-east-1:123456789012:cluster/myecscluster"
  role_arn = aws_iam_role.EventBridgeRuleInvokeECSTask.arn

  ecs_target {
    task_count          = 1
    task_definition_arn = "arn:aws:ecs:us-east-1:123456789012:task-definition/mytaskdefinition"
    launch_type = "FARGATE"
    
    network_configuration {
      subnets         = ["subnet-1","subnet-2","subnet-3"]
      security_groups = ["sg-group-id"]
   }
  }

  input_transformer {
    input_paths = {
      bucketname = "$.detail.bucket.name",
      objectkey   = "$.detail.object.key",
      objectversionid = "$.detail.object.version-id",
    }
    input_template = <<EOF
{
  "containerOverrides": [
    {
      "name": "containername",
      "environment" : [
        {
          "name" : "S3_BUCKET_NAME",
          "value" : <bucketname>
        },
        {
          "name" : "S3_OBJECT_KEY",
          "value" : <objectkey>
        },
        {
          "name" : "S3_OBJ_VERSION_ID",
          "value": <objectversionid>
        }
      ]
    }
  ]
}
EOF
  }
}

Once your ECS Task is running you can easily access these variables to check what bucket the object was created in, what was the object and the version and do a GetObject.

For e.g: In Go we can easily do it as follows. (snippets only not adding imports and stuff but you get the idea.

filename := aws.String(os.Getenv("S3_OBJECT_KEY"))
bucketname := aws.String(os.Getenv("S3_BUCKET_NAME"))
versionId := aws.String(os.Getenv("S3_OBJ_VERSION_ID"))

//You can print and verify the values in CloudWatch

//Prepare the s3 GetObjectInput

s3goi := &s3.GetObjectInput{
        Bucket: bucketname,
        Key:    filename,
        VersionId: versionId,
    }

s3goo, err := s3svc.GetObject(ctx, s3goi)
    if err != nil {
        log.Fatalf("Error retreiving object: %v", err)
    }

b, err := ioutil.ReadAll(s3goo.Body)
    if err != nil {
        log.Fatalf("Error reading file: %v", err)
    }

Upvotes: 9

blr
blr

Reputation: 968

There's no current direct invocation between EventBridge and Fargate. You can find the list of targets supported at https://docs.aws.amazon.com/eventbridge/latest/userguide/eventbridge-targets.html

The workarounds is to use an intermediary that supports calling fargate (like step-functions) or send the message to compute (like lambda [the irony]) before sending it downstream.

Upvotes: 2

Related Questions