diff --git a/aws-fargate-terraform/buildspec.yml b/aws-fargate-terraform/buildspec.yml new file mode 100644 index 00000000..7ada4351 --- /dev/null +++ b/aws-fargate-terraform/buildspec.yml @@ -0,0 +1,45 @@ +version: 0.2 + +phases: + install: + runtime-versions: + java: openjdk8 + docker: 18 + pre_build: + commands: + - $(aws ecr get-login --region ${region} --no-include-email) + - REGISTRY_URI_CUSTOMER=${repository_url_customer} + - REGISTRY_URI_ORDER=${repository_url_order} + - REGISTRY_URI_ORDER_HISTORY=${repository_url_orderhistory} + - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7) + - echo Finished the pre_build phase... + build: + commands: + - echo Build started on `date` + - echo Building the Docker image... + - export DOCKER_HOST_IP=`hostname -i` + - ./gradlew assemble + - docker build -t $REGISTRY_URI_CUSTOMER:$IMAGE_TAG customer-service + - docker build -t $REGISTRY_URI_ORDER:$IMAGE_TAG order-service + - docker build -t $REGISTRY_URI_ORDER_HISTORY:$IMAGE_TAG order-history-service + + post_build: + commands: + - echo Build completed on `date` + - echo Pushing the Docker images... + - docker push $REGISTRY_URI_ORDER:$IMAGE_TAG + - docker push $REGISTRY_URI_CUSTOMER:$IMAGE_TAG + - docker push $REGISTRY_URI_ORDER_HISTORY:$IMAGE_TAG + - echo Writing image definitions file... + - printf '[{"name":"order","imageUri":"%s"}]' $REGISTRY_URI_ORDER:$IMAGE_TAG > imagedefinitions1.json + - printf '[{"name":"customer","imageUri":"%s"}]' $REGISTRY_URI_CUSTOMER:$IMAGE_TAG > imagedefinitions2.json + - printf '[{"name":"orderhistory","imageUri":"%s"}]' $REGISTRY_URI_ORDER_HISTORY:$IMAGE_TAG > imagedefinitions3.json + - ls -l + - cat imagedefinitions1.json + - cat imagedefinitions2.json + - cat imagedefinitions3.json +artifacts: + files: + - imagedefinitions1.json + - imagedefinitions2.json + - imagedefinitions3.json diff --git a/aws-fargate-terraform/codebuild_policy.json b/aws-fargate-terraform/codebuild_policy.json new file mode 100644 index 00000000..bd45c741 --- /dev/null +++ b/aws-fargate-terraform/codebuild_policy.json @@ -0,0 +1,41 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Resource": [ + "*" + ], + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "ecr:GetAuthorizationToken", + "ecr:InitiateLayerUpload", + "ecr:UploadLayerPart", + "ecr:CompleteLayerUpload", + "ecr:BatchCheckLayerAvailability", + "ecr:PutImage", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:BatchCheckLayerAvailability", + "ecs:RunTask", + "iam:PassRole" + ] + }, + { + "Effect":"Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion", + "s3:GetBucketVersioning", + "s3:List*", + "s3:PutObject" + ], + "Resource": [ + "${aws_s3_bucket_arn}", + "${aws_s3_bucket_arn}/*" + ] + } + ] +} \ No newline at end of file diff --git a/aws-fargate-terraform/codebuild_role.json b/aws-fargate-terraform/codebuild_role.json new file mode 100644 index 00000000..23e96ea1 --- /dev/null +++ b/aws-fargate-terraform/codebuild_role.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} \ No newline at end of file diff --git a/aws-fargate-terraform/codepipeline.json b/aws-fargate-terraform/codepipeline.json new file mode 100644 index 00000000..7ea84557 --- /dev/null +++ b/aws-fargate-terraform/codepipeline.json @@ -0,0 +1,103 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect":"Allow", + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion", + "s3:GetBucketVersioning", + "s3:List*", + "s3:PutObject" + ], + "Resource": [ + "${aws_s3_bucket_arn}", + "${aws_s3_bucket_arn}/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "codebuild:BatchGetBuilds", + "codebuild:StartBuild" + ], + "Resource": "*" + }, + { + "Action": [ + "ecs:*", + "events:DescribeRule", + "events:DeleteRule", + "events:ListRuleNamesByTarget", + "events:ListTargetsByRule", + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfiles", + "iam:ListRoles", + "logs:CreateLogGroup", + "logs:DescribeLogGroups", + "logs:FilterLogEvents" + ], + "Resource": "*", + "Effect": "Allow" + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": [ + "*" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": "ecs-tasks.amazonaws.com" + } + } + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/ecsInstanceRole*" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] + } + } + }, + { + "Action": "iam:PassRole", + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/ecsAutoscaleRole*" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "application-autoscaling.amazonaws.com", + "application-autoscaling.amazonaws.com.cn" + ] + } + } + }, + { + "Effect": "Allow", + "Action": "iam:CreateServiceLinkedRole", + "Resource": "*", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "ecs.amazonaws.com", + "spot.amazonaws.com", + "spotfleet.amazonaws.com" + ] + } + } + } + ] +} \ No newline at end of file diff --git a/aws-fargate-terraform/codepipeline.tf b/aws-fargate-terraform/codepipeline.tf new file mode 100644 index 00000000..fac69740 --- /dev/null +++ b/aws-fargate-terraform/codepipeline.tf @@ -0,0 +1,246 @@ +provider "github" { + organization = "${var.git_username}" + token = "${var.git_pat}" +} + +resource "aws_ecr_repository" "cdc" { + name = "${var.prefix}-cdc-service" +} + +resource "aws_ecr_repository" "customer" { + name = "${var.prefix}-customer-service" +} + +resource "aws_ecr_repository" "order" { + name = "${var.prefix}-order-service" +} + +resource "aws_ecr_repository" "orderhistory" { + name = "${var.prefix}-orderhistory-service" +} + +resource "aws_s3_bucket" "source" { + bucket = "${var.prefix}-eventuate-source" + acl = "private" + force_destroy = true +} + +resource "aws_iam_role" "codebuild_role" { + name = "${var.prefix}-codebuild-role" + assume_role_policy = "${file("${path.module}/codebuild_role.json")}" +} + +data "template_file" "codebuild_policy" { + template = "${file("${path.module}/codebuild_policy.json")}" + vars { + aws_s3_bucket_arn = "${aws_s3_bucket.source.arn}" + } +} + +resource "aws_iam_role_policy" "codebuild_policy" { + name = "${var.prefix}-codebuild-policy" + role = "${aws_iam_role.codebuild_role.id}" + policy = "${data.template_file.codebuild_policy.rendered}" +} + +data "template_file" "buildspec" { + template = "${file("${path.module}/buildspec.yml")}" + + vars { + repository_url_cdc = "${aws_ecr_repository.cdc.repository_url}" + repository_url_customer = "${aws_ecr_repository.customer.repository_url}" + repository_url_order = "${aws_ecr_repository.order.repository_url}" + repository_url_orderhistory = "${aws_ecr_repository.orderhistory.repository_url}" + region = "${var.region}" + cluster_name = "${aws_ecs_cluster.cluster.name}" + subnet_id = "${aws_subnet.public-subnet1.id}" + security_group_ids = "${aws_security_group.sg-ecs.id})}" + } +} + +resource "aws_codebuild_project" "eventuate_build" { + name = "${var.prefix}-eventuate-codebuild" + build_timeout = "50" + service_role = "${aws_iam_role.codebuild_role.arn}" + + artifacts { + type = "CODEPIPELINE" + } + + environment { + compute_type = "BUILD_GENERAL1_MEDIUM" + image = "aws/codebuild/standard:2.0" + type = "LINUX_CONTAINER" + privileged_mode = true + + } + + source { + type = "CODEPIPELINE" + buildspec = "${data.template_file.buildspec.rendered}" + } +} + +resource "aws_codepipeline" "pipeline" { + name = "${var.prefix}-app-pipeline" + role_arn = "${aws_iam_role.codepipeline_role.arn}" + + artifact_store { + location = "${aws_s3_bucket.source.bucket}" + type = "S3" + } + + stage { + name = "Source" + + + action { + name = "Source" + category = "Source" + owner = "ThirdParty" + provider = "GitHub" + version = "1" + output_artifacts = ["source"] + + + configuration { + Owner = "${var.git_username}" + Repo = "eventuate-tram-examples-customers-and-orders" + Branch = "master" + OAuthToken = "${var.git_pat}" + + } + } + } + + stage { + name = "Build" + + action { + name = "Build" + category = "Build" + owner = "AWS" + provider = "CodeBuild" + version = "1" + + input_artifacts = ["source"] + output_artifacts = ["imagedefinitions"] + + configuration { + ProjectName = "${aws_codebuild_project.eventuate_build.name}" + } + } + } + + stage { + name = "DeployOrder" + + action { + name = "DeployOrder" + category = "Deploy" + owner = "AWS" + provider = "ECS" + input_artifacts = ["imagedefinitions"] + version = "1" + + configuration { + ClusterName = "${aws_ecs_cluster.cluster.name}" + ServiceName = "${aws_ecs_service.svc_order.name}" + FileName = "imagedefinitions1.json" + } + } + } + + stage { + name = "DeployCustomer" + + action { + name = "DeployCustomer" + category = "Deploy" + owner = "AWS" + provider = "ECS" + input_artifacts = ["imagedefinitions"] + version = "1" + + configuration { + ClusterName = "${aws_ecs_cluster.cluster.name}" + ServiceName = "${aws_ecs_service.svc_customer.name}" + FileName = "imagedefinitions2.json" + } + } + } + + stage { + name = "DeployOrderHistory" + + action { + name = "DeployOrderHistory" + category = "Deploy" + owner = "AWS" + provider = "ECS" + input_artifacts = ["imagedefinitions"] + version = "1" + + configuration { + ClusterName = "${aws_ecs_cluster.cluster.name}" + ServiceName = "${aws_ecs_service.svc_orderhistory.name}" + FileName = "imagedefinitions3.json" + } + } + } + +} + +locals { + webhook_secret = "super-secret" +} + +resource "aws_codepipeline_webhook" "pipeline_webhook" { + name = "${var.prefix}-app-webhook-github" + authentication = "GITHUB_HMAC" + target_action = "Source" + target_pipeline = "${aws_codepipeline.pipeline.name}" + authentication_configuration { + secret_token = "${local.webhook_secret}" + } + + filter { + json_path = "$.ref" + match_equals = "refs/heads/{Branch}" + } +} + +resource "github_repository_webhook" "git_webhook" { + repository = "${data.github_repository.repo.name}" + + configuration { + url = "${aws_codepipeline_webhook.pipeline_webhook.url}" + content_type = "form" + insecure_ssl = true + secret = "${local.webhook_secret}" + } + + events = ["push"] +} + +data "github_repository" "repo" { + name = "eventuate-tram-examples-customers-and-orders" +} + +resource "aws_iam_role" "codepipeline_role" { + name = "${var.prefix}-codepipeline-role" + assume_role_policy = "${file("${path.module}/codepipeline_role.json")}" +} + +data "template_file" "codepipeline_policy" { + template = "${file("${path.module}/codepipeline.json")}" + vars { + aws_s3_bucket_arn = "${aws_s3_bucket.source.arn}" + } +} + +resource "aws_iam_role_policy" "codepipeline_policy" { + name = "${var.prefix}-codepipeline_policy" + role = "${aws_iam_role.codepipeline_role.id}" + policy = "${data.template_file.codepipeline_policy.rendered}" +} diff --git a/aws-fargate-terraform/codepipeline_role.json b/aws-fargate-terraform/codepipeline_role.json new file mode 100644 index 00000000..be32a2ea --- /dev/null +++ b/aws-fargate-terraform/codepipeline_role.json @@ -0,0 +1,12 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "codepipeline.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +} \ No newline at end of file diff --git a/aws-fargate-terraform/ecs_customer_definition.json b/aws-fargate-terraform/ecs_customer_definition.json index b514abdb..5c8df98f 100644 --- a/aws-fargate-terraform/ecs_customer_definition.json +++ b/aws-fargate-terraform/ecs_customer_definition.json @@ -44,7 +44,7 @@ "value": "${db_user}" } ], - "image": "eventuateexamples/eventuate-tram-examples-customers-and-orders-customer-service", + "image": "${image_uri}", "essential": true, "name": "customer", "healthCheck" : { diff --git a/aws-fargate-terraform/ecs_customer_service.tf b/aws-fargate-terraform/ecs_customer_service.tf index b5b551c7..2122a679 100644 --- a/aws-fargate-terraform/ecs_customer_service.tf +++ b/aws-fargate-terraform/ecs_customer_service.tf @@ -49,6 +49,7 @@ data "template_file" "customer_task_definition" { eventuate_bootstrap_brokers = "${join(",", sort(split(",", aws_msk_cluster.eventuate.bootstrap_brokers)))}" logs_region = "${var.region}" logs_group = "${aws_cloudwatch_log_group.logs_customer_service.name}" + image_uri = "${aws_ecr_repository.customer.repository_url}" } } diff --git a/aws-fargate-terraform/ecs_order_definition.json b/aws-fargate-terraform/ecs_order_definition.json index 40fe6f45..0c7ece48 100644 --- a/aws-fargate-terraform/ecs_order_definition.json +++ b/aws-fargate-terraform/ecs_order_definition.json @@ -40,7 +40,7 @@ "value": "${db_user}" } ], - "image": "eventuateexamples/eventuate-tram-examples-customers-and-orders-order-service", + "image": "${image_uri}", "essential": true, "name": "order", "healthCheck" : { diff --git a/aws-fargate-terraform/ecs_order_service.tf b/aws-fargate-terraform/ecs_order_service.tf index f25c3a62..fbcbf122 100644 --- a/aws-fargate-terraform/ecs_order_service.tf +++ b/aws-fargate-terraform/ecs_order_service.tf @@ -49,6 +49,7 @@ data "template_file" "order_task_definition" { eventuate_bootstrap_brokers = "${join(",", sort(split(",", aws_msk_cluster.eventuate.bootstrap_brokers)))}" logs_region = "${var.region}" logs_group = "${aws_cloudwatch_log_group.logs_order_service.name}" + image_uri = "${aws_ecr_repository.customer.repository_url}" } } diff --git a/aws-fargate-terraform/ecs_orderhistory_definition.json b/aws-fargate-terraform/ecs_orderhistory_definition.json index 11ddf95a..5c4e3106 100644 --- a/aws-fargate-terraform/ecs_orderhistory_definition.json +++ b/aws-fargate-terraform/ecs_orderhistory_definition.json @@ -44,7 +44,7 @@ "value": "${db_user}" } ], - "image": "eventuateexamples/eventuate-tram-examples-customers-and-orders-order-history-service", + "image": "${image_uri}", "name": "orderhistory", "essential": true, "healthCheck" : { diff --git a/aws-fargate-terraform/ecs_orderhistory_service.tf b/aws-fargate-terraform/ecs_orderhistory_service.tf index 5c6ef6d5..e1db1e02 100644 --- a/aws-fargate-terraform/ecs_orderhistory_service.tf +++ b/aws-fargate-terraform/ecs_orderhistory_service.tf @@ -50,6 +50,7 @@ data "template_file" "orderhistory_task_definition" { logs_region = "${var.region}" logs_group = "${aws_cloudwatch_log_group.logs_orderhistory_service.name}" mongo_uri = "mongodb://${aws_docdb_cluster.docdb_cluster.master_username}:${aws_docdb_cluster.docdb_cluster.master_password}@${aws_docdb_cluster.docdb_cluster.endpoint}/customers_and_orders" + image_uri = "${aws_ecr_repository.customer.repository_url}" } } diff --git a/aws-fargate-terraform/kafka.tf b/aws-fargate-terraform/kafka.tf index 25825ad0..4eb126b2 100644 --- a/aws-fargate-terraform/kafka.tf +++ b/aws-fargate-terraform/kafka.tf @@ -36,7 +36,7 @@ resource "aws_msk_cluster" "eventuate" { resource "aws_msk_configuration" "msk" { kafka_versions = ["2.1.0"] - name = "example" + name = "${var.prefix}-example" server_properties = <