diff --git a/codebase-pipelines/artifactstore.tf b/codebase-pipelines/artifactstore.tf index 79dbb800..4e5a46ad 100644 --- a/codebase-pipelines/artifactstore.tf +++ b/codebase-pipelines/artifactstore.tf @@ -52,11 +52,16 @@ data "aws_iam_policy_document" "artifact_store_bucket_policy" { statement { effect = "Allow" principals { - type = "AWS" - identifiers = [ - for env in local.pipeline_environments : - "arn:aws:iam::${env.account}:role/${var.application}-${env.name}-codebase-pipeline-deploy" + type = "AWS" + identifiers = [for id in local.deploy_account_ids : "arn:aws:iam::${id}:root"] + } + condition { + test = "ArnLike" + values = [ + for id in local.deploy_account_ids : + "arn:aws:iam::${id}:role/${var.application}-*-codebase-pipeline-deploy" ] + variable = "aws:PrincipalArn" } actions = [ "s3:*" diff --git a/codebase-pipelines/buildspec-deploy.yml b/codebase-pipelines/buildspec-deploy.yml index aa8ddf01..eb51f653 100644 --- a/codebase-pipelines/buildspec-deploy.yml +++ b/codebase-pipelines/buildspec-deploy.yml @@ -18,9 +18,10 @@ phases: - set -e # Check if the specified image tag exists + - aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com - | - if ! aws ecr describe-images --repository-name "${REPOSITORY_NAME}" --image-ids "imageTag=${IMAGE_TAG}" > /dev/null 2>&1; then - echo "Error: image tag ${IMAGE_TAG} not found in repository ${REPOSITORY_NAME}" + if ! docker manifest inspect "${REPOSITORY_URL}:${IMAGE_TAG}" > /dev/null 2>&1; then + echo "Error: image tag ${IMAGE_TAG} not found in repository ${REPOSITORY_URL}" exit 1 fi @@ -31,9 +32,6 @@ phases: exit 1 fi - # Extract timestamp from image config and check if it exists - - aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com - # Construct Slack message env vars - SLACK_REF=$(regctl image config "${REPOSITORY_URL}:${IMAGE_TAG}" | jq -r '.config.Labels."uk.gov.trade.digital.build.timestamp"') - | diff --git a/codebase-pipelines/codepipeline.tf b/codebase-pipelines/codepipeline.tf index f8209972..de4ccc23 100644 --- a/codebase-pipelines/codepipeline.tf +++ b/codebase-pipelines/codepipeline.tf @@ -80,9 +80,7 @@ resource "aws_codepipeline" "codebase_pipeline" { { name : "ENVIRONMENT", value : stage.value.name }, { name : "IMAGE_TAG", value : "#{variables.IMAGE_TAG}" }, { name : "PIPELINE_EXECUTION_ID", value : "#{codepipeline.PipelineExecutionId}" }, - { name : "PREFIXED_REPOSITORY_NAME", value : local.prefixed_repository_name }, { name : "REPOSITORY_URL", value : local.repository_url }, - { name : "REPOSITORY_NAME", value : local.ecr_name }, { name : "SERVICE", value : action.value.name }, { name : "SLACK_CHANNEL_ID", value : var.slack_channel, type : "PARAMETER_STORE" }, ]) @@ -168,9 +166,7 @@ resource "aws_codepipeline" "manual_release_pipeline" { { name : "ENVIRONMENT", value : "#{variables.ENVIRONMENT}" }, { name : "IMAGE_TAG", value : "#{variables.IMAGE_TAG}" }, { name : "PIPELINE_EXECUTION_ID", value : "#{codepipeline.PipelineExecutionId}" }, - { name : "PREFIXED_REPOSITORY_NAME", value : local.prefixed_repository_name }, { name : "REPOSITORY_URL", value : local.repository_url }, - { name : "REPOSITORY_NAME", value : local.ecr_name }, { name : "SERVICE", value : action.value.name }, { name : "SLACK_CHANNEL_ID", value : var.slack_channel, type : "PARAMETER_STORE" }, ]) diff --git a/codebase-pipelines/eventbridge.tf b/codebase-pipelines/eventbridge.tf index 757da703..ff8bd429 100644 --- a/codebase-pipelines/eventbridge.tf +++ b/codebase-pipelines/eventbridge.tf @@ -19,19 +19,21 @@ resource "aws_cloudwatch_event_target" "codepipeline" { for_each = local.pipeline_map rule = aws_cloudwatch_event_rule.ecr_image_publish[each.key].name arn = aws_codepipeline.codebase_pipeline[each.key].arn - role_arn = aws_iam_role.event_bridge_pipeline_trigger.arn + role_arn = aws_iam_role.event_bridge_pipeline_trigger[""].arn } resource "aws_iam_role" "event_bridge_pipeline_trigger" { + for_each = toset(length(local.pipeline_map) > 0 ? [""] : []) name = "${var.application}-${var.codebase}-event-bridge-pipeline-trigger" assume_role_policy = data.aws_iam_policy_document.assume_event_bridge_policy.json tags = local.tags } resource "aws_iam_role_policy" "event_bridge_pipeline_trigger" { - name = "event-bridge-access" - role = aws_iam_role.event_bridge_pipeline_trigger.name - policy = data.aws_iam_policy_document.event_bridge_pipeline_trigger.json + for_each = toset(length(local.pipeline_map) > 0 ? [""] : []) + name = "event-bridge-access" + role = aws_iam_role.event_bridge_pipeline_trigger[""].name + policy = data.aws_iam_policy_document.event_bridge_pipeline_trigger.json } data "aws_iam_policy_document" "assume_event_bridge_policy" { diff --git a/codebase-pipelines/iam.tf b/codebase-pipelines/iam.tf index f4cbe488..147590fd 100644 --- a/codebase-pipelines/iam.tf +++ b/codebase-pipelines/iam.tf @@ -73,32 +73,6 @@ data "aws_iam_policy_document" "ecr_access_for_codebuild_images" { ] } - statement { - effect = "Allow" - actions = [ - "ecr-public:DescribeImageScanFindings", - "ecr-public:GetLifecyclePolicyPreview", - "ecr-public:GetDownloadUrlForLayer", - "ecr-public:BatchGetImage", - "ecr-public:DescribeImages", - "ecr-public:ListTagsForResource", - "ecr-public:BatchCheckLayerAvailability", - "ecr-public:GetLifecyclePolicy", - "ecr-public:GetRepositoryPolicy", - "ecr-public:PutImage", - "ecr-public:InitiateLayerUpload", - "ecr-public:UploadLayerPart", - "ecr-public:CompleteLayerUpload", - "ecr-public:BatchDeleteImage", - "ecr-public:DescribeRepositories", - "ecr-public:ListImages" - ] - resources = [ - # We have to wildcard the repository name because we currently expect the repository URL and it's not possible to get the ARN from that - "arn:aws:ecr-public::${data.aws_caller_identity.current.account_id}:repository/*" - ] - } - statement { effect = "Allow" actions = [ @@ -119,9 +93,40 @@ data "aws_iam_policy_document" "ecr_access_for_codebuild_images" { "ecr:DescribeRepositories", "ecr:ListImages" ] - resources = [ - aws_ecr_repository.this.arn - ] + resources = compact([ + "arn:aws:ecr:${local.account_region}:repository/${local.ecr_name}", + local.additional_private_repo_arn + ]) + } + + dynamic "statement" { + for_each = toset(local.is_additional_repo_public ? [""] : []) + + content { + effect = "Allow" + actions = [ + "ecr-public:DescribeImageScanFindings", + "ecr-public:GetLifecyclePolicyPreview", + "ecr-public:GetDownloadUrlForLayer", + "ecr-public:BatchGetImage", + "ecr-public:DescribeImages", + "ecr-public:ListTagsForResource", + "ecr-public:BatchCheckLayerAvailability", + "ecr-public:GetLifecyclePolicy", + "ecr-public:GetRepositoryPolicy", + "ecr-public:PutImage", + "ecr-public:InitiateLayerUpload", + "ecr-public:UploadLayerPart", + "ecr-public:CompleteLayerUpload", + "ecr-public:BatchDeleteImage", + "ecr-public:DescribeRepositories", + "ecr-public:ListImages" + ] + resources = [ + # We have to wildcard the repository name because we currently expect the repository URL and it's not possible to get the ARN from that + "arn:aws:ecr-public::${data.aws_caller_identity.current.account_id}:repository/*" + ] + } } } @@ -184,9 +189,10 @@ data "aws_iam_policy_document" "ecr_access_for_codebase_pipeline" { "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer" ] - resources = [ - aws_ecr_repository.this.arn - ] + resources = compact([ + "arn:aws:ecr:${local.account_region}:repository/${local.ecr_name}", + local.additional_private_repo_arn + ]) } statement { effect = "Allow" diff --git a/codebase-pipelines/locals.tf b/codebase-pipelines/locals.tf index 266128d7..4caaf426 100644 --- a/codebase-pipelines/locals.tf +++ b/codebase-pipelines/locals.tf @@ -7,9 +7,12 @@ locals { account_region = "${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}" - ecr_name = "${var.application}/${var.codebase}" - prefixed_repository_name = "uktrade/${var.application}" - repository_url = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/${local.ecr_name}" + ecr_name = "${var.application}/${var.codebase}" + private_repo_url = "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com" + is_additional_repo_public = var.additional_ecr_repository != null ? strcontains(var.additional_ecr_repository, "public.ecr.aws") : false + additional_ecr_url = var.additional_ecr_repository != null ? local.is_additional_repo_public ? var.additional_ecr_repository : "${local.private_repo_url}/${var.additional_ecr_repository}" : null + repository_url = coalesce(local.additional_ecr_url, "${local.private_repo_url}/${local.ecr_name}") + additional_private_repo_arn = var.additional_ecr_repository != null && !local.is_additional_repo_public ? "arn:aws:ecr:${local.account_region}:repository/${var.additional_ecr_repository}" : "" pipeline_branches = distinct([ for pipeline in var.pipelines : pipeline.branch if lookup(pipeline, "branch", null) != null @@ -33,10 +36,6 @@ locals { }) } - pipeline_environments = distinct(flatten([ - for pipeline in local.pipeline_map : [for env in pipeline.environments : env] - ])) - services = sort(flatten([ for run_group in var.services : [for service in flatten(values(run_group)) : service] ])) diff --git a/codebase-pipelines/tests/unit.tftest.hcl b/codebase-pipelines/tests/unit.tftest.hcl index 0f22ba44..85669b02 100644 --- a/codebase-pipelines/tests/unit.tftest.hcl +++ b/codebase-pipelines/tests/unit.tftest.hcl @@ -63,6 +63,13 @@ override_data { } } +override_data { + target = data.aws_iam_policy_document.ecr_access_for_codebase_pipeline + values = { + json = "{\"Sid\": \"PipelineECRAccess\"}" + } +} + variables { env_config = { "*" = { @@ -84,10 +91,9 @@ variables { } } } - application = "my-app" - codebase = "my-codebase" - repository = "my-repository" - additional_ecr_repository = "my-additional-repository" + application = "my-app" + codebase = "my-codebase" + repository = "my-repository" services = [ { "run_group_1" : [ @@ -171,9 +177,21 @@ run "test_artifact_store" { error_message = "Should be: AWS" } assert { - condition = flatten([for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].principals : el.identifiers]) == ["arn:aws:iam::000123456789:role/my-app-dev-codebase-pipeline-deploy", "arn:aws:iam::000123456789:role/my-app-staging-codebase-pipeline-deploy", "arn:aws:iam::123456789000:role/my-app-prod-codebase-pipeline-deploy"] + condition = flatten([for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].principals : el.identifiers]) == ["arn:aws:iam::000123456789:root", "arn:aws:iam::123456789000:root"] error_message = "Bucket policy principals incorrect" } + assert { + condition = one([for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].condition : el.test]) == "ArnLike" + error_message = "Bucket policy condition incorrect" + } + assert { + condition = one([for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].condition : el.variable]) == "aws:PrincipalArn" + error_message = "Bucket policy condition incorrect" + } + assert { + condition = flatten([for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].condition : el.values]) == ["arn:aws:iam::000123456789:role/my-app-*-codebase-pipeline-deploy", "arn:aws:iam::123456789000:role/my-app-*-codebase-pipeline-deploy"] + error_message = "Bucket policy condition incorrect" + } assert { condition = [for el in data.aws_iam_policy_document.artifact_store_bucket_policy.statement[1].actions : el][0] == "s3:*" error_message = "Should be: s3:*" @@ -216,29 +234,15 @@ run "test_codebuild_images" { error_message = "Should be: 'public.ecr.aws/uktrade/ci-image-builder:tag-latest'" } assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[1].name == "ECR_REPOSITORY" - error_message = "Should be: 'ECR_REPOSITORY'" - } - assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[1].value == "my-app/my-codebase" + condition = one([for var in one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable : + var.value if var.name == "ECR_REPOSITORY"]) == "my-app/my-codebase" error_message = "Should be: 'my-app/my-codebase'" } assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].name == "SLACK_CHANNEL_ID" - error_message = "Should be: 'SLACK_CHANNEL_ID'" - } - assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].value == "/fake/slack/channel" + condition = one([for var in one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable : + var.value if var.name == "SLACK_CHANNEL_ID"]) == "/fake/slack/channel" error_message = "Should be: '/fake/slack/channel'" } - assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[4].name == "ADDITIONAL_ECR_REPOSITORY" - error_message = "Should be: 'ADDITIONAL_ECR_REPOSITORY'" - } - assert { - condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[4].value == "my-additional-repository" - error_message = "Should be: 'my-additional-repository'" - } assert { condition = aws_codebuild_project.codebase_image_build[""].logs_config[0].cloudwatch_logs[ 0 @@ -340,7 +344,7 @@ run "test_codebuild_images_not_required" { } assert { condition = aws_cloudwatch_event_rule.ecr_image_publish[0].event_pattern == "{\"detail\":{\"action-type\":[\"PUSH\"],\"image-tag\":[\"latest\"],\"repository-name\":[\"my-app/my-codebase\"],\"result\":[\"SUCCESS\"]},\"detail-type\":[\"ECR Image Action\"],\"source\":[\"aws.ecr\"]}" - error_message = "Event pattern is incorrect ${jsonencode(aws_cloudwatch_event_rule.ecr_image_publish[0].event_pattern)}" + error_message = "Event pattern is incorrect" } assert { condition = aws_cloudwatch_event_rule.ecr_image_publish[1].event_pattern == "{\"detail\":{\"action-type\":[\"PUSH\"],\"image-tag\":[\"latest\"],\"repository-name\":[\"my-app/my-codebase\"],\"result\":[\"SUCCESS\"]},\"detail-type\":[\"ECR Image Action\"],\"source\":[\"aws.ecr\"]}" @@ -348,6 +352,113 @@ run "test_codebuild_images_not_required" { } } +run "test_additional_private_ecr_repository" { + command = plan + + variables { + additional_ecr_repository = "repository-namespace/repository-name" + } + + assert { + condition = local.is_additional_repo_public == false + error_message = "Should be: false" + } + assert { + condition = one([for var in one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable : + var.value if var.name == "ADDITIONAL_ECR_REPOSITORY"]) == "repository-namespace/repository-name" + error_message = "Should be: repository-namespace/repository-name" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/repository-namespace/repository-name" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/repository-namespace/repository-name" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].resources == toset([ + "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/my-app/my-codebase", + "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/repository-namespace/repository-name" + ]) + error_message = "Unexpected resources" + } + assert { + condition = length(data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].resources) == 2 + error_message = "Unexpected resources" + } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebase_pipeline.statement[0].resources == toset([ + "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/my-app/my-codebase", + "arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/repository-namespace/repository-name" + ]) + error_message = "Unexpected resources" + } + assert { + condition = length(data.aws_iam_policy_document.ecr_access_for_codebase_pipeline.statement[0].resources) == 2 + error_message = "Unexpected resources" + } +} + +run "test_additional_ecr_repository_public" { + command = plan + + variables { + additional_ecr_repository = "public.ecr.aws/repository-namespace/repository-name" + } + + assert { + condition = local.is_additional_repo_public == true + error_message = "Should be: true" + } + assert { + condition = one([for var in one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable : + var.value if var.name == "ADDITIONAL_ECR_REPOSITORY"]) == "public.ecr.aws/repository-namespace/repository-name" + error_message = "Should be: 'public.ecr.aws/repository-namespace/repository-name'" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "public.ecr.aws/repository-namespace/repository-name" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "public.ecr.aws/repository-namespace/repository-name" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[2].effect == "Allow" + error_message = "Should be: Allow" + } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[2].actions == toset([ + "ecr-public:DescribeImageScanFindings", + "ecr-public:GetLifecyclePolicyPreview", + "ecr-public:GetDownloadUrlForLayer", + "ecr-public:BatchGetImage", + "ecr-public:DescribeImages", + "ecr-public:ListTagsForResource", + "ecr-public:BatchCheckLayerAvailability", + "ecr-public:GetLifecyclePolicy", + "ecr-public:GetRepositoryPolicy", + "ecr-public:PutImage", + "ecr-public:InitiateLayerUpload", + "ecr-public:UploadLayerPart", + "ecr-public:CompleteLayerUpload", + "ecr-public:BatchDeleteImage", + "ecr-public:DescribeRepositories", + "ecr-public:ListImages" + ]) + error_message = "Unexpected actions" + } + assert { + condition = one(data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[2].resources) == "arn:aws:ecr-public::${data.aws_caller_identity.current.account_id}:repository/*" + error_message = "Unexpected resources" + } +} + run "test_main_branch_filter" { command = plan @@ -619,35 +730,6 @@ run "test_iam_documents" { } assert { condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].actions == toset([ - "ecr-public:DescribeImageScanFindings", - "ecr-public:GetLifecyclePolicyPreview", - "ecr-public:GetDownloadUrlForLayer", - "ecr-public:BatchGetImage", - "ecr-public:DescribeImages", - "ecr-public:ListTagsForResource", - "ecr-public:BatchCheckLayerAvailability", - "ecr-public:GetLifecyclePolicy", - "ecr-public:GetRepositoryPolicy", - "ecr-public:PutImage", - "ecr-public:InitiateLayerUpload", - "ecr-public:UploadLayerPart", - "ecr-public:CompleteLayerUpload", - "ecr-public:BatchDeleteImage", - "ecr-public:DescribeRepositories", - "ecr-public:ListImages" - ]) - error_message = "Unexpected actions" - } - assert { - condition = one(data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].resources) == "arn:aws:ecr-public::${data.aws_caller_identity.current.account_id}:repository/*" - error_message = "Unexpected resources" - } - assert { - condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[2].effect == "Allow" - error_message = "Should be: Allow" - } - assert { - condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[2].actions == toset([ "ecr:DescribeImageScanFindings", "ecr:GetLifecyclePolicyPreview", "ecr:GetDownloadUrlForLayer", @@ -667,6 +749,14 @@ run "test_iam_documents" { ]) error_message = "Unexpected actions" } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].resources == toset(["arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/my-app/my-codebase"]) + error_message = "Unexpected resources" + } + assert { + condition = length(data.aws_iam_policy_document.ecr_access_for_codebuild_images.statement[1].resources) == 1 + error_message = "Unexpected resources" + } # Codestar connection assert { @@ -771,13 +861,20 @@ run "test_iam_documents" { ]) error_message = "Unexpected actions" } + assert { + condition = data.aws_iam_policy_document.ecr_access_for_codebase_pipeline.statement[0].resources == toset(["arn:aws:ecr:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:repository/my-app/my-codebase"]) + error_message = "Unexpected resources" + } + assert { + condition = length(data.aws_iam_policy_document.ecr_access_for_codebase_pipeline.statement[0].resources) == 1 + error_message = "Unexpected resources" + } # SSM access assert { condition = data.aws_iam_policy_document.deploy_ssm_access.statement[0].effect == "Allow" error_message = "Should be: Allow" } - assert { condition = data.aws_iam_policy_document.deploy_ssm_access.statement[0].actions == toset([ "ssm:GetParameter", @@ -785,7 +882,6 @@ run "test_iam_documents" { ]) error_message = "Unexpected actions" } - assert { condition = one(data.aws_iam_policy_document.deploy_ssm_access.statement[0].resources) == "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/codebuild/slack_*" error_message = "Unexpected resources" @@ -838,7 +934,7 @@ run "test_codebuild_deploy" { } assert { condition = one(aws_codebuild_project.codebase_deploy.environment).environment_variable[0].name == "ENV_CONFIG" - error_message = "Should be: 'ENV_CONFIG' ${jsonencode(one(aws_codebuild_project.codebase_deploy.environment).environment_variable[0])}" + error_message = "Should be: 'ENV_CONFIG'" } assert { condition = one(aws_codebuild_project.codebase_deploy.environment).environment_variable[0].value == "{\"dev\":{\"account\":\"000123456789\"},\"prod\":{\"account\":\"123456789000\"},\"staging\":{\"account\":\"000123456789\"}}" @@ -1005,12 +1101,56 @@ run "test_main_pipeline" { condition = aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.ProjectName == "my-app-my-codebase-codebase-pipeline-deploy" error_message = "Should be: my-app-my-codebase-codebase-pipeline-deploy" } - assert { - condition = aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"dev\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-1\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "APPLICATION"]) == "my-app" + error_message = "APPLICATION environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "AWS_REGION"]) == "${data.aws_region.current.name}" + error_message = "AWS_REGION environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "AWS_ACCOUNT_ID"]) == "${data.aws_caller_identity.current.account_id}" + error_message = "AWS_ACCOUNT_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "dev" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "IMAGE_TAG"]) == "#{variables.IMAGE_TAG}" + error_message = "IMAGE_TAG environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "PIPELINE_EXECUTION_ID"]) == "#{codepipeline.PipelineExecutionId}" + error_message = "PIPELINE_EXECUTION_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-1" + error_message = "SERVICE environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "SLACK_CHANNEL_ID"]) == "/fake/slack/channel" + error_message = "SLACK_CHANNEL_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[0].configuration.EnvironmentVariables) : + var.type if var.name == "SLACK_CHANNEL_ID"]) == "PARAMETER_STORE" + error_message = "SLACK_CHANNEL_ID environment variable type is incorrect" } - assert { condition = aws_codepipeline.codebase_pipeline[0].stage[1].action[0].run_order == 2 error_message = "Run order incorrect" @@ -1046,10 +1186,15 @@ run "test_main_pipeline" { error_message = "Should be: my-app-my-codebase-codebase-pipeline-deploy" } assert { - condition = aws_codepipeline.codebase_pipeline[0].stage[1].action[1].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"dev\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-2\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "dev" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[0].stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-2" + error_message = "SERVICE environment variable incorrect" } - assert { condition = aws_codepipeline.codebase_pipeline[0].stage[1].action[1].run_order == 3 error_message = "Run order incorrect" @@ -1084,10 +1229,15 @@ run "test_tagged_pipeline" { error_message = "Should be: service-1" } assert { - condition = aws_codepipeline.codebase_pipeline[1].stage[1].action[0].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"staging\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-1\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "staging" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-1" + error_message = "SERVICE environment variable incorrect" } - assert { condition = aws_codepipeline.codebase_pipeline[1].stage[1].action[0].run_order == 2 error_message = "Run order incorrect" @@ -1096,11 +1246,17 @@ run "test_tagged_pipeline" { # Deploy service-2 action assert { condition = aws_codepipeline.codebase_pipeline[1].stage[1].action[1].name == "service-2" - error_message = "Should be: service-1" + error_message = "Should be: service-2" } assert { - condition = aws_codepipeline.codebase_pipeline[1].stage[1].action[1].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"staging\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-2\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "staging" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-2" + error_message = "SERVICE environment variable incorrect" } assert { condition = aws_codepipeline.codebase_pipeline[1].stage[1].action[1].run_order == 3 @@ -1145,8 +1301,14 @@ run "test_tagged_pipeline" { error_message = "Should be: service-1" } assert { - condition = aws_codepipeline.codebase_pipeline[1].stage[2].action[1].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"prod\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-1\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[2].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "prod" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[2].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-1" + error_message = "SERVICE environment variable incorrect" } assert { condition = aws_codepipeline.codebase_pipeline[1].stage[2].action[1].run_order == 2 @@ -1159,8 +1321,14 @@ run "test_tagged_pipeline" { error_message = "Should be: service-1" } assert { - condition = aws_codepipeline.codebase_pipeline[1].stage[2].action[2].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"prod\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-2\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[2].action[2].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "prod" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.codebase_pipeline[1].stage[2].action[2].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-2" + error_message = "SERVICE environment variable incorrect" } assert { condition = aws_codepipeline.codebase_pipeline[1].stage[2].action[2].run_order == 3 @@ -1298,8 +1466,54 @@ run "test_manual_release_pipeline" { error_message = "Should be: my-app-my-codebase-codebase-pipeline-deploy" } assert { - condition = aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"#{variables.ENVIRONMENT}\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-1\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "APPLICATION"]) == "my-app" + error_message = "APPLICATION environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "AWS_REGION"]) == "${data.aws_region.current.name}" + error_message = "AWS_REGION environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "AWS_ACCOUNT_ID"]) == "${data.aws_caller_identity.current.account_id}" + error_message = "AWS_ACCOUNT_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "#{variables.ENVIRONMENT}" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "IMAGE_TAG"]) == "#{variables.IMAGE_TAG}" + error_message = "IMAGE_TAG environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "PIPELINE_EXECUTION_ID"]) == "#{codepipeline.PipelineExecutionId}" + error_message = "PIPELINE_EXECUTION_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "REPOSITORY_URL"]) == "${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase" + error_message = "REPOSITORY_URL environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-1" + error_message = "SERVICE environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.value if var.name == "SLACK_CHANNEL_ID"]) == "/fake/slack/channel" + error_message = "SLACK_CHANNEL_ID environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[0].configuration.EnvironmentVariables) : + var.type if var.name == "SLACK_CHANNEL_ID"]) == "PARAMETER_STORE" + error_message = "SLACK_CHANNEL_ID environment variable type is incorrect" } assert { condition = aws_codepipeline.manual_release_pipeline.stage[1].action[0].run_order == 2 @@ -1336,8 +1550,14 @@ run "test_manual_release_pipeline" { error_message = "Should be: my-app-my-codebase-codebase-pipeline-deploy" } assert { - condition = aws_codepipeline.manual_release_pipeline.stage[1].action[1].configuration.EnvironmentVariables == "[{\"name\":\"APPLICATION\",\"value\":\"my-app\"},{\"name\":\"AWS_REGION\",\"value\":\"${data.aws_region.current.name}\"},{\"name\":\"AWS_ACCOUNT_ID\",\"value\":\"${data.aws_caller_identity.current.account_id}\"},{\"name\":\"ENVIRONMENT\",\"value\":\"#{variables.ENVIRONMENT}\"},{\"name\":\"IMAGE_TAG\",\"value\":\"#{variables.IMAGE_TAG}\"},{\"name\":\"PIPELINE_EXECUTION_ID\",\"value\":\"#{codepipeline.PipelineExecutionId}\"},{\"name\":\"PREFIXED_REPOSITORY_NAME\",\"value\":\"uktrade/my-app\"},{\"name\":\"REPOSITORY_URL\",\"value\":\"${data.aws_caller_identity.current.account_id}.dkr.ecr.${data.aws_region.current.name}.amazonaws.com/my-app/my-codebase\"},{\"name\":\"REPOSITORY_NAME\",\"value\":\"my-app/my-codebase\"},{\"name\":\"SERVICE\",\"value\":\"service-2\"},{\"name\":\"SLACK_CHANNEL_ID\",\"type\":\"PARAMETER_STORE\",\"value\":\"/fake/slack/channel\"}]" - error_message = "Configuration environment variables incorrect" + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "ENVIRONMENT"]) == "#{variables.ENVIRONMENT}" + error_message = "ENVIRONMENT environment variable incorrect" + } + assert { + condition = one([for var in jsondecode(aws_codepipeline.manual_release_pipeline.stage[1].action[1].configuration.EnvironmentVariables) : + var.value if var.name == "SERVICE"]) == "service-2" + error_message = "SERVICE environment variable incorrect" } assert { condition = aws_codepipeline.manual_release_pipeline.stage[1].action[1].run_order == 3 @@ -1386,27 +1606,27 @@ run "test_event_bridge" { # IAM roles assert { - condition = aws_iam_role.event_bridge_pipeline_trigger.name == "my-app-my-codebase-event-bridge-pipeline-trigger" + condition = aws_iam_role.event_bridge_pipeline_trigger[""].name == "my-app-my-codebase-event-bridge-pipeline-trigger" error_message = "Should be: 'my-app-my-codebase-event-bridge-pipeline-trigger'" } assert { - condition = aws_iam_role.event_bridge_pipeline_trigger.assume_role_policy == "{\"Sid\": \"AssumeEventBridge\"}" + condition = aws_iam_role.event_bridge_pipeline_trigger[""].assume_role_policy == "{\"Sid\": \"AssumeEventBridge\"}" error_message = "Should be: {\"Sid\": \"AssumeEventBridge\"}" } assert { - condition = jsonencode(aws_iam_role.event_bridge_pipeline_trigger.tags) == jsonencode(var.expected_tags) + condition = jsonencode(aws_iam_role.event_bridge_pipeline_trigger[""].tags) == jsonencode(var.expected_tags) error_message = "Should be: ${jsonencode(var.expected_tags)}" } assert { - condition = aws_iam_role_policy.event_bridge_pipeline_trigger.name == "event-bridge-access" + condition = aws_iam_role_policy.event_bridge_pipeline_trigger[""].name == "event-bridge-access" error_message = "Should be: 'event-bridge-access'" } assert { - condition = aws_iam_role_policy.event_bridge_pipeline_trigger.role == "my-app-my-codebase-event-bridge-pipeline-trigger" + condition = aws_iam_role_policy.event_bridge_pipeline_trigger[""].role == "my-app-my-codebase-event-bridge-pipeline-trigger" error_message = "Should be: 'my-app-my-codebase-event-bridge-pipeline-trigger'" } assert { - condition = aws_iam_role_policy.event_bridge_pipeline_trigger.policy == "{\"Sid\": \"EventBridgePipelineTrigger\"}" + condition = aws_iam_role_policy.event_bridge_pipeline_trigger[""].policy == "{\"Sid\": \"EventBridgePipelineTrigger\"}" error_message = "Unexpected policy" } diff --git a/codebase-pipelines/variables.tf b/codebase-pipelines/variables.tf index e0974afb..0481c442 100644 --- a/codebase-pipelines/variables.tf +++ b/codebase-pipelines/variables.tf @@ -11,7 +11,8 @@ variable "repository" { } variable "additional_ecr_repository" { - type = string + type = string + default = null } variable "pipelines" {