@@ -64,6 +64,88 @@ resource "aws_dynamodb_table" "orders" {
6464 }
6565}
6666
67+ # ── ECR ───────────────────────────────────────────────────────────────────────
68+
69+ resource "aws_ecr_repository" "fulfillment" {
70+ name = " fulfillment"
71+ }
72+
73+ # ── ECS ───────────────────────────────────────────────────────────────────────
74+
75+ resource "aws_ecs_cluster" "main" {
76+ name = " workshop"
77+ }
78+
79+ resource "aws_iam_role" "ecs_execution" {
80+ name = " ecs-execution-role"
81+
82+ assume_role_policy = jsonencode ({
83+ Version = " 2012-10-17"
84+ Statement = [{
85+ Action = " sts:AssumeRole"
86+ Effect = " Allow"
87+ Principal = { Service = " ecs-tasks.amazonaws.com" }
88+ }]
89+ })
90+ }
91+
92+ resource "aws_iam_role_policy_attachment" "ecs_execution" {
93+ role = aws_iam_role. ecs_execution . name
94+ policy_arn = " arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
95+ }
96+
97+ resource "aws_iam_role" "ecs_task" {
98+ name = " ecs-task-role"
99+
100+ assume_role_policy = jsonencode ({
101+ Version = " 2012-10-17"
102+ Statement = [{
103+ Action = " sts:AssumeRole"
104+ Effect = " Allow"
105+ Principal = { Service = " ecs-tasks.amazonaws.com" }
106+ }]
107+ })
108+ }
109+
110+ resource "aws_iam_role_policy" "ecs_task" {
111+ role = aws_iam_role. ecs_task . id
112+
113+ policy = jsonencode ({
114+ Version = " 2012-10-17"
115+ Statement = [
116+ {
117+ Effect = " Allow"
118+ Action = [" dynamodb:GetItem" , " dynamodb:UpdateItem" ]
119+ Resource = aws_dynamodb_table.orders.arn
120+ },
121+ {
122+ Effect = " Allow"
123+ Action = [" s3:PutObject" ]
124+ Resource = " ${ aws_s3_bucket . receipts . arn } /*"
125+ }
126+ ]
127+ })
128+ }
129+
130+ resource "aws_ecs_task_definition" "fulfillment" {
131+ family = " fulfillment"
132+ requires_compatibilities = [" FARGATE" ]
133+ network_mode = " awsvpc"
134+ cpu = 256
135+ memory = 512
136+ execution_role_arn = aws_iam_role. ecs_execution . arn
137+ task_role_arn = aws_iam_role. ecs_task . arn
138+
139+ container_definitions = jsonencode ([{
140+ name = " fulfillment"
141+ image = " ${ aws_ecr_repository . fulfillment . repository_url } :latest"
142+ environment = [
143+ { name = " ORDERS_TABLE" , value = aws_dynamodb_table.orders.name },
144+ { name = " RECEIPTS_BUCKET" , value = aws_s3_bucket.receipts.bucket },
145+ ]
146+ }])
147+ }
148+
67149# ── S3 ────────────────────────────────────────────────────────────────────────
68150
69151resource "aws_s3_bucket" "receipts" {
@@ -148,11 +230,28 @@ resource "aws_iam_role_policy" "sfn_policy" {
148230
149231 policy = jsonencode ({
150232 Version = " 2012-10-17"
151- Statement = [{
152- Effect = " Allow"
153- Action = " lambda:InvokeFunction"
154- Resource = aws_lambda_function.order_processor.arn
155- }]
233+ Statement = [
234+ {
235+ Effect = " Allow"
236+ Action = " lambda:InvokeFunction"
237+ Resource = aws_lambda_function.order_processor.arn
238+ },
239+ {
240+ Effect = " Allow"
241+ Action = [" ecs:RunTask" , " ecs:StopTask" , " ecs:DescribeTasks" ]
242+ Resource = " *"
243+ },
244+ {
245+ Effect = " Allow"
246+ Action = " iam:PassRole"
247+ Resource = [aws_iam_role.ecs_execution.arn, aws_iam_role.ecs_task.arn]
248+ },
249+ {
250+ Effect = " Allow"
251+ Action = [" events:PutTargets" , " events:PutRule" , " events:DescribeRule" ]
252+ Resource = " *"
253+ }
254+ ]
156255 })
157256}
158257
@@ -202,7 +301,6 @@ resource "aws_lambda_function" "order_processor" {
202301 environment {
203302 variables = {
204303 ORDERS_TABLE = aws_dynamodb_table.orders.name
205- RECEIPTS_BUCKET = aws_s3_bucket.receipts.bucket
206304 STATE_MACHINE_ARN = local.state_machine_arn
207305 }
208306 }
@@ -251,12 +349,21 @@ resource "aws_sfn_state_machine" "order_processing" {
251349 }
252350 FulfillOrder = {
253351 Type = " Task"
254- Resource = aws_lambda_function.order_processor. arn
352+ Resource = " arn:aws:states:::ecs:runTask.sync:2 "
255353 Parameters = {
256- " step" = " fulfill"
257- " order.$" = " $.order"
354+ LaunchType = " FARGATE"
355+ Cluster = aws_ecs_cluster.main.arn
356+ TaskDefinition = aws_ecs_task_definition.fulfillment.arn
357+ Overrides = {
358+ ContainerOverrides = [{
359+ Name = " fulfillment"
360+ Environment = [
361+ { " Name" = " ORDER_ID" , " Value.$" = " $.order.order_id" }
362+ ]
363+ }]
364+ }
258365 }
259- ResultPath = " $.order "
366+ ResultPath = null
260367 Catch = [{ ErrorEquals = [" States.ALL" ], Next = " HandleFailure" , ResultPath = " $.error" }]
261368 End = true
262369 }
0 commit comments