mongodb / terraform-provider-mongodbatlas

Terraform MongoDB Atlas Provider: Deploy, update, and manage MongoDB Atlas infrastructure as code through HashiCorp Terraform
https://registry.terraform.io/providers/mongodb/mongodbatlas
Mozilla Public License 2.0
242 stars 168 forks source link

Crash during the changes for `mongodbatlas_cloud_backup_schedule` interval with dynamic blocks. #1041

Closed VitaliAndrushkevich closed 1 year ago

VitaliAndrushkevich commented 1 year ago

Terraform CLI and Terraform MongoDB Atlas Provider Version

$ terraform --version
Terraform v1.3.7
on darwin_arm64

Terraform Configuration File

resource "mongodbatlas_cloud_backup_schedule" "this" {
  project_id   = "project_id"
  cluster_name ="cluster_name"

  reference_hour_of_day    = element(split(":", var.snapshot_utc_time), 0)
  reference_minute_of_hour = element(split(":", var.snapshot_utc_time), 1)
  restore_window_days      = 14

  dynamic "policy_item_hourly" {
    for_each = {
      for item in lookup(var.backup_schedule, "hourly_policy", {}) : item.frequency_interval => item
    }

    content {
      frequency_interval = lookup(policy_item_hourly.value, "frequency_interval", null)
      retention_unit     = lookup(policy_item_hourly.value, "retention_unit", null)
      retention_value    = lookup(policy_item_hourly.value, "retention_value", null)
    }
  }

  dynamic "policy_item_daily" {
    for_each = {
      for item in lookup(var.backup_schedule, "daily_policy", {}) : item.frequency_interval => item
    }

    content {
      frequency_interval = lookup(policy_item_daily.value, "frequency_interval", null)
      retention_unit     = lookup(policy_item_daily.value, "retention_unit", null)
      retention_value    = lookup(policy_item_daily.value, "retention_value", null)
    }
  }

  dynamic "policy_item_weekly" {
    for_each = {
      for item in lookup(var.backup_schedule, "weekly_policy", {}) : item.frequency_interval => item
    }

    content {
      frequency_interval = lookup(policy_item_weekly.value, "frequency_interval", null)
      retention_unit     = lookup(policy_item_weekly.value, "retention_unit", null)
      retention_value    = lookup(policy_item_weekly.value, "retention_value", null)
    }
  }

  dynamic "policy_item_monthly" {
    for_each = {
      for item in lookup(var.backup_schedule, "monthly_policy", {}) : item.frequency_interval => item
    }

    content {
      frequency_interval = lookup(policy_item_monthly.value, "frequency_interval", null)
      retention_unit     = lookup(policy_item_monthly.value, "retention_unit", null)
      retention_value    = lookup(policy_item_monthly.value, "retention_value", null)
    }
  }
}

# var.backup_schedule
backup_schedule = {
    hourly_policy = [{
      frequency_interval = 8
      retention_unit     = "days"
      retention_value    = 3
    }],
    daily_policy = [{
      frequency_interval = 1
      retention_unit     = "days"
      retention_value    = 8
    }],
    weekly_policy = [{
      frequency_interval = 3
      retention_unit     = "weeks"
      retention_value    = 5
    }],
    monthly_policy = [{
      frequency_interval = 10
      retention_unit     = "months"
      retention_value    = 6
    }]
  }

Steps to Reproduce

  1. Terraform init
  2. Terraform apply
  3. Everything is working fine.
  4. Change the value of the frequency_interval in hourly_policy from 8 to 4
  5. Execute terraform apply again
  6. I'm receiving this error.

Expected Behavior

Frequency interval should be changed without the error.

Actual Behavior

During the terraform apply I'm receiving the crash. (Looks like it happened only with dynamic blocks)

Debug Output

Crash Output

Error: Request cancelled
│ 
│   with mongodbatlas_cloud_backup_schedule.this,
│   on ... line 53, in resource "mongodbatlas_cloud_backup_schedule" "this":
│   53: resource "mongodbatlas_cloud_backup_schedule" "this" {
│ 
│ The plugin.(*GRPCProvider).ApplyResourceChange request was cancelled.
╵
Releasing state lock. This may take a few moments...

Stack trace from the terraform-provider-mongodbatlas_v1.8.0 plugin:

panic: interface conversion: interface {} is nil, not map[string]interface {}

goroutine 97 [running]:
github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas.cloudBackupScheduleCreateOrUpdate({0x104e34348, 0x1400030eb40}, 0x14000113000, 0xc?, {0x140003134d0, 0x18}, {0x140003134a0, 0x11})
        github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go:505 +0xe18
github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas.resourceMongoDBAtlasCloudBackupScheduleUpdate({0x104e34348, 0x1400030eb40}, 0x1400015ec80, {0x104d03f00?, 0x140005a0f30?})
        github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go:384 +0x1b4
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).update(0x14000410540, {0x104e34380, 0x14000720b10}, 0xd?, {0x104d03f00, 0x140005a0f30})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/resource.go:741 +0xec
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0x14000410540, {0x104e34380, 0x14000720b10}, 0x140003e1a00, 0x1400015eb00, {0x104d03f00, 0x140005a0f30})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/resource.go:847 +0x680
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0x14000125950, {0x104e34380?, 0x140007209f0?}, 0x140007222d0)
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/grpc_provider.go:1021 +0xb94
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0x1400043e1e0, {0x104e34380?, 0x140007201b0?}, 0x140002220e0)
        github.com/hashicorp/terraform-plugin-go@v0.14.1/tfprotov5/tf5server/server.go:818 +0x3c0
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0x104df3180?, 0x1400043e1e0}, {0x104e34380, 0x140007201b0}, 0x14000222070, 0x0)
        github.com/hashicorp/terraform-plugin-go@v0.14.1/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x174
google.golang.org/grpc.(*Server).processUnaryRPC(0x140000d8000, {0x104e37a40, 0x140007029c0}, 0x14000728000, 0x140004163c0, 0x1053e0440, 0x0)
        google.golang.org/grpc@v1.50.1/server.go:1340 +0xb90
google.golang.org/grpc.(*Server).handleStream(0x140000d8000, {0x104e37a40, 0x140007029c0}, 0x14000728000, 0x0)
        google.golang.org/grpc@v1.50.1/server.go:1713 +0x840
google.golang.org/grpc.(*Server).serveStreams.func1.2()
        google.golang.org/grpc@v1.50.1/server.go:965 +0x88
created by google.golang.org/grpc.(*Server).serveStreams.func1
        google.golang.org/grpc@v1.50.1/server.go:963 +0x298

Error: The terraform-provider-mongodbatlas_v1.8.0 plugin crashed!

This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.

Additional Context

It looks like that is not a constant error and I'm receiving only with dynamic blocks. It happens from time to time, without dynamic blocks I was not able to reproduce the issue.

References

martinstibbe commented 1 year ago

@VitaliAndrushkevich We will try to replicate your issue thank you for the good example

martinstibbe commented 1 year ago

@VitaliAndrushkevich Not able to duplicate so far using your dynamic example with constant value of snapshot_utc_time = "12:03" I get ``` ~ update in-place

Terraform will perform the following actions:

mongodbatlas_cloud_backup_schedule.this will be updated in-place ~ resource "mongodbatlas_cloud_backup_schedule" "this" { id = "Y2x1c3Rlcl9uYW1l:Y2x1c3Rlci10ZXN0-cHJvamVjdF9pZA==:NjIxOTUyNTY3Yzg3Njg0ZmQ2OWIwMTAx"

(10 unchanged attributes hidden)

  ~ policy_item_hourly {
      ~ frequency_interval = 8 -> 4
        id                 = "63dc83839addaa046c36ce85"
        # (3 unchanged attributes hidden)
    }

    # (3 unchanged blocks hidden)
}

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

Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve.

Enter a value: yes

mongodbatlas_cloud_backup_schedule.this: Modifying... [id=Y2x1c3Rlcl9uYW1l:Y2x1c3Rlci10ZXN0-cHJvamVjdF9pZA==:NjIxOTUyNTY3Yzg3Njg0ZmQ2OWIwMTAx] mongodbatlas_cloud_backup_schedule.this: Modifications complete after 1s [id=Y2x1c3Rlcl9uYW1l:Y2x1c3Rlci10ZXN0-cHJvamVjdF9pZA==:NjIxOTUyNTY3Yzg3Njg0ZmQ2OWIwMTAx]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

VitaliAndrushkevich commented 1 year ago

Thanks a lot for you time and for updates @martinstibbe Sorry. I'll try to reproduce it again and provide a bit more details if that's possible. If no, then I'll close the issue.

VitaliAndrushkevich commented 1 year ago

@martinstibbe I was able to reproduce it again. Could you please try to add dynamics for export block:

dynamic "export" {
    for_each = var.enable_snapshot_export ? [1] : []
    content {
      export_bucket_id = var.export_bucket_id
      frequency_type   = var.frequency_type
    }
  }

When I'm trying to apply I can see this planned action:

 resource "mongodbatlas_cloud_backup_schedule" "this" {
        id                                       = "ID"
        # (10 unchanged attributes hidden)

      + export {}

        # (4 unchanged blocks hidden)
    }

After that I'm seeing this one

│ Error: Plugin did not respond
│ 
│   with mongodbatlas_cloud_backup_schedule.this,
│   on PATH line 53, in resource "mongodbatlas_cloud_backup_schedule" "this":
│   53: resource "mongodbatlas_cloud_backup_schedule" "this" {
│ 
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵

Stack trace from the terraform-provider-mongodbatlas_v1.8.0 plugin:

panic: interface conversion: interface {} is nil, not map[string]interface {}

goroutine 12 [running]:
github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas.cloudBackupScheduleCreateOrUpdate({0x104fc4348, 0x1400012b0e0}, 0x14000033c00, 0xc?, {0x14000118c00, 0x18}, {0x14000118bd0, 0x11})
        github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go:505 +0xe18
github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas.resourceMongoDBAtlasCloudBackupScheduleUpdate({0x104fc4348, 0x1400012b0e0}, 0x14000a9fa80, {0x104e93f00?, 0x14000a971c0?})
        github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/resource_mongodbatlas_cloud_backup_schedule.go:384 +0x1b4
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).update(0x14000284380, {0x104fc4380, 0x1400080e960}, 0xd?, {0x104e93f00, 0x14000a971c0})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/resource.go:741 +0xec
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0x14000284380, {0x104fc4380, 0x1400080e960}, 0x14000a14a90, 0x14000a9f500, {0x104e93f00, 0x14000a971c0})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/resource.go:847 +0x680
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0x1400000c048, {0x104fc4380?, 0x1400080e840?}, 0x1400004c280)
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.1/helper/schema/grpc_provider.go:1021 +0xb94
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0x140003c0280, {0x104fc4380?, 0x1400080e030?}, 0x140009ec070)
        github.com/hashicorp/terraform-plugin-go@v0.14.1/tfprotov5/tf5server/server.go:818 +0x3c0
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0x104f83180?, 0x140003c0280}, {0x104fc4380, 0x1400080e030}, 0x140009ec000, 0x0)
        github.com/hashicorp/terraform-plugin-go@v0.14.1/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x174
google.golang.org/grpc.(*Server).processUnaryRPC(0x1400025e1e0, {0x104fc7a40, 0x140007829c0}, 0x14000a8afc0, 0x140004ad1d0, 0x105570440, 0x0)
        google.golang.org/grpc@v1.50.1/server.go:1340 +0xb90
google.golang.org/grpc.(*Server).handleStream(0x1400025e1e0, {0x104fc7a40, 0x140007829c0}, 0x14000a8afc0, 0x0)
        google.golang.org/grpc@v1.50.1/server.go:1713 +0x840
google.golang.org/grpc.(*Server).serveStreams.func1.2()
        google.golang.org/grpc@v1.50.1/server.go:965 +0x88
created by google.golang.org/grpc.(*Server).serveStreams.func1
        google.golang.org/grpc@v1.50.1/server.go:963 +0x298

Error: The terraform-provider-mongodbatlas_v1.8.0 plugin crashed!

This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.
martinstibbe commented 1 year ago

@VitaliAndrushkevich Are you setting up multiple export storage buckets or just one ? As this variable block read looks like an enable export flag and a fixed bucket and interval

dynamic "export" {
    for_each = var.enable_snapshot_export ? [1] : []
    content {
      export_bucket_id = var.export_bucket_id
      frequency_type   = var.frequency_type
    }
  }

Using something singular like this in variable declaration ?

enable_snapshot_export = {
  export_bucket_id = "63e6929eccc50e0df1cf1b"
  frequency_type   = "daily"
}
VitaliAndrushkevich commented 1 year ago

Thanks for you time @martinstibbe ! My idea was to keep the flag, like enable exporting or not and if yes, provide parameters for exporting. It means only single export block. Actually, after removal of dynamic block for exporting the error has gone away.

Zuhairahmed commented 1 year ago

Glad to hear @VitaliAndrushkevich. Closing this issue as you appear to be unblocked, but feel free to re-open if you need anything else