ovh / terraform-provider-ovh

Terraform OVH provider
https://registry.terraform.io/providers/ovh/ovh/latest/docs
Mozilla Public License 2.0
183 stars 134 forks source link

[BUG] ovh_cloud_project_database_* replacing resources instead of updating it #592

Closed lpaturel closed 7 months ago

lpaturel commented 7 months ago

Describe the bug

As we are trying to add new users to our mongoDB instance (via ovh_cloud_project_database_mongodb_user), Terraform plans to replace the resources (even the database instance) instead of updating it in-place.

Terraform Version

/gitlab-org/terraform-images/releases/1.4:v1.0.0

OVH Terraform Provider Version

0.29

Affected Resource(s)

ovh_cloud_projectdatabase* Issue is found while trying to add users on MongoDB instance. We also encountered the issue while attempting to upgrade our PostgreSQL DB (from essential to business) and symptoms are the same with trying to replace instead of update.

Terraform Configuration Files

module "mongodb_users" {
  for_each = toset([
    for key in toset(keys(local.mongodb_users)) : key
  ])

  source = "../tf_modules/ovh/users"

  cluster_id   = module.mongodb_instances[each.value].db_instance_info.id
  engine       = module.mongodb_instances[each.value].db_instance_info.engine
  service_name = module.mongodb_instances[each.value].db_instance_info.service_name
  users        = try({ for k, v in local.mongodb_users[each.value] : k => v }, {})
}

resource "ovh_cloud_project_database_mongodb_user" "users" {
  for_each = {
    for k, v in var.users :
    k => v
    if var.engine == "mongodb"
  }

  service_name   = var.service_name
  cluster_id     = var.cluster_id
  name           = each.key
  roles          = each.value.roles
  password_reset = each.value.reset_password
}

Debug Output

Terraform will perform the following actions:
  # module.mongodb_instances["mongodb_instance_ID"].ovh_cloud_project_database.instance must be replaced
-/+ resource "ovh_cloud_project_database" "instance" {
      ~ advanced_configuration  = {} -> (known after apply)
      ~ backup_time             = "07:00:00" -> (known after apply)
      ~ created_at              = "2023-08-08T11:03:26.256684+02:00" -> (known after apply)
      ~ disk_type               = "high-speed" -> (known after apply)
      ~ endpoints               = [
          - {
              - component = "mongodbSrv"
              - domain    = "mongodbSrv_domainID.database.cloud.ovh.net"
              - path      = ""
              - port      = 0
              - scheme    = "mongodb+srv"
              - ssl       = true
              - ssl_mode  = "required"
              - uri       = "mongodb+srv://<username>:<password>@mongodbSrv_domainID.database.cloud.ovh.net/admin?replicaSet=replicaset&tls=true"
            },
          - {
              - component = "mongodb"
              - domain    = "mongodb_domainID.database.cloud.ovh.net"
              - path      = ""
              - port      = 27017
              - scheme    = "mongodb"
              - ssl       = true
              - ssl_mode  = "required"
              - uri       = "mongodb://<username>:<password>@node1-mongodb_domainID.database.cloud.ovh.net,node2-mongodb_domainID.database.cloud.ovh.net,node3-mongodb_domainID.database.cloud.ovh.net/admin?replicaSet=replicaset&tls=true"
            },
        ] -> (known after apply)
      ~ id                      = "mongodbID" -> (known after apply)
      - kafka_rest_api          = false -> null
      ~ maintenance_time        = "11:00:00" -> (known after apply)
      ~ network_type            = "private" -> (known after apply)
      - opensearch_acls_enabled = false -> null
      ~ status                  = "READY" -> (known after apply)
        # (7 unchanged attributes hidden)
      - nodes {
          - network_id = "networkID" -> null # forces replacement
          - region     = "GRA" -> null # forces replacement
          - subnet_id  = "subnetID" -> null
        }
      - nodes {
          - network_id = "networkID" -> null # forces replacement
          - region     = "GRA" -> null # forces replacement
          - subnet_id  = "subnetID" -> null
        }
        # (1 unchanged block hidden)
    }
  # module.mongodb_users["mongodb_instance_ID"].ovh_cloud_project_database_mongodb_user.users["user1"] will be created
  + resource "ovh_cloud_project_database_mongodb_user" "users" {
      + cluster_id     = (known after apply)
      + created_at     = (known after apply)
      + id             = (known after apply)
      + name           = "user1@admin"
      + password       = (sensitive value)
      + password_reset = "reset1"
      + roles          = [
          + "dbOwner@user1",
        ]
      + service_name   = "serviceName"
      + status         = (known after apply)
    }
  # module.mongodb_users["mongodb_instance_ID"].ovh_cloud_project_database_mongodb_user.users["user2"] must be replaced
-/+ resource "ovh_cloud_project_database_mongodb_user" "users" {
      ~ cluster_id     = "mongodb_ID" # forces replacement -> (known after apply)
      ~ created_at     = "2023-11-07T10:58:35.030023+01:00" -> (known after apply)
      ~ id             = "user2ID" -> (known after apply)
        name           = "user2@admin"
      ~ password       = (sensitive value)
      ~ status         = "READY" -> (known after apply)
        # (3 unchanged attributes hidden)
    }
  # module.mongodb_users["mongodb_instance_ID"].ovh_cloud_project_database_mongodb_user.users["user3"] must be replaced
-/+ resource "ovh_cloud_project_database_mongodb_user" "users" {
      ~ cluster_id     = "mongodb_ID" # forces replacement -> (known after apply)
      ~ created_at     = "2023-10-26T13:48:57.05025+02:00" -> (known after apply)
      ~ id             = "user3ID" -> (known after apply)
        name           = "user3@admin"
      ~ password       = (sensitive value)
      ~ status         = "READY" -> (known after apply)
        # (3 unchanged attributes hidden)
    }

... + 3 more users not showed to clean logs ...

Plan: 7 to add, 0 to change, 6 to destroy.

Expected Behavior

The resources should be "updated in-place" instead of "replaced".

Actual Behavior

If plan is applied, Terraform should destroy the resources before re-creating it.

Steps to Reproduce

our plan is launched as following with gitlab templates .terraform:build: &terraform_build stage: build script:

References

No ID as the issue is found inside our gitlab CI

amstuta commented 7 months ago

Hi @lpaturel , thanks for opening this issue.

It is quite difficult to pinpoint the issue with the configuration that you gave us, would you be able to have a reproducer with just a database instance and an associated user ?

Also, could you test with the provider version 0.40.0 ? Just in case it is an issue that was resolved by a previous release.

lpaturel commented 7 months ago

Hello @amstuta , thanks for your answer.

We've update the provider version to 0.40.0 but nothing's changed on the "plan" output.

As of testing with a single database and associated user, I'll try to find how to reproduce the issue but I'm not sure if this can be done with newly created resources. I'll keep you posted whenever I have new information on how to reproduce the case.

lpaturel commented 7 months ago

Hello, little update here, it turns out that our tfstate may have had been corrupted due to some "manual" actions that we've attempted to correct. The number of nodes in the terraform plan was not accurate which has led to some misunderstanding as there was no error messaging but the replacing of resources... Closing this issue.