hashicorp / terraform-provider-google

Terraform Provider for Google Cloud Platform
https://registry.terraform.io/providers/hashicorp/google/latest/docs
Mozilla Public License 2.0
2.35k stars 1.75k forks source link

Project ID Not Respected In google_cloudbuild_trigger #11255

Closed clive-h-townsend closed 4 months ago

clive-h-townsend commented 2 years ago

Community Note

Terraform Version

Affected Resource(s)

google-beta provider and specifically google_cloudbuild_trigger

Terraform Configuration Files

variable "project_name" {
  default = "XX-test"
}

resource "random_id" "id" {
  byte_length = 4
}

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.0.0"
    }
  }
  backend "gcs" {
    bucket = "XXXXXXXXf"
    prefix = "terraform/state"
  }
}

provider "google" {
  credentials = file("terraform-sa-cred.json")
}

provider "google-beta" {
  credentials = file("terraform-sa-cred.json")
}

resource "google_folder" "testing" {
  display_name = "Testing"
  parent       = "organizations/XXXXXXXX"
}

resource "google_project" "project" {
  name            = format("%s-%s", var.project_name, random_id.id.hex)
  project_id      = format("%s-%s", var.project_name, random_id.id.hex)
  folder_id       = google_folder.testing.name
  billing_account = "XXXXXX-XXXXXX-XXXXXX"
}

resource "google_app_engine_application" "app" {
  project       = google_project.project.project_id
  location_id   = "us-central"
  database_type = "CLOUD_FIRESTORE"
}

resource "google_project_service" "cloud_firestore" {
  project = google_project.project.project_id
  service = "firestore.googleapis.com"
} 

resource "google_firebase_project" "default" {
  provider = google-beta
  project  = google_project.project.project_id
}

resource "google_firebase_web_app" "default" {
  provider     = google-beta
  project      = google_project.project.project_id
  display_name = "Testing App"
  depends_on   = [google_firebase_project.default]
}

data "google_firebase_web_app_config" "basic" {
  provider   = google-beta
  web_app_id = google_firebase_web_app.default.app_id
  project    = google_project.project.project_id
}
resource "google_storage_bucket" "webApp" {
  provider = google-beta
  name     = format("fb-webapp-%s-%s", var.project_name, random_id.id.hex)
  location = "US"
  project  = google_project.project.project_id

}

resource "google_storage_bucket_object" "default" {
  provider = google-beta
  bucket   = google_storage_bucket.webApp.name
  name     = "firebase-config.json"
}

resource "google_storage_object_access_control" "public_env" {
  object = google_storage_bucket_object.config_info.name
  bucket = google_storage_bucket.webApp.name
  role = "READER"
  entity= "allUsers"
}

resource "google_project_service" "secret_manager" {
  project = google_project.project.project_id
  service = "secretmanager.googleapis.com"
} 

resource "google_secret_manager_secret" "algolia_id" {
    secret_id = "algolia_id"
    project = google_project.project.project_id
    replication {
      automatic = true
    }
    depends_on = [google_project_service.secret_manager]
}

resource "google_secret_manager_secret" "stripe_public_key" {
    secret_id = "stripe_public_key"
    project = google_project.project.project_id
    replication {
      automatic = true
    }
    depends_on = [google_project_service.secret_manager]
}

resource "google_project_service" "cloud_build" {
  project = google_project.project.project_id
  service = "cloudbuild.googleapis.com"
} 
resource "google_project_service" "container_registry" {
  project = google_project.project.project_id
  service = "containerregistry.googleapis.com"
} 

resource "google_cloudbuild_trigger" "build-trigger" {
  project = google_project.project.project_id
  depends_on = [
    google_project_service.cloud_build
  ]
  provider = "google-beta"
  name = "Deploy test"
  description = "A deployment of the Platform"

  github {
    push {
      branch = "staging"
    }

  }
  build {
    source {
      repo_source {
        project_id = google_project.project.project_id
        repo_name = "plus"
        branch_name = "staging"
      }
    }

    step {
      name = "echo"
      args = ["echo", "hello world"]
    }

  }

}

Debug Output

https://gist.github.com/clive-h-townsend/76517f93e88750058f3deda1bb6950e9

Expected Behavior

Create the Cloud Build Trigger.

Actual Behavior

Failed because it says the API is not enabled. The API is indeed enabled (confirmed by checking on the console). It appears that the project= field is not working because the error goes away when I add Cloud Build API on the service account project. But, we are looking to setup the trigger on the project= project.

Steps to Reproduce

  1. terraform apply

References

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloudbuild_trigger#project

kr1schan commented 2 years ago

I have the same problem when using google_spanner_instance: The Project ID is not respected and when the service account is from another project this project is incorrectly used by the resource.

Vedaad-Shakib commented 2 years ago

I have the same problem. Did anyone figure out the solution?

whmackay commented 2 years ago

I also encountered this challenge with Cloud Build triggers using Cloud Functions Version 2/Gen 2 and was pointed by a peer to the reason. user_project_override defaults to false which allows the service (i.e. API) to decides which project to use for provisioning and managing the resource. In the case of Cloud Build the API defaults to the project associated with the Terraform user versus the project set at the provider or resource level. For many of us we use an account/service account from a different GCP project with Terraform than the one we're deploying resources which causes this problem. Instead set user_project_override on the provider and specify the project in either the provider or resource which will ensure Cloud Build provisions in the correct project where Cloud Build is enabled.

bjornandre commented 1 year ago

Also encountered this challenge with Cloud Build triggers and was pointed by another to the reason. user_project_override defaults to false which allows the service to decide if the resource project or project associated with the credential will be used. In the case of Cloud Build triggers seems its preference is the credential's project even if you set the project at either the provider or resource level. Setting the user_project_override in the provider resolved this for me.

I had the same problem. Thanks to @whmackay's suggestion I solved it by adding the google-beta provider and set the user_project_override attribute like this:

provider "google-beta" {
   user_project_override = true
   # ...
}

resource "google_service_account" "cloudbuild_service_account" {
   project = data.google_project.project.project_id
   account_id = "cloud-build-service-account"
}

resource "google_cloudbuild_trigger" "cloud-build-trigger" {
   provider = google-beta
   project  = data.google_project.project.project_id
   service_account = google_service_account.cloudbuild_service_account.id
   # ...
}
henrahmagix commented 7 months ago

I just experienced this, and it was very unintuitive. I even set project = ... on the resource, and that was ignored in favour of the default project of the credentials it uses.

Is this possible to fix in the Go code? Can we set one of these options to false to allow it to use the defined project from the resource config? https://github.com/hashicorp/terraform-provider-google/blob/1e379a92d1ca7233dac691a2f171df9f71b141c8/google/services/cloudbuild/resource_cloudbuild_trigger.go#L6038-L6043

Here's a version of my config that had this issue. I had to add user_project_override = true to the provider to get it working.

resource "google_cloudbuild_trigger" "my-trigger" {
  project = "my-cloudbuild-project"
  location = "global"
  # ...
}
import {
  id = "projects/my-cloudbuild-project/locations/global/triggers/abc123-redacted"
  to = google_cloudbuild_trigger.my-trigger
}

Output:

$ terraform plan
... <trimmed>
│ Error: Error when reading or editing CloudBuildTrigger "projects/my-cloudbuild-project/triggers/abc123-redacted": googleapi: Error 403: Cloud Build API has not been used in project my-terraform-service-project before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=my-terraform-service-project then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
│ Details:
│ [
│   {
│     "@type": "type.googleapis.com/google.rpc.Help",
│     "links": [
│       {
│         "description": "Google developers console API activation",
│         "url": "https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=my-terraform-service-project"
│       }
│     ]
│   },
│   {
│     "@type": "type.googleapis.com/google.rpc.ErrorInfo",
│     "domain": "googleapis.com",
│     "metadata": {
│       "consumer": "projects/my-terraform-service-project",
│       "service": "cloudbuild.googleapis.com"
│     },
│     "reason": "SERVICE_DISABLED"
│   }
│ ]
averbuks commented 4 months ago

The Cloud Build API, along with several other Google Cloud Platform APIs, must be enabled in both the project where the service account (used to initiate API calls) resides, and the project where Cloud Build resources (e.g., triggers, builds) are created. This is expected behavior and there is noting we can/should do on the terraform provider side. The recommended way to handle it would be enabling CloudBuild API on the terraform SA project. @hao-nan-li we may close the ticket.

hao-nan-li commented 4 months ago

Thanks @averbuks!

github-actions[bot] commented 3 months ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.