diff --git a/codebase-pipelines/codebuild.tf b/codebase-pipelines/codebuild.tf index 07fd376c..e9042114 100644 --- a/codebase-pipelines/codebuild.tf +++ b/codebase-pipelines/codebuild.tf @@ -3,10 +3,11 @@ data "aws_codestarconnections_connection" "github_codestar_connection" { } resource "aws_codebuild_project" "codebase_image_build" { + for_each = toset(var.image_build ? [""] : []) name = "${var.application}-${var.codebase}-codebase-pipeline-image-build" description = "Publish images on push to ${var.repository}" build_timeout = 30 - service_role = aws_iam_role.codebase_image_build.arn + service_role = aws_iam_role.codebase_image_build[""].arn badge_enabled = true artifacts { @@ -49,8 +50,8 @@ resource "aws_codebuild_project" "codebase_image_build" { logs_config { cloudwatch_logs { - group_name = aws_cloudwatch_log_group.codebase_image_build.name - stream_name = aws_cloudwatch_log_stream.codebase_image_build.name + group_name = aws_cloudwatch_log_group.codebase_image_build[""].name + stream_name = aws_cloudwatch_log_stream.codebase_image_build[""].name } } @@ -70,17 +71,20 @@ resource "aws_codebuild_project" "codebase_image_build" { resource "aws_cloudwatch_log_group" "codebase_image_build" { # checkov:skip=CKV_AWS_338:Retains logs for 3 months instead of 1 year # checkov:skip=CKV_AWS_158:Log groups encrypted using default encryption key instead of KMS CMK + for_each = toset(var.image_build ? [""] : []) name = "codebuild/${var.application}-${var.codebase}-codebase-image-build/log-group" retention_in_days = 90 } resource "aws_cloudwatch_log_stream" "codebase_image_build" { + for_each = toset(var.image_build ? [""] : []) name = "codebuild/${var.application}-${var.codebase}-codebase-image-build/log-stream" - log_group_name = aws_cloudwatch_log_group.codebase_image_build.name + log_group_name = aws_cloudwatch_log_group.codebase_image_build[""].name } resource "aws_codebuild_webhook" "codebuild_webhook" { - project_name = aws_codebuild_project.codebase_image_build.name + for_each = toset(var.image_build ? [""] : []) + project_name = aws_codebuild_project.codebase_image_build[""].name build_type = "BUILD" dynamic "filter_group" { diff --git a/codebase-pipelines/iam.tf b/codebase-pipelines/iam.tf index 819f0b72..644548c1 100644 --- a/codebase-pipelines/iam.tf +++ b/codebase-pipelines/iam.tf @@ -2,6 +2,7 @@ data "aws_caller_identity" "current" {} data "aws_region" "current" {} resource "aws_iam_role" "codebase_image_build" { + for_each = toset(var.image_build ? [""] : []) name = "${var.application}-${var.codebase}-codebase-pipeline-image-build" assume_role_policy = data.aws_iam_policy_document.assume_codebuild_role.json tags = local.tags @@ -21,13 +22,15 @@ data "aws_iam_policy_document" "assume_codebuild_role" { } resource "aws_iam_role_policy_attachment" "ssm_access" { - role = aws_iam_role.codebase_image_build.name + for_each = toset(var.image_build ? [""] : []) + role = aws_iam_role.codebase_image_build[""].name policy_arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess" } resource "aws_iam_role_policy" "log_access_for_codebuild_images" { + for_each = toset(var.image_build ? [""] : []) name = "log-access" - role = aws_iam_role.codebase_image_build.name + role = aws_iam_role.codebase_image_build[""].name policy = data.aws_iam_policy_document.log_access.json } @@ -50,8 +53,9 @@ data "aws_iam_policy_document" "log_access" { } resource "aws_iam_role_policy" "ecr_access_for_codebuild_images" { + for_each = toset(var.image_build ? [""] : []) name = "ecr-access" - role = aws_iam_role.codebase_image_build.name + role = aws_iam_role.codebase_image_build[""].name policy = data.aws_iam_policy_document.ecr_access_for_codebuild_images.json } @@ -122,8 +126,9 @@ data "aws_iam_policy_document" "ecr_access_for_codebuild_images" { } resource "aws_iam_role_policy" "codestar_connection_access_for_codebuild_images" { + for_each = toset(var.image_build ? [""] : []) name = "codestar-connection-policy" - role = aws_iam_role.codebase_image_build.name + role = aws_iam_role.codebase_image_build[""].name policy = data.aws_iam_policy_document.codestar_connection_access.json } diff --git a/codebase-pipelines/tests/unit.tftest.hcl b/codebase-pipelines/tests/unit.tftest.hcl index dc3d31a7..4d3b0f3c 100644 --- a/codebase-pipelines/tests/unit.tftest.hcl +++ b/codebase-pipelines/tests/unit.tftest.hcl @@ -175,117 +175,117 @@ run "test_codebuild_images" { command = plan assert { - condition = aws_codebuild_project.codebase_image_build.name == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_codebuild_project.codebase_image_build[""].name == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: my-app-my-codebase-codebase-pipeline-image-build" } assert { - condition = aws_codebuild_project.codebase_image_build.description == "Publish images on push to my-repository" + condition = aws_codebuild_project.codebase_image_build[""].description == "Publish images on push to my-repository" error_message = "Should be: 'Publish images on push to my-repository'" } assert { - condition = aws_codebuild_project.codebase_image_build.build_timeout == 30 + condition = aws_codebuild_project.codebase_image_build[""].build_timeout == 30 error_message = "Should be: 30" } assert { - condition = one(aws_codebuild_project.codebase_image_build.artifacts).type == "NO_ARTIFACTS" + condition = one(aws_codebuild_project.codebase_image_build[""].artifacts).type == "NO_ARTIFACTS" error_message = "Should be: 'NO_ARTIFACTS'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.cache).type == "LOCAL" + condition = one(aws_codebuild_project.codebase_image_build[""].cache).type == "LOCAL" error_message = "Should be: 'LOCAL'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.cache).modes[0] == "LOCAL_DOCKER_LAYER_CACHE" + condition = one(aws_codebuild_project.codebase_image_build[""].cache).modes[0] == "LOCAL_DOCKER_LAYER_CACHE" error_message = "Should be: 'LOCAL_DOCKER_LAYER_CACHE'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.environment).compute_type == "BUILD_GENERAL1_SMALL" + condition = one(aws_codebuild_project.codebase_image_build[""].environment).compute_type == "BUILD_GENERAL1_SMALL" error_message = "Should be: 'BUILD_GENERAL1_SMALL'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.environment).image == "public.ecr.aws/uktrade/ci-image-builder:tag-latest" + condition = one(aws_codebuild_project.codebase_image_build[""].environment).image == "public.ecr.aws/uktrade/ci-image-builder:tag-latest" 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" + 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(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[1].value == "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 == "ADDITIONAL_ECR_REPOSITORY" + condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].name == "ADDITIONAL_ECR_REPOSITORY" error_message = "Should be: 'ADDITIONAL_ECR_REPOSITORY'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.environment).environment_variable[3].value == "my-additional-repository" + condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].value == "my-additional-repository" error_message = "Should be: 'my-additional-repository'" } assert { - condition = aws_codebuild_project.codebase_image_build.logs_config[0].cloudwatch_logs[ + condition = aws_codebuild_project.codebase_image_build[""].logs_config[0].cloudwatch_logs[ 0 ].group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group" error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'" } assert { - condition = aws_codebuild_project.codebase_image_build.logs_config[0].cloudwatch_logs[ + condition = aws_codebuild_project.codebase_image_build[""].logs_config[0].cloudwatch_logs[ 0 ].stream_name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream" error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-stream'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.source).type == "GITHUB" + condition = one(aws_codebuild_project.codebase_image_build[""].source).type == "GITHUB" error_message = "Should be: 'GITHUB'" } assert { - condition = one(aws_codebuild_project.codebase_image_build.source).location == "https://github.com/my-repository.git" + condition = one(aws_codebuild_project.codebase_image_build[""].source).location == "https://github.com/my-repository.git" error_message = "Should be: 'https://github.com/my-repository.git'" } assert { - condition = length(regexall(".*/work/cli build.*", aws_codebuild_project.codebase_image_build.source[0].buildspec)) > 0 + condition = length(regexall(".*/work/cli build.*", aws_codebuild_project.codebase_image_build[""].source[0].buildspec)) > 0 error_message = "Should contain: '/work/cli build'" } assert { - condition = jsonencode(aws_codebuild_project.codebase_image_build.tags) == jsonencode(var.expected_tags) + condition = jsonencode(aws_codebuild_project.codebase_image_build[""].tags) == jsonencode(var.expected_tags) error_message = "Should be: ${jsonencode(var.expected_tags)}" } # Cloudwatch config: assert { - condition = aws_cloudwatch_log_group.codebase_image_build.name == "codebuild/my-app-my-codebase-codebase-image-build/log-group" + condition = aws_cloudwatch_log_group.codebase_image_build[""].name == "codebuild/my-app-my-codebase-codebase-image-build/log-group" error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'" } assert { - condition = aws_cloudwatch_log_group.codebase_image_build.retention_in_days == 90 + condition = aws_cloudwatch_log_group.codebase_image_build[""].retention_in_days == 90 error_message = "Should be: 90" } assert { - condition = aws_cloudwatch_log_stream.codebase_image_build.name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream" + condition = aws_cloudwatch_log_stream.codebase_image_build[""].name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream" error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-stream'" } assert { - condition = aws_cloudwatch_log_stream.codebase_image_build.log_group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group" + condition = aws_cloudwatch_log_stream.codebase_image_build[""].log_group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group" error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'" } # Webhook config: assert { - condition = aws_codebuild_webhook.codebuild_webhook.project_name == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_codebuild_webhook.codebuild_webhook[""].project_name == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_codebuild_webhook.codebuild_webhook.build_type == "BUILD" + condition = aws_codebuild_webhook.codebuild_webhook[""].build_type == "BUILD" error_message = "Should be: 'BUILD'" } assert { - condition = length(aws_codebuild_webhook.codebuild_webhook.filter_group) == 2 + condition = length(aws_codebuild_webhook.codebuild_webhook[""].filter_group) == 2 error_message = "Should be: 2" } assert { condition = [ - for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true + for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true if[for filter in el.filter : true if filter.type == "EVENT" && filter.pattern == "PUSH"][0] == true ][ 0 @@ -294,6 +294,19 @@ run "test_codebuild_images" { } } +run "test_codebuild_images_disabled" { + command = plan + + variables { + image_build = false + } + # TODO testing when image_build is false, all of the image build stuff isn't created + assert { + condition = length(terraform_data.update_pipeline.triggers_replace) == 3 + error_message = "Should be: 3" + } +} + run "test_main_branch_filter" { command = plan @@ -312,7 +325,7 @@ run "test_main_branch_filter" { assert { condition = [ - for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true + for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true if[ for filter in el.filter : true if filter.type == "HEAD_REF" && filter.pattern == "^refs/heads/main$" @@ -344,7 +357,7 @@ run "test_tagged_branch_filter" { assert { condition = [ - for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true + for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true if[ for filter in el.filter : true if filter.type == "HEAD_REF" && filter.pattern == "^refs/tags/.*" @@ -363,47 +376,47 @@ run "test_iam" { # CodeBuild image build assert { - condition = aws_iam_role.codebase_image_build.name == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_iam_role.codebase_image_build[""].name == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_iam_role.codebase_image_build.assume_role_policy == "{\"Sid\": \"AssumeCodebuildRole\"}" + condition = aws_iam_role.codebase_image_build[""].assume_role_policy == "{\"Sid\": \"AssumeCodebuildRole\"}" error_message = "Should be: {\"Sid\": \"AssumeCodebuildRole\"}" } assert { - condition = jsonencode(aws_iam_role.codebase_image_build.tags) == jsonencode(var.expected_tags) + condition = jsonencode(aws_iam_role.codebase_image_build[""].tags) == jsonencode(var.expected_tags) error_message = "Should be: ${jsonencode(var.expected_tags)}" } assert { - condition = aws_iam_role_policy.log_access_for_codebuild_images.name == "log-access" + condition = aws_iam_role_policy.log_access_for_codebuild_images[""].name == "log-access" error_message = "Should be: 'log-access'" } assert { - condition = aws_iam_role_policy.log_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_iam_role_policy.log_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_iam_role_policy.ecr_access_for_codebuild_images.name == "ecr-access" + condition = aws_iam_role_policy.ecr_access_for_codebuild_images[""].name == "ecr-access" error_message = "Should be: 'ecr-access'" } assert { - condition = aws_iam_role_policy.ecr_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_iam_role_policy.ecr_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images.name == "codestar-connection-policy" + condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images[""].name == "codestar-connection-policy" error_message = "Should be: 'codestar-connection-policy'" } assert { - condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_iam_role_policy_attachment.ssm_access.role == "my-app-my-codebase-codebase-pipeline-image-build" + condition = aws_iam_role_policy_attachment.ssm_access[""].role == "my-app-my-codebase-codebase-pipeline-image-build" error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'" } assert { - condition = aws_iam_role_policy_attachment.ssm_access.policy_arn == "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess" + condition = aws_iam_role_policy_attachment.ssm_access[""].policy_arn == "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess" error_message = "Should be: 'arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess'" } diff --git a/codebase-pipelines/variables.tf b/codebase-pipelines/variables.tf index 0d304470..48f52bde 100644 --- a/codebase-pipelines/variables.tf +++ b/codebase-pipelines/variables.tf @@ -37,3 +37,8 @@ variable "services" { variable "env_config" { type = any } + +variable "image_build" { + type = bool + default = true +}