1-bootstrap/tf_image.tf (94 lines of code) (raw):

/** * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ locals { docker_tag_version_terraform = "v1" } data "google_project" "project" { project_id = var.project_id } resource "google_artifact_registry_repository" "tf_image" { project = var.project_id location = var.location repository_id = "terraform-image" description = "Terraform Image Docker repository" format = "DOCKER" } resource "google_service_account" "builder" { project = var.project_id account_id = "tf-builder" } resource "google_storage_bucket" "build_logs" { name = "cb-tf-builder-logs-${var.project_id}" project = var.project_id uniform_bucket_level_access = true force_destroy = var.bucket_force_destroy location = var.location } # IAM Roles required to build the terraform image on Google Cloud Build resource "google_storage_bucket_iam_member" "builder_admin" { member = google_service_account.builder.member bucket = google_storage_bucket.build_logs.name role = "roles/storage.admin" } resource "google_project_iam_member" "builder_object_user" { member = google_service_account.builder.member project = var.project_id role = "roles/storage.objectUser" } resource "google_artifact_registry_repository_iam_member" "builder" { project = google_artifact_registry_repository.tf_image.project location = google_artifact_registry_repository.tf_image.location repository = google_artifact_registry_repository.tf_image.name role = "roles/artifactregistry.repoAdmin" member = google_service_account.builder.member } resource "google_project_iam_member" "tf_workerpool_user" { for_each = toset([ "serviceAccount:${data.google_project.project.number}@cloudbuild.gserviceaccount.com", google_service_account.builder.member ] ) member = each.value project = local.worker_pool_project role = "roles/cloudbuild.workerPoolUser" } resource "time_sleep" "wait_iam_propagation" { create_duration = "60s" depends_on = [ google_project_iam_member.tf_workerpool_user, google_artifact_registry_repository_iam_member.builder, google_storage_bucket_iam_member.builder_admin, google_project_iam_member.builder_object_user, ] } # Use Dockerfile to create the custom Terraform Image on Google Cloud Build module "build_terraform_image" { source = "terraform-google-modules/gcloud/google" version = "~> 3.1" upgrade = false create_cmd_triggers = { "tag_version" = local.docker_tag_version_terraform } create_cmd_entrypoint = "bash" create_cmd_body = "gcloud builds submit --tag ${var.location}-docker.pkg.dev/${var.project_id}/${google_artifact_registry_repository.tf_image.name}/terraform:${local.docker_tag_version_terraform} --project=${var.project_id} --service-account=${google_service_account.builder.id} --gcs-log-dir=${google_storage_bucket.build_logs.url} --worker-pool=${var.workerpool_id} || ( sleep 45 && gcloud builds submit --tag ${var.location}-docker.pkg.dev/${var.project_id}/${google_artifact_registry_repository.tf_image.name}/terraform:${local.docker_tag_version_terraform} --project=${var.project_id} --service-account=${google_service_account.builder.id} --gcs-log-dir=${google_storage_bucket.build_logs.url} --worker-pool=${var.workerpool_id} )" module_depends_on = [time_sleep.wait_iam_propagation] } # Allow infrastructure pipeline service accounts to download the image resource "google_artifact_registry_repository_iam_member" "terraform_sa_artifact_registry_reader" { for_each = module.tf_cloudbuild_workspace project = var.project_id location = var.location repository = google_artifact_registry_repository.tf_image.name role = "roles/artifactregistry.reader" member = "serviceAccount:${reverse(split("/", each.value.cloudbuild_sa))[0]}" }