Skip to content

feat: add DNS provider Validate method with early credential checking#182

Draft
viniciusdc wants to merge 2 commits into
mainfrom
feat/dns-validate-early
Draft

feat: add DNS provider Validate method with early credential checking#182
viniciusdc wants to merge 2 commits into
mainfrom
feat/dns-validate-early

Conversation

@viniciusdc

@viniciusdc viniciusdc commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

DNS credential errors (missing CLOUDFLARE_API_TOKEN, bad zone_name) were only caught deep in the deploy flow — after infrastructure was already provisioned. The nic validate command had no DNS awareness at all.

Supersedes and closes #111 and closes #137 with a unified design.

Design

Separation of concerns (addresses both issues)

Phase When it runs What it checks
Config Always (incl. nic validate) zone_name present, domain within zone
Creds --check-creds or deploy/destroy Token set, zone accessible via live API

This keeps nic validate fast and offline-friendly by default (addresses #137), while nic deploy / nic destroy always do the full check before any tofu operations (addresses #111).

Changes

pkg/dnsprovider/provider.go

  • Add ValidateOptions struct with CheckCreds bool
  • Add Validate(ctx, domain, dnsConfig, opts) to the DNSProvider interface

pkg/config/config.go

  • Add DNSConfig.Single() helper — returns the sole provider name + config map, eliminating repeated map-iteration in CLI handlers

pkg/dnsprovider/cloudflare/provider.go

  • Implement Validate: composes existing extractCloudflareConfig, getAPIToken, getClient, and ResolveZoneID into the two-phase check

cmd/nic/validate.go

  • Add --check-creds flag
  • Check DNS config (and optionally credentials) when dns block is present in config

cmd/nic/deploy.go

  • Add validateDNSCredentials shared helper (reused by destroy)
  • Call it early in runDeploy, before any tofu operations, with CheckCreds: true

cmd/nic/destroy.go

  • Call validateDNSCredentials early in runDestroy, before any tofu operations

pkg/dnsprovider/cloudflare/provider_test.go

  • Add TestValidate with 9 table-driven cases: missing zone_name, nil config, domain outside zone, domain equal to zone, missing token, inaccessible zone, valid config-only, valid with creds

Usage

# Offline config check (fast, no network)
nic validate -f config.yaml

# Config + live credential check
nic validate -f config.yaml --check-creds

# deploy/destroy always check credentials before touching infrastructure
nic deploy -f config.yaml
nic destroy -f config.yaml

Testing

All 605 existing tests pass; 9 new tests added for Validate.

Addresses issues #111 and #137 with a unified design.

## What changed

### pkg/dnsprovider/provider.go
- Add ValidateOptions struct (CheckCreds bool field)
- Add Validate(ctx, domain, dnsConfig, opts) method to DNSProvider interface

### pkg/config/config.go
- Add DNSConfig.Single() helper returning the sole provider name + config map

### pkg/dnsprovider/cloudflare/provider.go
- Implement Validate with two phases:
  - Config (always): zone_name present, domain within zone
  - Creds (CheckCreds=true): token set, zone accessible via API

### cmd/nic/validate.go
- Add --check-creds flag
- Validate DNS config (and optionally credentials) when dns block is present

### cmd/nic/deploy.go
- Add validateDNSCredentials shared helper
- Call it early in runDeploy, before any tofu operations

### cmd/nic/destroy.go
- Call validateDNSCredentials early in runDestroy, before any tofu operations

### pkg/dnsprovider/cloudflare/provider_test.go
- Add TestValidate with 9 table-driven cases:
  missing zone_name, nil config, domain outside zone, domain equal to zone,
  missing token, inaccessible zone, valid config-only, valid with creds
@viniciusdc

viniciusdc commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

Manual smoke test — real Hetzner + Cloudflare deployment

Tested against a live deployment config (Hetzner provider, Cloudflare DNS, domain within a real zone) with the binary built from this branch.

1. Offline config-only validate (default)

$ nic validate -f config.yaml
{"time":"2026-03-20T17:56:46.447839689-03:00","level":"INFO","msg":"Validating configuration","config_file":"config.yaml"}
{"time":"2026-03-20T17:56:46.44832777-03:00","level":"INFO","msg":"Configuration is valid","provider":"hetzner","project_name":"nic-deploy"}
{"time":"2026-03-20T17:56:46.44846001-03:00","level":"INFO","msg":"DNS configuration validated (use --check-creds to also verify credentials)","dns_provider":"cloudflare"}
✓ Configuration file is valid
  Provider: hetzner
  Project:  nic-deploy
  DNS:      cloudflare
  • Config parsed and provider registered ✓
  • DNS config validated (zone_name present, domain within zone) ✓
  • Hint printed: "use --check-creds to also verify credentials"
  • No network calls made — fast and offline-safe ✓

2. Config + live credential check (--check-creds)

$ nic validate -f config.yaml --check-creds
{"time":"2026-03-20T17:57:08.922534498-03:00","level":"INFO","msg":"Validating configuration","config_file":"config.yaml"}
{"time":"2026-03-20T17:57:08.922839478-03:00","level":"INFO","msg":"Configuration is valid","provider":"hetzner","project_name":"nic-deploy"}
{"time":"2026-03-20T17:57:10.397252507-03:00","level":"INFO","msg":"DNS credentials validated","dns_provider":"cloudflare"}
✓ Configuration file is valid
  Provider: hetzner
  Project:  nic-deploy
  DNS:      cloudflare
  • All config checks pass ✓
  • Cloudflare API contacted (~1.5s), zone ID resolved ✓
  • "DNS credentials validated" logged ✓

3. Error path — missing token (--check-creds with CLOUDFLARE_API_TOKEN unset)

$ CLOUDFLARE_API_TOKEN="" nic validate -f config.yaml --check-creds
{"time":"2026-03-20T17:57:29.695349789-03:00","level":"INFO","msg":"Validating configuration","config_file":"config.yaml"}
{"time":"2026-03-20T17:57:29.695635089-03:00","level":"INFO","msg":"Configuration is valid","provider":"hetzner","project_name":"nic-deploy"}
{"time":"2026-03-20T17:57:29.695674999-03:00","level":"ERROR","msg":"DNS validation failed","error":"CLOUDFLARE_API_TOKEN environment variable is required","dns_provider":"cloudflare"}
Error: DNS validation failed: CLOUDFLARE_API_TOKEN environment variable is required
{"time":"2026-03-20T17:57:29.695716529-03:00","level":"ERROR","msg":"Command execution failed","error":"DNS validation failed: CLOUDFLARE_API_TOKEN environment variable is required"}
  • Fails immediately with a clear, actionable message ✓
  • No network call attempted ✓
  • Non-zero exit code ✓
  • No infrastructure touched ✓

@viniciusdc

Copy link
Copy Markdown
Contributor Author

I want to hold on this ultill #6 gets merged, since that will defined some standards

@viniciusdc viniciusdc marked this pull request as draft March 23, 2026 15:45
@viniciusdc viniciusdc added status: blocked ⛔️ Another task is blocking this item enhancement New feature or request dns-provider DNS provider related issues labels Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dns-provider DNS provider related issues enhancement New feature or request status: blocked ⛔️ Another task is blocking this item

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Validate method to DNS provider interface Validate DNS credentials early in validate command

2 participants