dnsimple / terraform-provider-dnsimple

Terraform DNSimple provider.
https://www.terraform.io/docs/providers/dnsimple/
Mozilla Public License 2.0
22 stars 20 forks source link

Turning prefetch on changes the view of the world in DNSimple #80

Closed lawrencewilson closed 1 year ago

lawrencewilson commented 1 year ago

Terraform Version

Terraform v1.3.6
on darwin_arm64
+ provider registry.terraform.io/dnsimple/dnsimple v0.15.0

Affected Resource(s)

Terraform Configuration Files

main.tf

terraform {
  required_providers {
    dnsimple = {
      source  = "dnsimple/dnsimple"
      version = "0.15.0"
    }
  }

  required_version = ">= 1.1.0"

  backend "remote" {
    organization = "example"

    workspaces {
      prefix = "example-"
    }
  }
}

provider "dnsimple" {
  token    = var.DNSIMPLE_TOKEN
  account  = var.DNSIMPLE_ACCOUNT
  sandbox  = var.DNSIMPLE_SANDBOX_ENVIRONMENT
  prefetch = var.DNSIMPLE_PREFETCH
}

locals {
  domain1_com      = "domain1.com"
  domain1_com_json = jsondecode(file("${path.root}/${local.domain1_com}.json"))
  domain1_com_set = flatten([for each in local.domain1_com_json :
    {
      "id"       = base64encode("${each.value}-${each.type}-${each.name}")
      "name"     = each.name
      "value"    = each.value
      "type"     = each.type
      "ttl"      = each.ttl
      "priority" = can(each.priority) ? each.priority : null
  }])
}

resource "dnsimple_zone_record" "domain1_com" {
  for_each = {
    for each in local.domain1_com_set : each.id => each
  }
  zone_name = local.domain1_com
  name      = each.value.name
  value     = each.value.value
  type      = each.value.type
  ttl       = each.value.ttl
  priority  = each.value.priority
}

variable "DNSIMPLE_TOKEN" {
  description = "DNsimple api token"
}

variable "DNSIMPLE_ACCOUNT" {
  description = "DNsimple account ID"
}

variable "DNSIMPLE_SANDBOX_ENVIRONMENT" {
  description = "true/false to specify if this is using sandbox"
}

variable "DNSIMPLE_PREFETCH" {
  description = "true/false to specify if this should save api requests to avoid rate-limiting"
}

domain1.com.json

[
  {
    "name": "",
    "value": "1.1.1.1",
    "type": "A",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "1a",
    "value": "1.1.1.1",
    "type": "A",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "2a",
    "value": "1.1.1.1",
    "type": "A",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "3a",
    "value": "1.1.1.1",
    "type": "A",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "1cname",
    "value": "www.example.com",
    "type": "CNAME",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "2cname",
    "value": "www.example.com",
    "type": "CNAME",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "3cname",
    "value": "www.example.com",
    "type": "CNAME",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "",
    "value": "https://www.example.com",
    "type": "URL",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "",
    "value": "mail.example.com",
    "type": "MX",
    "zone": "domain1.com",
    "ttl": 3600,
    "priority": 11
  },
  {
    "name": "1mx",
    "value": "mail.example.com",
    "type": "MX",
    "zone": "domain1.com",
    "ttl": 3600,
    "priority": 10
  },
  {
    "name": "2mx",
    "value": "mail25.example.com",
    "type": "MX",
    "zone": "domain1.com",
    "ttl": 3600,
    "priority": 5
  },
  {
    "name": "2mx",
    "value": "mail21.example.com",
    "type": "MX",
    "zone": "domain1.com",
    "ttl": 3600,
    "priority": 1
  },
  {
    "name": "example",
    "value": "ns-1.example.com",
    "type": "NS",
    "zone": "domain1.com",
    "ttl": 3600
  },
  {
    "name": "example",
    "value": "ns-2.example.com",
    "type": "NS",
    "zone": "domain1.com",
    "ttl": 3600
  },
  {
    "name": "example",
    "value": "ns-3.example.com",
    "type": "NS",
    "zone": "domain1.com",
    "ttl": 3600
  },
  {
    "name": "example",
    "value": "ns-4.example.com",
    "type": "NS",
    "zone": "domain1.com",
    "ttl": 3600
  },
  {
    "name": "_example",
    "value": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeee=",
    "type": "TXT",
    "zone": "domain1.com",
    "ttl": 600
  },
  {
    "name": "_example.e",
    "value": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeey",
    "type": "TXT",
    "zone": "domain1.com",
    "ttl": 600
  }
]

Debug Output

https://gist.github.com/lawrencewilson/c74945564685cb46241718a2db56a5b9

Panic Output

If Terraform produced a panic, please provide a link to a GitHub Gist containing the output of the crash.log.

Expected Behavior

What should have happened?

When you enable prefetch without changing the state, we should see No changes in terraform.

Actual Behavior

When you enable prefetch without changing the state, terraform detects drift where there is none and will attempt to delete and re-create records.

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. Set the values as necessary (Ensure the prefetch is set to false):
    $Env:TF_VAR_DNSIMPLE_TOKEN="secretvalue"
    $Env:TF_VAR_DNSIMPLE_SANDBOX_ENVIRONMENT="true"
    $Env:TF_VAR_DNSIMPLE_ACCOUNT="0000"
    $Env:TF_WORKSPACE="localdev"
    $Env:TF_VAR_DNSIMPLE_PREFETCH="false"
  2. Initialise the back end and apply the configuration
    terraform init
    terraform apply
  3. run terraform plan to ensure no state changes
    
    terraform plan                                               
    [WARN] Invalid log level: "TRUE". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR OFF][WARN] Invalid log level: "TRUE". Defaulting to level: TRACE. Valid levels are: [TRACE DEBUG INFO WARN ERROR 

... redacted to save space ...

dnsimple_zone_record.domain1_com["bWFpbC5leGFtcGxlLmNvbS1NWC0xbXg="]: Refreshing state... [id=2940594] dnsimple_zone_record.domain1_com["aHR0cHM6Ly93d3cuZXhhbXBsZS5jb20tVVJMLQ=="]: Refreshing state... [id=2940578]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

4. set the prefetch to `true` and re-initialize

PS > $Env:TF_VAR_DNSIMPLE_PREFETCH="true" PS > terraform init

Initializing the backend...

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work.

If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.

5. run another plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place -/+ destroy and then create replacement

Terraform will perform the following actions:

dnsimple_zone_record.domain1_com["MS4xLjEuMS1BLQ=="] must be replaced

-/+ resource "dnsimple_zone_record" "domain1_com" { ~ id = "2940587" -> (known after apply) ~ priority = "0" -> (known after apply) ~ qualified_name = "domain1.com" -> (known after apply) ~ ttl = "3600" -> "600" ~ type = "SOA" -> "A" # forces replacement ~ value = "ns1.dnsimple.com admin.dnsimple.com 1677551382 86400 7200 604800 300" -> "1.1.1.1" ~ zone_id = "domain1.com" -> (known after apply)

(1 unchanged attribute hidden)

}

dnsimple_zone_record.domain1_com["aHR0cHM6Ly93d3cuZXhhbXBsZS5jb20tVVJMLQ=="] must be replaced

-/+ resource "dnsimple_zone_record" "domain1_com" { ~ id = "2940578" -> (known after apply) ~ priority = "0" -> (known after apply) ~ qualified_name = "domain1.com" -> (known after apply) ~ ttl = "3600" -> "600" ~ type = "SOA" -> "URL" # forces replacement ~ value = "ns1.dnsimple.com admin.dnsimple.com 1677551382 86400 7200 604800 300" -> "https://www.example.com" ~ zone_id = "domain1.com" -> (known after apply)

(1 unchanged attribute hidden)

}

dnsimple_zone_record.domain1_com["bWFpbC5leGFtcGxlLmNvbS1NWC0="] must be replaced

-/+ resource "dnsimple_zone_record" "domain1_com" { ~ id = "2940580" -> (known after apply) ~ priority = "0" -> "11" ~ qualified_name = "domain1.com" -> (known after apply) ~ type = "SOA" -> "MX" # forces replacement ~ value = "ns1.dnsimple.com admin.dnsimple.com 1677551382 86400 7200 604800 300" -> "mail.example.com" ~ zone_id = "domain1.com" -> (known after apply)

(2 unchanged attributes hidden)

}

dnsimple_zone_record.domain1_com["bWFpbDIxLmV4YW1wbGUuY29tLU1YLTJteA=="] will be updated in-place

~ resource "dnsimple_zone_record" "domain1_com" { id = "2940600" name = "2mx" ~ priority = "5" -> "1" ~ value = "mail25.example.com" -> "mail21.example.com"

(5 unchanged attributes hidden)

}

dnsimple_zone_record.domain1_com["bnMtMS5leGFtcGxlLmNvbS1OUy1leGFtcGxl"] will be updated in-place

~ resource "dnsimple_zone_record" "domain1_com" { id = "2940591" name = "example" ~ value = "ns-3.example.com" -> "ns-1.example.com"

(6 unchanged attributes hidden)

}

dnsimple_zone_record.domain1_com["bnMtMi5leGFtcGxlLmNvbS1OUy1leGFtcGxl"] will be updated in-place

~ resource "dnsimple_zone_record" "domain1_com" { id = "2940584" name = "example" ~ value = "ns-3.example.com" -> "ns-2.example.com"

(6 unchanged attributes hidden)

}

dnsimple_zone_record.domain1_com["bnMtNC5leGFtcGxlLmNvbS1OUy1leGFtcGxl"] will be updated in-place

~ resource "dnsimple_zone_record" "domain1_com" { id = "2940582" name = "example" ~ value = "ns-3.example.com" -> "ns-4.example.com"

(6 unchanged attributes hidden)

}

Plan: 3 to add, 4 to change, 3 to destroy.



### Important Factoids
<!-- 
Are there anything atypical about your accounts that we should know? For example: Running in EC2 Classic? Custom version of OpenStack? Tight ACLs?
-->
We have split the domain records out of terraform configuration and read them in as a set from a json file.

### References
<!-- 
Are there any other GitHub issues (open or closed) or Pull Requests that should be linked here? For example:
- GH-1234
-->
DXTimer commented 1 year ago

Thank you @lawrencewilson for the detailed steps on reproducing the issue. We will work on a fix in the coming days.

DXTimer commented 1 year ago

Happy to share that we've been able to address the issue and a fix has been released as part of 0.16.2. #84

In case there are further comments, questions, or new discoveries please feel free to comment on the issue and we will re-open it.