From a317b5f0ce4f1e08105bbad5e829ec1bd61f78ba Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Mon, 4 May 2026 01:21:53 +1000 Subject: [PATCH] Require provider api_key and remove env var fallback --- README.md | 2 +- docs/index.md | 2 +- examples/live_end_to_end_dns_zone/README.md | 6 ++---- examples/live_end_to_end_dns_zone/variables.tf | 2 +- examples/live_safe_dns_record/README.md | 2 +- .../live_safe_dns_record/terraform.tfvars.example | 3 +-- examples/live_safe_dns_record/variables.tf | 2 +- examples/provider/provider.tf | 2 +- examples/read_only/providers.tf | 3 +-- examples/read_only/terraform.tfvars.example | 3 +-- examples/read_only/variables.tf | 2 +- internal/provider/provider.go | 11 +++++------ internal/provider/provider_test.go | 12 +++++------- 13 files changed, 22 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 390bd11..eadcaa7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A standalone Terraform provider for Dynu DNS and domain management. - `dynu_domains` - `dynu_domain` - `dynu_dns_records` -- Provider authentication via `api_key` or `DYNU_API_KEY`. +- Provider authentication via `api_key`. ## Minimal usage example diff --git a/docs/index.md b/docs/index.md index d3a5bcd..6ea04f7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,5 +29,5 @@ provider "dynu" { ### Optional -- `api_key` (String, Sensitive) Dynu API key. If omitted, `DYNU_API_KEY` is used. +- `api_key` (String, Sensitive) Dynu API key. Configure via provider argument (for example with `var.dynu_api_key` from `terraform.tfvars`). - `base_url` (String) Override API base URL. Primarily intended for automated tests. diff --git a/examples/live_end_to_end_dns_zone/README.md b/examples/live_end_to_end_dns_zone/README.md index 3bab247..86d489e 100644 --- a/examples/live_end_to_end_dns_zone/README.md +++ b/examples/live_end_to_end_dns_zone/README.md @@ -20,9 +20,7 @@ This example performs full live validation of the Dynu provider lifecycle by cre ## Prerequisites - A local build of this provider with Terraform `dev_overrides` for `dynu/dynu`. -- Dynu API key provided either by: - - environment variable `DYNU_API_KEY`, or - - Terraform variable `dynu_api_key`. +- Dynu API key provided as Terraform variable `dynu_api_key` (for example via `terraform.tfvars`). - A disposable domain value for `test_domain`. ## Required variables @@ -31,7 +29,7 @@ Create `terraform.tfvars` in this folder: ```hcl test_domain = "my-disposable-test-domain.example" -# dynu_api_key = "..." # optional if DYNU_API_KEY is exported +dynu_api_key = "..." ``` ## Commands diff --git a/examples/live_end_to_end_dns_zone/variables.tf b/examples/live_end_to_end_dns_zone/variables.tf index 5c7c8ba..81015f6 100644 --- a/examples/live_end_to_end_dns_zone/variables.tf +++ b/examples/live_end_to_end_dns_zone/variables.tf @@ -1,5 +1,5 @@ variable "dynu_api_key" { - description = "Dynu API key. Leave null to use DYNU_API_KEY from environment." + description = "Dynu API key used by the provider. Set in terraform.tfvars." type = string default = null sensitive = true diff --git a/examples/live_safe_dns_record/README.md b/examples/live_safe_dns_record/README.md index 3f7840e..76b6123 100644 --- a/examples/live_safe_dns_record/README.md +++ b/examples/live_safe_dns_record/README.md @@ -18,7 +18,7 @@ Using a single suffix (`test_suffix`), this example creates five DNS record scen ## Prerequisites - Local provider binary + Terraform `dev_overrides` for `dynu/dynu` -- `DYNU_API_KEY` exported, or `dynu_api_key` set in `terraform.tfvars` +- `dynu_api_key` set in `terraform.tfvars` - A Dynu-managed root domain you control ## Configure diff --git a/examples/live_safe_dns_record/terraform.tfvars.example b/examples/live_safe_dns_record/terraform.tfvars.example index 2c75fac..97817ba 100644 --- a/examples/live_safe_dns_record/terraform.tfvars.example +++ b/examples/live_safe_dns_record/terraform.tfvars.example @@ -1,5 +1,4 @@ -# Optional if DYNU_API_KEY is exported in your shell. -# dynu_api_key = "REPLACE_ME" +dynu_api_key = "REPLACE_ME" # Required: a Dynu-managed root domain/zone that you control. # Do NOT put an existing production hostname here. diff --git a/examples/live_safe_dns_record/variables.tf b/examples/live_safe_dns_record/variables.tf index ce2f302..44a5240 100644 --- a/examples/live_safe_dns_record/variables.tf +++ b/examples/live_safe_dns_record/variables.tf @@ -1,5 +1,5 @@ variable "dynu_api_key" { - description = "Dynu API key. Leave null to use DYNU_API_KEY from environment." + description = "Dynu API key used by the provider. Set in terraform.tfvars." type = string default = null sensitive = true diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index b601ea0..6e873a3 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -7,7 +7,7 @@ terraform { } provider "dynu" { - # api_key can be omitted when DYNU_API_KEY is set. + # Set var.dynu_api_key in terraform.tfvars. api_key = var.dynu_api_key } diff --git a/examples/read_only/providers.tf b/examples/read_only/providers.tf index c84a49c..128654c 100644 --- a/examples/read_only/providers.tf +++ b/examples/read_only/providers.tf @@ -12,7 +12,6 @@ terraform { # This source address stays "dynu/dynu" while using ~/.terraformrc dev_overrides. # Terraform will load your local terraform-provider-dynu binary instead of the public registry. provider "dynu" { - # Use DYNU_API_KEY environment variable by default. - # Set var.dynu_api_key in terraform.tfvars to override. + # Set var.dynu_api_key in terraform.tfvars. api_key = var.dynu_api_key } diff --git a/examples/read_only/terraform.tfvars.example b/examples/read_only/terraform.tfvars.example index 4943273..67a524a 100644 --- a/examples/read_only/terraform.tfvars.example +++ b/examples/read_only/terraform.tfvars.example @@ -1,6 +1,5 @@ # Copy to terraform.tfvars and adjust values for your environment. -# dynu_api_key can be omitted when DYNU_API_KEY is exported in your shell. -# dynu_api_key = "replace-with-dynu-api-key" +dynu_api_key = "replace-with-dynu-api-key" # Use a hostname that exists in your Dynu account. hostname = "www.example.com" diff --git a/examples/read_only/variables.tf b/examples/read_only/variables.tf index 0d4034d..0474d23 100644 --- a/examples/read_only/variables.tf +++ b/examples/read_only/variables.tf @@ -1,5 +1,5 @@ variable "dynu_api_key" { - description = "Dynu API key. Leave null to use DYNU_API_KEY from environment." + description = "Dynu API key used by the provider. Set in terraform.tfvars." type = string default = null sensitive = true diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 7a2e9f1..160bd43 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -2,7 +2,6 @@ package provider import ( "context" - "os" "strings" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -48,7 +47,7 @@ func (p *dynuProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp "api_key": schema.StringAttribute{ Optional: true, Sensitive: true, - Description: "Dynu API key. If omitted, the provider uses the DYNU_API_KEY environment variable.", + Description: "Dynu API key. Set this explicitly, such as via a Terraform variable in terraform.tfvars.", }, "base_url": schema.StringAttribute{ Optional: true, @@ -66,12 +65,12 @@ func (p *dynuProvider) Configure(ctx context.Context, req provider.ConfigureRequ return } - apiKey := resolveAPIKey(data.APIKey, os.Getenv("DYNU_API_KEY")) + apiKey := resolveAPIKey(data.APIKey) if apiKey == "" { resp.Diagnostics.AddAttributeError( path.Root("api_key"), "Missing Dynu API key", - "Configure api_key in the provider block or set the DYNU_API_KEY environment variable.", + "Configure api_key in the provider block (for example, from var.dynu_api_key set in terraform.tfvars).", ) return } @@ -81,11 +80,11 @@ func (p *dynuProvider) Configure(ctx context.Context, req provider.ConfigureRequ resp.ResourceData = providerData } -func resolveAPIKey(configValue types.String, envValue string) string { +func resolveAPIKey(configValue types.String) string { if !configValue.IsNull() && !configValue.IsUnknown() { return strings.TrimSpace(configValue.ValueString()) } - return strings.TrimSpace(envValue) + return "" } func (p *dynuProvider) DataSources(_ context.Context) []func() datasource.DataSource { diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index c237f4e..0ccb11a 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -16,19 +16,17 @@ func TestResolveAPIKey(t *testing.T) { tests := []struct { name string config types.String - env string want string }{ - {name: "config wins", config: types.StringValue("config-key"), env: "env-key", want: "config-key"}, - {name: "env fallback", config: types.StringNull(), env: "env-key", want: "env-key"}, - {name: "trim spaces", config: types.StringValue(" config-key "), env: " env-key ", want: "config-key"}, - {name: "unknown uses env", config: types.StringUnknown(), env: "env-key", want: "env-key"}, - {name: "empty when missing", config: types.StringNull(), env: "", want: ""}, + {name: "configured", config: types.StringValue("config-key"), want: "config-key"}, + {name: "null when missing", config: types.StringNull(), want: ""}, + {name: "trim spaces", config: types.StringValue(" config-key "), want: "config-key"}, + {name: "unknown when pending", config: types.StringUnknown(), want: ""}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if got := resolveAPIKey(tc.config, tc.env); got != tc.want { + if got := resolveAPIKey(tc.config); got != tc.want { t.Fatalf("resolveAPIKey() = %q, want %q", got, tc.want) } })