Dirkos
Dirkos

Reputation: 676

Terraform keeps destroying existing resource

Im trying to debug why my Terraform script is not working. Due an unknown reason Terraform keeps destroying my MySQL database and recreates it after that.

Below is the output of the execution plan:

  # azurerm_mysql_server.test01 will be destroyed
  - resource "azurerm_mysql_server" "test01" {
      - administrator_login               = "me" -> null
      - auto_grow_enabled                 = true -> null
      - backup_retention_days             = 7 -> null
      - create_mode                       = "Default" -> null
      - fqdn                              = "db-test01.mysql.database.azure.com" -> null
      - geo_redundant_backup_enabled      = false -> null
      - id                                = "/subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/production-rg/providers/Microsoft.DBforMySQL/servers/db-test01" -> null
      - infrastructure_encryption_enabled = false -> null
      - location                          = "westeurope" -> null
      - name                              = "db-test01" -> null
      - public_network_access_enabled     = true -> null
      - resource_group_name               = "production-rg" -> null
      - sku_name                          = "B_Gen5_1" -> null
      - ssl_enforcement                   = "Disabled" -> null
      - ssl_enforcement_enabled           = false -> null
      - ssl_minimal_tls_version_enforced  = "TLSEnforcementDisabled" -> null
      - storage_mb                        = 51200 -> null
      - tags                              = {} -> null
      - version                           = "8.0" -> null

      - storage_profile {
          - auto_grow             = "Enabled" -> null
          - backup_retention_days = 7 -> null
          - geo_redundant_backup  = "Disabled" -> null
          - storage_mb            = 51200 -> null
        }

      - timeouts {}
    }

  # module.databases.module.test.azurerm_mysql_server.test01 will be created
  + resource "azurerm_mysql_server" "test01" {
      + administrator_login               = "me"
      + administrator_login_password      = (sensitive value)
      + auto_grow_enabled                 = true
      + backup_retention_days             = 7
      + create_mode                       = "Default"
      + fqdn                              = (known after apply)
      + geo_redundant_backup_enabled      = false
      + id                                = (known after apply)
      + infrastructure_encryption_enabled = false
      + location                          = "westeurope"
      + name                              = "db-test01"
      + public_network_access_enabled     = true
      + resource_group_name               = "production-rg"
      + sku_name                          = "B_Gen5_1"
      + ssl_enforcement                   = (known after apply)
      + ssl_enforcement_enabled           = false
      + ssl_minimal_tls_version_enforced  = "TLSEnforcementDisabled"
      + storage_mb                        = 51200
      + version                           = "8.0"

      + storage_profile {
          + auto_grow             = (known after apply)
          + backup_retention_days = (known after apply)
          + geo_redundant_backup  = (known after apply)
          + storage_mb            = (known after apply)
        }
    }

As far as i know all is exactly the same. To prevent this i also did a manually terraform import to sync the state with the remote state.

The actually resource as defined in my main.tf

resource "azurerm_mysql_server" "test01" {
  name                = "db-test01"
  location            = "West Europe"
  resource_group_name = var.rg

  administrator_login          = "me"
  administrator_login_password = var.root_password

  sku_name   = "B_Gen5_1"
  storage_mb = 51200
  version    = "8.0"

  auto_grow_enabled                 = true
  backup_retention_days             = 7
  geo_redundant_backup_enabled      = false
  infrastructure_encryption_enabled = false
  public_network_access_enabled     = true
  ssl_enforcement_enabled           = false
}

The other odd thing is that below command will output that all is actually in sync?

➜  terraform git:(develop) ✗ terraform plan --refresh-only
azurerm_mysql_server.test01: Refreshing state... [id=/subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/firstklas-production-rg/providers/Microsoft.DBforMySQL/servers/db-test01]

No changes. Your infrastructure still matches the configuration.

After an actual import the same still happens even though the import states all is in state:

➜  terraform git:(develop) ✗ terraform import azurerm_mysql_server.test01 /subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/production-rg/providers/Microsoft.DBforMySQL/servers/db-test01
azurerm_mysql_server.test01: Importing from ID "/subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/production-rg/providers/Microsoft.DBforMySQL/servers/db-test01"...
azurerm_mysql_server.test01: Import prepared!
  Prepared azurerm_mysql_server for import
azurerm_mysql_server.test01: Refreshing state... [id=/subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/production-rg/providers/Microsoft.DBforMySQL/servers/db-test01]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

What can i do to prevent this destroy? Or even figure out why the actually destroy is triggered? This is happening on multiple azure instances at this point.

NOTE: the subscription ID is spoofed so don't worry

Best, Pim

Upvotes: 1

Views: 1847

Answers (2)

Shridhar Gavai
Shridhar Gavai

Reputation: 19

There is a way. user

Plan Apply terraform state rm "resource_name" --------This will eliminate or remove resource from current state next Apply

Worked perfectly on GCP for creating 2 successive VM using same TF script.

Only thing is we need to write/code to get current resources and store somewhere and create commands in config: require blocks for upstream dependencies #3. While destroying we can add back using terraform state mv "resource_name"

Note : This has risk as the very first VM did not get deleted as it is considered generated out of scope of terraform. So your cost may persist. So you have to have back up (incremental for states)

Hope this helps.

Upvotes: 0

Martin Atkins
Martin Atkins

Reputation: 74779

Your plan output shows that Terraform is seeing two different resource addresses:

  # azurerm_mysql_server.test01 will be destroyed
  # module.databases.module.test.azurerm_mysql_server.test01 will be created

Notice that the one to be created is in a nested module, not in the root module.

If your intent is to import this object to the address that is shown as needing to be created above, you'll need to specify this full address in the terraform import command:

terraform import 'module.databases.module.test.azurerm_mysql_server.test01' /subscriptions/8012-4035-b8f3-860f8cb1119e/resourceGroups/production-rg/providers/Microsoft.DBforMySQL/servers/db-test01

The terraform import command tells Terraform to bind an existing remote object to a particular Terraform address, and so when you use it you need to be careful to specify the correct Terraform address to bind to.

In your case, you told Terraform to bind the object to a hypothetical resource "azurerm_mysql_server" "test01" block in the root module, but your configuration has no such block and so when you ran terraform plan Terraform assumed that you wanted to delete that object, because deleting a resource block is how we typically tell Terraform that we intend to delete something.

Upvotes: 2

Related Questions