Terraform deleted my google project?

So I have an existing infrastructure on gcloud that I needed to convert to infra-as-code so I could replicate it. Terraform Import seemed perfect for the job. So I imported every resources with terraform import and created a state for my existing infra. I then applied a plan on top of it to add a secret manager and some bindings.

To my horror, after all the steps, terraform just deleted the entire gcloud project. At no point in the plan there was ANY mention of deleting anything.

The activity logs clearly show terraform deleting the project at 12:17 PM:

Does anyone have any idea of why this happened?

Did you actually write any Terraform code?

Of course! Here it is:

terraform {
  backend "gcs" {
    bucket      = "terraform-admin"
    prefix      = "terraform/states"
    credentials = "tfadmin-service-key.json"
  }
}

provider "google" {
  credentials = file("tfadmin-service-key.json")
  region      = var.region
}

provider "google-beta" {
  credentials = file("tfadmin-service-key.json")
  region      = var.region
}

resource "google_project" "project" {
  provider        = google
  project_id      = var.project_name
  name            = var.project_name
  billing_account = var.billing_account
  org_id          = var.org_id
}

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

# Enables secret manager
resource "google_project_service" "secret_manager" {
  project = google_project.project.project_id
  service = "secretmanager.googleapis.com"
}

# Enables cloud build which is required by firebase for deployments
resource "google_project_service" "cloudbuild" {
  project = google_project.project.project_id
  service = "cloudbuild.googleapis.com"
}

resource "google_app_engine_application" "app" {
  project       = google_project.project.project_id
  location_id   = var.region
  database_type = "CLOUD_FIRESTORE"
}

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

# Firebase App
resource "google_firebase_web_app" "basic" {
  provider     = google-beta
  project      = google_project.project.project_id
  display_name = google_project.project.project_id

  depends_on = [google_firebase_project.default]
}

data "google_firebase_web_app_config" "basic" {
  provider   = google-beta
  project    = google_project.project.project_id
  web_app_id = google_firebase_web_app.basic.app_id
}

# Cloud Storage
resource "google_storage_bucket" "default" {
  provider = google-beta
  project  = google_project.project.project_id
  name     = google_project.project.project_id
}

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

  content = jsonencode({
    appId             = google_firebase_web_app.basic.app_id
    apiKey            = data.google_firebase_web_app_config.basic.api_key
    authDomain        = data.google_firebase_web_app_config.basic.auth_domain
    databaseURL       = lookup(data.google_firebase_web_app_config.basic, "database_url", "")
    storageBucket     = lookup(data.google_firebase_web_app_config.basic, "storage_bucket", "")
    messagingSenderId = lookup(data.google_firebase_web_app_config.basic, "messaging_sender_id", "")
    measurementId     = lookup(data.google_firebase_web_app_config.basic, "measurement_id", ""),
    bugsnag           = var.bugsnag_api_key
    projectId         = google_project.project.project_id
  })
}

# Write locally so we can use the config in the app
resource "local_file" "firebase_config" {
  filename = "env.${google_project.project.project_id}.json"

  content = jsonencode({
    appId             = google_firebase_web_app.basic.app_id
    apiKey            = data.google_firebase_web_app_config.basic.api_key
    authDomain        = data.google_firebase_web_app_config.basic.auth_domain
    databaseURL       = lookup(data.google_firebase_web_app_config.basic, "database_url", "")
    storageBucket     = lookup(data.google_firebase_web_app_config.basic, "storage_bucket", "")
    messagingSenderId = lookup(data.google_firebase_web_app_config.basic, "messaging_sender_id", "")
    measurementId     = lookup(data.google_firebase_web_app_config.basic, "measurement_id", ""),
    bugsnag           = var.bugsnag_api_key
    projectId         = google_project.project.project_id
  })
}

# Give bucket access to firebase
resource "google_storage_bucket_iam_binding" "binding" {
  bucket = data.google_firebase_web_app_config.basic.storage_bucket
  role   = "roles/storage.admin"
  members = [
    "serviceAccount:firebase-storage@system.gserviceaccount.com",
  ]
}

# Create Algolia secret resource
resource "google_secret_manager_secret" "algolia" {
  provider  = google-beta
  project   = google_project.project.project_id
  secret_id = "algolia_backend"
  replication {
    automatic = true
  }

  depends_on = [google_project_service.secret_manager]
}

resource "google_secret_manager_secret_version" "algolia-secret" {
  provider    = google-beta
  secret      = google_secret_manager_secret.algolia.id
  secret_data = var.algolia_secret
  depends_on  = [google_secret_manager_secret.algolia]
}

# Give access to algolia secret to the app
resource "google_secret_manager_secret_iam_member" "algolia" {
  provider  = google-beta
  project   = google_project.project.project_id
  secret_id = google_secret_manager_secret.algolia.secret_id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_project.project.project_id}@appspot.gserviceaccount.com"
}

output "project_id" {
  value = google_project.project.project_id
}

output "firebase_bucket" {
  value = data.google_firebase_web_app_config.basic.storage_bucket
}

output "firebase-config" {
  value = data.google_firebase_web_app_config.basic
}

What did the plan look like?

Are you sure your code exactly matched what you imported?

Some resources can’t be altered in place, so will result in the underlying item being removed and recreated.

Unfortunately, I don’t have the plan anymore. But yes, the plan looked OK and did not specify at any point that the project would be created, replaced or deleted.

Do you think this could happen for an entire project? And if did, I would expect terraform to try to recreate the project after being deleted but it hasn’t :confused:

So now I’m confused as to whether I did something wrong or terraform is at fault here. I tried looking for similar issues and did not find any so that tells me I probably did something wrong.

But there’s not a lot of resources about the import feature and not a lot of user feedback either as its a relatively new feature I believe.

Anyway, here’s the import steps I did. Maybe that can be useful?

terraform import google_project.project ProjectID
terraform import google_project_service.firestore ProjectID/firestore.googleapis.com
terraform import google_project_service.cloudbuild ProjectID/cloudbuild.googleapis.com
terraform import google_app_engine_application.app ProjectID
terraform import google_firebase_project.default ProjectID 
terraform import google_firebase_web_app.basic ProjectID
terraform import google_storage_bucket.default ProjectID
terraform import google_storage_bucket_iam_binding.binding "ProjectID roles/storage.admin"