From c4eebf7197ca0582a1bed4b7e604e8e5466c70e5 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Thu, 23 Apr 2026 14:56:12 +1000 Subject: [PATCH] Add live-safe DNS record lifecycle example --- README.md | 26 ++++++++- examples/live_safe_dns_record/README.md | 53 +++++++++++++++++++ examples/live_safe_dns_record/main.tf | 33 ++++++++++++ examples/live_safe_dns_record/outputs.tf | 19 +++++++ .../terraform.tfvars.example | 13 +++++ examples/live_safe_dns_record/variables.tf | 29 ++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 examples/live_safe_dns_record/README.md create mode 100644 examples/live_safe_dns_record/main.tf create mode 100644 examples/live_safe_dns_record/outputs.tf create mode 100644 examples/live_safe_dns_record/terraform.tfvars.example create mode 100644 examples/live_safe_dns_record/variables.tf diff --git a/README.md b/README.md index 0efa894..9edab2f 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,16 @@ terraform validate terraform plan ``` +4. Run the live-safe write example (opt-in, creates a disposable DNS record only): + +```bash +cd examples/live_safe_dns_record +cp terraform.tfvars.example terraform.tfvars +# set only dynu_root_domain to a Dynu-managed root zone you control +terraform validate +terraform plan +``` + > [!WARNING] > Do not run `terraform init` as part of the normal Codex/local test loop for this repo. Because the provider is not yet published to the Terraform Registry, `init` may attempt registry/network resolution and fail or give misleading results. Use `dev_overrides`, rebuild the local binary, then run `terraform validate` and `terraform plan`. > @@ -232,6 +242,7 @@ data "dynu_dns_records" "selected" { ## Examples - Runnable local workflow: `examples/read_only/` +- Live-safe write lifecycle workflow: `examples/live_safe_dns_record/` - Provider block example: `examples/provider/provider.tf` - Individual data source snippets: - `examples/data-sources/dynu_domains/data-source.tf` @@ -277,11 +288,24 @@ Before committing, run: - `./scripts/test-integration.sh` - local mock-backed provider integration tests - `./scripts/testacc.sh` - acceptance/integration test wrapper (live tests opt-in) -Live acceptance tests are read-only and require: +Live acceptance tests are opt-in and require: - `TF_ACC=1` - `DYNU_API_KEY` - optional `DYNU_DOMAIN` for domain-specific coverage +### Live safe write testing + +Use `examples/live_safe_dns_record` when you want to safely validate writable provider behavior against a real Dynu account. + +- This example creates a unique temporary subdomain in the form `-.`. +- It creates exactly one disposable `A` record using an obviously non-production test IP by default. +- It is designed so `terraform destroy` removes only the created disposable record from that run/state. + +Safety guidance: +- Set `dynu_root_domain` to a root Dynu-managed zone you control (for example `example.com`). +- Do **not** supply or target an existing live full hostname you care about. +- If apply is interrupted, rerun `terraform destroy` from the same directory/state to clean up. + ## Feature scope Implemented: diff --git a/examples/live_safe_dns_record/README.md b/examples/live_safe_dns_record/README.md new file mode 100644 index 0000000..260ec7e --- /dev/null +++ b/examples/live_safe_dns_record/README.md @@ -0,0 +1,53 @@ +# Live Safe DNS Record Example + +This example is an **opt-in live test** for writable Dynu provider functionality. +It creates exactly one disposable DNS `A` record under a user-supplied Dynu root domain, +then you remove it with `terraform destroy`. + +## Safety model + +- Creates a **new unique subdomain** every run using `random_id`. +- Hostname format is: + - `-.` +- Creates exactly one record: + - `A` record, default content `198.51.100.10`, default TTL `300`. +- Does **not** import, update, replace, or delete existing production hostnames/records. +- `terraform destroy` removes only the disposable record in this state. + +> [!WARNING] +> Do not repurpose this example to target existing production subdomains. +> Always provide only a root Dynu-managed domain (for example, `example.com`) via +> `dynu_root_domain`. + +## Prerequisites + +- Local provider binary and Terraform `dev_overrides` set up for `dynu/dynu`. +- `DYNU_API_KEY` exported (or set `dynu_api_key` in `terraform.tfvars`). +- A Dynu-managed root domain you control. + +## Workflow + +```bash +go build -o terraform-provider-dynu +cd examples/live_safe_dns_record +cp terraform.tfvars.example terraform.tfvars +# edit terraform.tfvars and set only dynu_root_domain +terraform validate +terraform plan +terraform apply +``` + +After apply, inspect outputs to confirm the generated disposable hostname and record ID, +then clean up: + +```bash +terraform destroy +``` + +## Cleanup guidance + +- Always run `terraform destroy` after testing. +- If apply is interrupted or partially succeeds, rerun `terraform destroy` from this same + directory with the same `terraform.tfvars` and state files. +- If re-running without destroying first, Terraform may keep state for the previous + disposable record until it is destroyed. diff --git a/examples/live_safe_dns_record/main.tf b/examples/live_safe_dns_record/main.tf new file mode 100644 index 0000000..38691d0 --- /dev/null +++ b/examples/live_safe_dns_record/main.tf @@ -0,0 +1,33 @@ +terraform { + required_providers { + dynu = { + source = "dynu/dynu" + } + + random = { + source = "hashicorp/random" + version = ">= 3.6.0" + } + } +} + +provider "dynu" { + api_key = var.dynu_api_key +} + +resource "random_id" "suffix" { + byte_length = 4 +} + +locals { + disposable_label = "${var.test_prefix}-${lower(random_id.suffix.hex)}" + disposable_hostname = "${local.disposable_label}.${var.dynu_root_domain}" +} + +resource "dynu_dns_record" "safe_live_test" { + hostname = local.disposable_hostname + record_type = "A" + content = var.test_ip + ttl = var.test_ttl + state = true +} diff --git a/examples/live_safe_dns_record/outputs.tf b/examples/live_safe_dns_record/outputs.tf new file mode 100644 index 0000000..65b7406 --- /dev/null +++ b/examples/live_safe_dns_record/outputs.tf @@ -0,0 +1,19 @@ +output "disposable_hostname" { + description = "Generated unique disposable hostname created by this run." + value = local.disposable_hostname +} + +output "disposable_record_id" { + description = "Dynu DNS record ID in domain_id/record_id format for the disposable record." + value = dynu_dns_record.safe_live_test.id +} + +output "root_domain" { + description = "Dynu root domain used for this live-safe test." + value = var.dynu_root_domain +} + +output "cleanup_reminder" { + description = "Reminder to destroy the disposable record after verification." + value = "Run terraform destroy in this same directory/state to remove only this disposable record." +} diff --git a/examples/live_safe_dns_record/terraform.tfvars.example b/examples/live_safe_dns_record/terraform.tfvars.example new file mode 100644 index 0000000..e2599cc --- /dev/null +++ b/examples/live_safe_dns_record/terraform.tfvars.example @@ -0,0 +1,13 @@ +# Required: use only a Dynu-managed root domain/zone that you control. +# Do NOT put an existing full production hostname here. +dynu_root_domain = "example.com" + +# Optional prefix for generated disposable hostname labels. +# Final hostname format: -. +test_prefix = "tfacc" + +# Optional: documentation/test IP for disposable A record content. +test_ip = "198.51.100.10" + +# Optional TTL for disposable A record. +test_ttl = 300 diff --git a/examples/live_safe_dns_record/variables.tf b/examples/live_safe_dns_record/variables.tf new file mode 100644 index 0000000..1e65559 --- /dev/null +++ b/examples/live_safe_dns_record/variables.tf @@ -0,0 +1,29 @@ +variable "dynu_api_key" { + description = "Dynu API key. Leave null to use DYNU_API_KEY from the environment." + type = string + default = null + sensitive = true +} + +variable "dynu_root_domain" { + description = "Dynu-managed root domain for creating a disposable live test subdomain (for example: example.com)." + type = string +} + +variable "test_prefix" { + description = "Prefix for the disposable test hostname label." + type = string + default = "tfacc" +} + +variable "test_ip" { + description = "Safe documentation/test IPv4 value for the disposable A record." + type = string + default = "198.51.100.10" +} + +variable "test_ttl" { + description = "TTL in seconds for the disposable DNS record." + type = number + default = 300 +}