Implement godaddy_dns_record resource CRUD #11

Closed
opened 2026-06-14 17:26:45 +00:00 by ldraney · 1 comment
Owner

Type

Feature

Summary

Implement resource_dns_record.go with full CRUD lifecycle using the Terraform Plugin Framework.

User Story

As a platform operator, I want to manage GoDaddy DNS records via tofu apply so that DNS configuration is version-controlled and reproducible.

Context

The Go client (pkg/godaddy/) is fully implemented and tested. The provider skeleton exists but returns empty resource/data source maps. This is the P0 resource that makes the provider usable.

Lineage

Parent: none
Story: dns-iac

Repo

godaddy-tofu

Scope

  • Create resource_dns_record.go implementing resource.Resource interface
  • Schema: domain (string, required), type (string, required), name (string, required), data (string, required), ttl (int, optional, default 600), priority (int, optional), weight (int, optional), port (int, optional)
  • Create: client.ReplaceRecords(ctx, domain, type, name, []DNSRecord{...})
  • Read: client.GetRecords(ctx, domain, type, name)
  • Update: client.ReplaceRecords(ctx, domain, type, name, []DNSRecord{...})
  • Delete: client.DeleteRecords(ctx, domain, type, name)
  • Register in provider.go Resources() map
  • Import support via domain:type:name composite ID

File Targets

  • resource_dns_record.go (new)
  • provider.go (register resource)

Feature Flag

None

Test Expectations

  • Acceptance tests in separate issue
  • Manual test: tofu plan/apply/destroy against live API

Acceptance Criteria

  • tofu plan shows DNS record as a resource to create
  • tofu apply creates a DNS record at GoDaddy
  • tofu plan after apply shows no diff
  • tofu destroy removes the record
  • Import via composite ID works

Constraints

  • GoDaddy API uses PUT (replace) semantics, not POST (create) — design around this
  • Composite ID domain:type:name since GoDaddy has no record-level IDs

Checklist

  • resource.Resource interface implemented
  • Registered in provider.go
  • Import support
  • Error handling with APIError unwrapping

Depends on: #3 (done), #4 (done)
Blocks: palinks #50, pal-e-platform terraform config

### Type Feature ### Summary Implement `resource_dns_record.go` with full CRUD lifecycle using the Terraform Plugin Framework. ### User Story As a platform operator, I want to manage GoDaddy DNS records via `tofu apply` so that DNS configuration is version-controlled and reproducible. ### Context The Go client (`pkg/godaddy/`) is fully implemented and tested. The provider skeleton exists but returns empty resource/data source maps. This is the P0 resource that makes the provider usable. ### Lineage Parent: none Story: dns-iac ### Repo godaddy-tofu ### Scope - Create `resource_dns_record.go` implementing `resource.Resource` interface - Schema: `domain` (string, required), `type` (string, required), `name` (string, required), `data` (string, required), `ttl` (int, optional, default 600), `priority` (int, optional), `weight` (int, optional), `port` (int, optional) - Create: `client.ReplaceRecords(ctx, domain, type, name, []DNSRecord{...})` - Read: `client.GetRecords(ctx, domain, type, name)` - Update: `client.ReplaceRecords(ctx, domain, type, name, []DNSRecord{...})` - Delete: `client.DeleteRecords(ctx, domain, type, name)` - Register in `provider.go` Resources() map - Import support via `domain:type:name` composite ID ### File Targets - `resource_dns_record.go` (new) - `provider.go` (register resource) ### Feature Flag None ### Test Expectations - Acceptance tests in separate issue - Manual test: `tofu plan/apply/destroy` against live API ### Acceptance Criteria - [ ] `tofu plan` shows DNS record as a resource to create - [ ] `tofu apply` creates a DNS record at GoDaddy - [ ] `tofu plan` after apply shows no diff - [ ] `tofu destroy` removes the record - [ ] Import via composite ID works ### Constraints - GoDaddy API uses PUT (replace) semantics, not POST (create) — design around this - Composite ID `domain:type:name` since GoDaddy has no record-level IDs ### Checklist - [ ] resource.Resource interface implemented - [ ] Registered in provider.go - [ ] Import support - [ ] Error handling with APIError unwrapping ### Related Depends on: #3 (done), #4 (done) Blocks: palinks #50, pal-e-platform terraform config
Author
Owner

Scope Review: #11 + #12 (DNS Resource CRUD + Data Source)

Reviewed both issues together since they ship as one unit.


1. Scope Clarity and Actionability

#11 (resource CRUD): Excellent. Scope section specifies the exact interface to implement (resource.Resource), all schema attributes with types and optionality, the client methods to call for each CRUD operation (GetRecords, ReplaceRecords, DeleteRecords), and the composite ID format (domain:type:name). A dev agent can implement this without asking questions.

#12 (data source): Clear and appropriately scoped. Interface (datasource.DataSource), schema with required/optional filters, client method (GetRecords), and output shape are all specified. Straightforward companion to #11.

2. Acceptance Criteria Testability

#11: Five criteria, all manually testable with tofu plan/apply/destroy. Import test is verifiable. These are appropriate for a first implementation -- acceptance test automation is explicitly deferred to #13.

#12: Three criteria, testable via tofu plan against live API. Filter behavior is verifiable.

3. File Targets

#11: resource_dns_record.go (new) + provider.go (register). Correct and complete.

#12: data_source_dns_records.go (new) + provider.go (register). Correct.

Both reference provider.go registration -- the existing code has empty return slices in Resources() and DataSources() which are ready to receive entries.

4. Dependencies

#3 (Go scaffold): Closed. provider.go skeleton exists with auth, empty resource/data source maps, and client wiring via resp.ResourceData/resp.DataSourceData. Confirmed in tree.

#4 (Integration tests): Closed. Client methods are proven:

  • GetRecords(ctx, domain, type, name) -- returns []DNSRecord
  • ReplaceRecords(ctx, domain, type, name, []DNSRecord) -- returns error
  • DeleteRecords(ctx, domain, type, name) -- returns error

All three signatures match what #11 and #12 reference. APIError type exists for error unwrapping per #11's checklist.

#10 (QA nits): Open, but covers test-level fixes (errors.As consistency, dead code). Does not affect the client API surface or provider skeleton. Not a blocker.

5. Ambiguity Check

No blockers found. Two minor observations (non-blocking):

  • GoDaddy PUT semantics: #11's Constraints section correctly flags that the API uses PUT (replace-all) rather than POST. The existing ReplaceRecords method already handles this. A dev agent should be aware that creating a single record for a type/name replaces any existing records at that path -- this is inherent to the API and documented in the constraint. Good.

  • Delete behavior: GoDaddy's DELETE endpoint for DNS records may return 422 for certain protected record types (e.g., NS at @). The dev agent should handle this gracefully but this is implementation detail, not a scoping gap.


Verdict: APPROVED

Both issues are well-structured, specify exact file targets and interfaces, reference proven client methods, and have all dependencies satisfied. Ready for development as a single PR.

## Scope Review: #11 + #12 (DNS Resource CRUD + Data Source) Reviewed both issues together since they ship as one unit. --- ### 1. Scope Clarity and Actionability **#11 (resource CRUD):** Excellent. Scope section specifies the exact interface to implement (`resource.Resource`), all schema attributes with types and optionality, the client methods to call for each CRUD operation (`GetRecords`, `ReplaceRecords`, `DeleteRecords`), and the composite ID format (`domain:type:name`). A dev agent can implement this without asking questions. **#12 (data source):** Clear and appropriately scoped. Interface (`datasource.DataSource`), schema with required/optional filters, client method (`GetRecords`), and output shape are all specified. Straightforward companion to #11. ### 2. Acceptance Criteria Testability **#11:** Five criteria, all manually testable with `tofu plan/apply/destroy`. Import test is verifiable. These are appropriate for a first implementation -- acceptance test automation is explicitly deferred to #13. **#12:** Three criteria, testable via `tofu plan` against live API. Filter behavior is verifiable. ### 3. File Targets **#11:** `resource_dns_record.go` (new) + `provider.go` (register). Correct and complete. **#12:** `data_source_dns_records.go` (new) + `provider.go` (register). Correct. Both reference `provider.go` registration -- the existing code has empty return slices in `Resources()` and `DataSources()` which are ready to receive entries. ### 4. Dependencies **#3 (Go scaffold):** Closed. `provider.go` skeleton exists with auth, empty resource/data source maps, and client wiring via `resp.ResourceData`/`resp.DataSourceData`. Confirmed in tree. **#4 (Integration tests):** Closed. Client methods are proven: - `GetRecords(ctx, domain, type, name)` -- returns `[]DNSRecord` - `ReplaceRecords(ctx, domain, type, name, []DNSRecord)` -- returns `error` - `DeleteRecords(ctx, domain, type, name)` -- returns `error` All three signatures match what #11 and #12 reference. `APIError` type exists for error unwrapping per #11's checklist. **#10 (QA nits):** Open, but covers test-level fixes (`errors.As` consistency, dead code). Does not affect the client API surface or provider skeleton. Not a blocker. ### 5. Ambiguity Check **No blockers found.** Two minor observations (non-blocking): - **GoDaddy PUT semantics:** #11's Constraints section correctly flags that the API uses PUT (replace-all) rather than POST. The existing `ReplaceRecords` method already handles this. A dev agent should be aware that creating a single record for a type/name replaces any existing records at that path -- this is inherent to the API and documented in the constraint. Good. - **Delete behavior:** GoDaddy's DELETE endpoint for DNS records may return 422 for certain protected record types (e.g., NS at `@`). The dev agent should handle this gracefully but this is implementation detail, not a scoping gap. --- ### Verdict: APPROVED Both issues are well-structured, specify exact file targets and interfaces, reference proven client methods, and have all dependencies satisfied. Ready for development as a single PR.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/godaddy-tofu#11
No description provided.