Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource Changes Triggering Unrelated Data Reads & Resource Replacements #8767

Closed
sam-humphreys opened this issue Mar 25, 2021 · 12 comments
Closed

Comments

@sam-humphreys
Copy link

sam-humphreys commented Mar 25, 2021

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request.
  • Please do not leave +1 or me too comments, they generate extra noise for issue followers and do not help prioritize the request.
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment.
  • If an issue is assigned to the modular-magician user, it is either in the process of being autogenerated, or is planned to be autogenerated soon. If an issue is assigned to a user, that user is claiming responsibility for the issue. If an issue is assigned to hashibot, a community member has claimed the issue already.

Terraform Version

╰─ terraform -v
Terraform v0.14.7

  • provider registry.terraform.io/hashicorp/google v3.61.0

Affected Resource(s)

google_storage_transfer_project_service_account (data)
google_storage_bucket_iam_member (resource)

Terraform Configuration Files

# Pre-change
resource "google_project" "project" {
  name            = "Test"
  project_id      = "gmex-example-20210325"
  folder_id       = "528660710754"
  billing_account = "MY_BILLING_ACCOUNT"
  labels          = {
    "project_owner" = "samhumphreys"
  }
}

resource "google_project_service" "storage-api-googleapis-com" {
  project             = google_project.project.project_id
  service             = "storage-api.googleapis.com"
  disable_on_destroy  = false
}

resource "google_project_service" "storage-component-googleapis-com" {
  project             = google_project.project.project_id
  service             = "storage-component.googleapis.com"
  disable_on_destroy  = false
}

resource "google_storage_bucket" "gmex-ex-20210325-state" {
  project                     = google_project.project.project_id
  name                        = "gmex-ex-20210325-state"
  location                    = "US"
  storage_class               = "MULTI_REGIONAL"
  uniform_bucket_level_access = "true"
  requester_pays              = "false"

  lifecycle_rule {
      action {
        type = "Delete"
      }

      condition {
        with_state          = "ANY"
        num_newer_versions  = "30"
      }
    }

  versioning {
    enabled = "true"
  }
}

data "google_storage_transfer_project_service_account" "stj-gmex-ex-20210325-state" {
  project = google_project.project.project_id
}

resource "google_storage_bucket_iam_member" "stj-gmex-ex-20210325-state-reader" {
  bucket      = "gmex-ex-20210325-state"
  role        = "roles/storage.admin"
  member      = "serviceAccount:${data.google_storage_transfer_project_service_account.stj-gmex-ex-20210325-state.email}"
  depends_on  = [ google_storage_bucket.gmex-ex-20210325-state ]
}

# Post-change
resource "google_project" "project" {
  name            = "Test"
  project_id      = "gmex-example-20210325"
  folder_id       = "528660710754"
  billing_account = "MY_BILLING_ACCOUNT"
  labels          = {
    "project_owner" = "samhumphreys"
    "test"                  = "yes"
  }
}

resource "google_project_service" "storage-api-googleapis-com" {
  project             = google_project.project.project_id
  service             = "storage-api.googleapis.com"
  disable_on_destroy  = false
}

resource "google_project_service" "storage-component-googleapis-com" {
  project             = google_project.project.project_id
  service             = "storage-component.googleapis.com"
  disable_on_destroy  = false
}

resource "google_storage_bucket" "gmex-ex-20210325-state" {
  project                     = google_project.project.project_id
  name                        = "gmex-ex-20210325-state"
  location                    = "US"
  storage_class               = "MULTI_REGIONAL"
  uniform_bucket_level_access = "true"
  requester_pays              = "false"

  lifecycle_rule {
      action {
        type = "Delete"
      }

      condition {
        with_state          = "ANY"
        num_newer_versions  = "30"
      }
    }

  versioning {
    enabled = "true"
  }
}

data "google_storage_transfer_project_service_account" "stj-gmex-ex-20210325-state" {
  project = google_project.project.project_id
}

resource "google_storage_bucket_iam_member" "stj-gmex-ex-20210325-state-reader" {
  bucket      = "gmex-ex-20210325-state"
  role        = "roles/storage.admin"
  member      = "serviceAccount:${data.google_storage_transfer_project_service_account.stj-gmex-ex-20210325-state.email}"
  depends_on  = [ google_storage_bucket.gmex-ex-20210325-state ]
}

Debug Output

Gist

Expected Behavior

Just a label should have been added, no other changes.

Actual Behavior

Label gets added. google_storage_transfer_project_service_account is read and google_storage_bucket_iam_member is forced to be replaced - no change is made here.

Steps to Reproduce

  1. Create resources from pre-change terraform config terraform apply
  2. Add an extra label to google_project, then apply change terraform apply

Important Factoids

  • Authenticated as user.
  • Replace billing account ID with MY_BILLING_ACCOUNT in terraform code and Gist log

b/302672921

@ghost ghost added the bug label Mar 25, 2021
@edwardmedia edwardmedia self-assigned this Mar 25, 2021
@edwardmedia
Copy link
Contributor

@sam-humphreys can you share the plan after you modified the label on the project? You did not provide project in below resource. Is that on purpose?

resource "google_storage_bucket_iam_member" "stj-gmex-ex-20210325-state-reader" {
  bucket      = "gmex-ex-20210325-state"
  role        = "roles/storage.admin"
  member      = "serviceAccount:${data.google_storage_transfer_project_service_account.stj-gmex-ex-20210325-state.email}"
  depends_on  = [ google_storage_bucket.gmex-ex-20210325-state ]
}

@sam-humphreys
Copy link
Author

I have since deleted the project, so the debug plan in this Gist refers to project gmex-example-20210325-1. Summary:

Terraform will perform the following actions:

  # data.google_storage_transfer_project_service_account.stj-gmex-ex-20210325-state will be read during apply
  # (config refers to values not yet known)
 <= data "google_storage_transfer_project_service_account" "stj-gmex-ex-20210325-state"  {
      ~ email   = "project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply)
      ~ id      = "project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply)
        # (1 unchanged attribute hidden)
    }

  # google_project.project will be updated in-place
  ~ resource "google_project" "project" {
        id                  = "projects/gmex-example-20210325-1"
      ~ labels              = {
          + "test"          = "yes"
            # (1 unchanged element hidden)
        }
        name                = "Test"
        # (5 unchanged attributes hidden)
    }

  # google_storage_bucket_iam_member.stj-gmex-ex-20210325-state-reader must be replaced
-/+ resource "google_storage_bucket_iam_member" "stj-gmex-ex-20210325-state-reader" {
      ~ bucket = "b/gmex-ex-20210325-state" -> "gmex-ex-20210325-state"
      ~ etag   = "CAI=" -> (known after apply)
      ~ id     = "b/gmex-ex-20210325-state/roles/storage.admin/serviceaccount:project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply)
      ~ member = "serviceAccount:project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply) # forces replacement
        # (1 unchanged attribute hidden)
    }

Plan: 1 to add, 1 to change, 1 to destroy.

As for the missing project on the google_storage_bucket_iam_member - I am assuming that it's not necessarily required. The reason being that project is specified within the google_storage_bucket resource and it would therefore be inferred, as well as being a resource-scoped permission rather than a project-scoped one.

@ghost ghost removed waiting-response labels Mar 25, 2021
@edwardmedia
Copy link
Contributor

edwardmedia commented Mar 25, 2021

@sam-humphreys I can't repro with below config.

resource "google_project" "project" {
  name            = "issue8767"
  project_id      = "issue8767"
  org_id     = "xxxxxxxxx"
  labels          = {
    "project_owner" = "samhumphreys"
    "test"                  = "no"
  }
}

data "google_storage_transfer_project_service_account" "stj-gmex-ex-20210325-state" {
  project = google_project.project.project_id
}

What did you do below plan? Can you post the plan after only a single change is made in the label field?

  # google_storage_bucket_iam_member.stj-gmex-ex-20210325-state-reader must be replaced
-/+ resource "google_storage_bucket_iam_member" "stj-gmex-ex-20210325-state-reader" {
      ~ bucket = "b/gmex-ex-20210325-state" -> "gmex-ex-20210325-state"
      ~ etag   = "CAI=" -> (known after apply)
      ~ id     = "b/gmex-ex-20210325-state/roles/storage.admin/serviceaccount:project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply)
      ~ member = "serviceAccount:project-473444228554@storage-transfer-service.iam.gserviceaccount.com" -> (known after apply) # forces replacement
        # (1 unchanged attribute hidden)
    }

@sam-humphreys
Copy link
Author

I did only make a single change, I added a label ("test" = "yes") to the project - somehow it's triggering the change to the other resources

  # google_project.project will be updated in-place
  ~ resource "google_project" "project" {
        id                  = "projects/gmex-example-20210325-1"
      ~ labels              = {
          + "test"          = "yes"
            # (1 unchanged element hidden)
        }
        name                = "Test"
        # (5 unchanged attributes hidden)
    }

@ghost ghost removed waiting-response labels Mar 25, 2021
@edwardmedia
Copy link
Contributor

edwardmedia commented Mar 25, 2021

@sam-humphreys from this plan, I don't see other resources besides google_project which is expected. What other resources you refer to? From my test, I did not see the data source google_storage_transfer_project_service_account in the subsequent plan.

somehow it's triggering the change to the other resources

I am not super clear what creates this plan. Can you give a simple config that we can repro the issue? I understood before call tf plan, there is only one change in the google_project`

@sam-humphreys
Copy link
Author

I included the plan in the original and in this comment, my previous comment just showed the change I was making.

Okay for clarity, firstly create the resources in the config below. Once complete, add an extra label (e.g. "test" = "yes") to the google_project (no other changes), and run terraform plan

Simplified config:

resource "google_project" "project" {
  name            = "Test"
  project_id      = "gmex-example-20210325-1"
  folder_id       = "528660710754"
  billing_account = "MY_BILLING_ACCOUNT"
  labels          = {
    "project_owner" = "samhumphreys"
  }
}

resource "google_storage_bucket" "bug-bucket-20210326" {
  project                     = google_project.project.project_id
  name                        = "bug-bucket-20210326"
  location                    = "US"
  storage_class               = "MULTI_REGIONAL"
  uniform_bucket_level_access = "true"
  requester_pays              = "false"
}

data "google_storage_transfer_project_service_account" "stj-bug-bucket-20210326" {
  project = google_project.project.project_id
}

resource "google_storage_bucket_iam_member" "stj-bug-bucket-20210326-reader" {
  bucket      = "bug-bucket-20210326"
  role        = "roles/storage.admin"
  member      = "serviceAccount:${data.google_storage_transfer_project_service_account.stj-bug-bucket-20210326.email}"
  depends_on  = [ google_storage_bucket.bug-bucket-20210326 ]
}

@ghost ghost removed waiting-response labels Mar 26, 2021
@edwardmedia
Copy link
Contributor

Interesting. I can repro it now. It only happens with Terraform v0.14.x. It is fine with v0.13.x.

@enicholson125
Copy link

I get the same issue with google_kms_secret data reads. It seems to be related to the module dependency - if I add an index to the module dependency, i.e. change it from
depends_on = [ google_storage_bucket.bug-bucket-20210326 ]
to
depends_on = [ google_storage_bucket.bug-bucket-20210326[0] ]
then the unwanted data reads go away.

@edwardmedia edwardmedia removed their assignment Apr 24, 2021
@maroux
Copy link
Contributor

maroux commented Jul 14, 2021

Happens with terraform v1.0.2 as well.

@maroux
Copy link
Contributor

maroux commented Jul 14, 2021

Also, this bug is marked with label upstream does that mean its a bug in terraform, or? In any case, can a reference to the upstream github issue be added to this thread?

@github-actions github-actions bot added service/storage forward/review In review; remove label to forward labels Aug 17, 2023
modular-magician added a commit to modular-magician/terraform-provider-google that referenced this issue Sep 19, 2023
@edwardmedia edwardmedia removed the forward/review In review; remove label to forward label Sep 20, 2023
@NickElliot
Copy link
Collaborator

Verified this is a byproduct of intended upstream Terraform behavior -- the data source read is unavoidable due to it being implicitly dependent_on the google_project via referencing it through google_project.project.project_id, and that deferred potential update to the data source exported field google_storage_transfer_project_service_account.email means the resource needs to Plan on being recreated, as a immutable attribute is potentially changing. My guess is the behavior manifested in a later Terraform version as a result of this edge case of chained depends_on being caught and the preventative measure being implemented.

Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 22, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants