Archived
Refactor repo for standalone portable provider workflow
This commit is contained in:
@@ -1,67 +1,58 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Goal
|
||||
Build a Terraform provider for Dynu DNS and domains.
|
||||
Build and maintain a standalone Terraform provider for Dynu DNS and domains.
|
||||
|
||||
## Scope for current phase
|
||||
Read-only only. Implement provider configuration and data sources first.
|
||||
Do not implement any writable Terraform resources in the first phase.
|
||||
## Scope
|
||||
Current phase is **read-only**.
|
||||
|
||||
## Language and framework
|
||||
- Language: Go
|
||||
- Terraform provider framework: HashiCorp Terraform Plugin Framework
|
||||
- Do not use the legacy SDK unless explicitly requested.
|
||||
|
||||
## API usage
|
||||
- Use Dynu's public API.
|
||||
- Prefer stable, documented endpoints.
|
||||
- Build a small internal API client package rather than scattering HTTP calls across resources/data sources.
|
||||
- Add clear handling for pagination, 4xx/5xx responses, and malformed responses.
|
||||
- Never log secrets.
|
||||
|
||||
## Provider design
|
||||
Implement:
|
||||
- Provider configuration
|
||||
- Environment variable support for credentials
|
||||
- Read-only data sources:
|
||||
- dynu_domains
|
||||
- dynu_domain
|
||||
- dynu_dns_records
|
||||
- `dynu_domains`
|
||||
- `dynu_domain`
|
||||
- `dynu_dns_records`
|
||||
|
||||
Do not implement:
|
||||
- resource_dynu_dns_record
|
||||
- any create/update/delete flows
|
||||
- any speculative unsupported resources
|
||||
Do not implement in this phase:
|
||||
- Any Terraform resources with create/update/delete
|
||||
- Any write HTTP methods
|
||||
|
||||
## Safety
|
||||
- Read-only phase only.
|
||||
- No write HTTP methods in this phase.
|
||||
- Acceptance tests must only cover provider auth and read-only data sources.
|
||||
- Any future write support must be added in a separate phase.
|
||||
## Language and framework
|
||||
- Language: Go
|
||||
- Framework: HashiCorp Terraform Plugin Framework
|
||||
- Do not use the legacy Terraform Plugin SDK unless explicitly requested
|
||||
|
||||
## Code quality
|
||||
- Keep code modular and idiomatic Go.
|
||||
- Use strong typing for API models.
|
||||
- Prefer explicit schema definitions with clear descriptions.
|
||||
- Return actionable diagnostics.
|
||||
- Keep public documentation accurate to actual implementation.
|
||||
## API usage
|
||||
- Use Dynu public API endpoints
|
||||
- Prefer stable, documented endpoints
|
||||
- Keep HTTP logic in a small internal client package
|
||||
- Handle pagination and API errors clearly
|
||||
- Never log secrets or credentials
|
||||
|
||||
## Portability requirements
|
||||
- Keep the repository generic and standalone
|
||||
- Do not reference personal infrastructure, private domains, homelab tooling, or external repo scripts
|
||||
- Use neutral placeholders in docs and examples (for example: `example.com`, `my-test-domain.example`, `var.dynu_api_key`)
|
||||
- Avoid hardcoded local filesystem paths
|
||||
|
||||
## Testing
|
||||
- Add unit tests where practical.
|
||||
- Add acceptance tests gated behind environment variables.
|
||||
- Do not require live credentials for normal unit tests.
|
||||
- Add unit tests where practical
|
||||
- Gate acceptance tests behind generic environment variables
|
||||
- `TF_ACC=1`
|
||||
- `DYNU_API_KEY`
|
||||
- optional `DYNU_DOMAIN` for domain-specific acceptance coverage
|
||||
- Unit tests must not require live credentials
|
||||
|
||||
## Documentation
|
||||
- Add examples for every implemented data source.
|
||||
- Update README with provider configuration and environment variables.
|
||||
- Document limitations and unsupported areas clearly.
|
||||
- Keep README and examples aligned with actual provider behavior
|
||||
- Document current read-only limitations clearly
|
||||
- Include build, test, and acceptance test instructions for any contributor
|
||||
|
||||
## Developer scripts
|
||||
- `scripts/setup-dev.sh`: validate local toolchain requirements
|
||||
- `scripts/check.sh`: run formatting and unit checks
|
||||
- `scripts/testacc.sh`: run acceptance tests using generic env vars
|
||||
|
||||
## Output expectations
|
||||
Create a provider skeleton that can compile and expose the provider plus read-only data sources.
|
||||
|
||||
## Codex environment
|
||||
- Use `codex/setup.sh` to prepare the repository-local Codex environment.
|
||||
- Use `codex/maintain.sh` to refresh and validate the environment.
|
||||
- Use `codex/doctor.sh` for troubleshooting.
|
||||
- Do not install global packages unless explicitly required.
|
||||
- Prefer repo-local state under `.codex/`.
|
||||
Changes should keep the provider idiomatic, easy to contribute to, and ready for public/open-source usage.
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
# terraform-provider-dynu
|
||||
|
||||
Terraform provider for Dynu DNS using the Terraform Plugin Framework.
|
||||
A standalone Terraform provider for [Dynu](https://www.dynu.com/) DNS data.
|
||||
|
||||
> Current phase is **read-only**: this provider implements provider configuration and data sources only.
|
||||
> Current phase: **read-only**. This provider supports provider configuration and data sources only.
|
||||
|
||||
## Features
|
||||
## Feature scope
|
||||
|
||||
- Provider configuration with API key authentication.
|
||||
- Environment variable support (`DYNU_API_KEY`).
|
||||
Implemented:
|
||||
- Provider authentication via API key
|
||||
- Environment variable support (`DYNU_API_KEY`)
|
||||
- Read-only data sources:
|
||||
- `dynu_domains`
|
||||
- `dynu_domain`
|
||||
- `dynu_dns_records`
|
||||
|
||||
Not implemented in this phase:
|
||||
- Terraform resources
|
||||
- Any create/update/delete operations
|
||||
|
||||
## Requirements
|
||||
|
||||
- Terraform >= 1.5
|
||||
- Go >= 1.22 (for building)
|
||||
- A Dynu API key
|
||||
- [Terraform](https://developer.hashicorp.com/terraform/downloads) `>= 1.5`
|
||||
- [Go](https://go.dev/dl/) `>= 1.23` (for building and testing)
|
||||
- Dynu API key
|
||||
|
||||
## Provider configuration
|
||||
|
||||
@@ -25,24 +30,29 @@ Terraform provider for Dynu DNS using the Terraform Plugin Framework.
|
||||
provider "dynu" {
|
||||
api_key = var.dynu_api_key
|
||||
}
|
||||
|
||||
variable "dynu_api_key" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
```
|
||||
|
||||
You can also omit `api_key` and set `DYNU_API_KEY` in your environment.
|
||||
You can omit `api_key` in Terraform configuration and set the environment variable instead:
|
||||
|
||||
## Data sources
|
||||
```bash
|
||||
export DYNU_API_KEY="your-dynu-api-key"
|
||||
```
|
||||
|
||||
## Data source usage
|
||||
|
||||
### dynu_domains
|
||||
|
||||
Returns all DNS domains associated with the account.
|
||||
|
||||
```hcl
|
||||
data "dynu_domains" "all" {}
|
||||
```
|
||||
|
||||
### dynu_domain
|
||||
|
||||
Resolves the root domain from a hostname, then returns full domain details.
|
||||
|
||||
```hcl
|
||||
data "dynu_domain" "selected" {
|
||||
hostname = "www.example.com"
|
||||
@@ -51,34 +61,52 @@ data "dynu_domain" "selected" {
|
||||
|
||||
### dynu_dns_records
|
||||
|
||||
Resolves the root domain from a hostname, then returns DNS records for that domain.
|
||||
|
||||
```hcl
|
||||
data "dynu_dns_records" "records" {
|
||||
hostname = "www.example.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Development
|
||||
## Build
|
||||
|
||||
```bash
|
||||
./codex/setup.sh
|
||||
./codex/maintain.sh
|
||||
go build ./...
|
||||
```
|
||||
|
||||
Run tests:
|
||||
## Test
|
||||
|
||||
Run formatting and unit tests:
|
||||
|
||||
```bash
|
||||
./scripts/check.sh
|
||||
```
|
||||
|
||||
Or run unit tests directly:
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Acceptance tests (requires live Dynu credentials):
|
||||
## Acceptance tests
|
||||
|
||||
Acceptance tests are opt-in and require live Dynu credentials.
|
||||
|
||||
```bash
|
||||
TF_ACC=1 DYNU_API_KEY=... go test ./internal/provider -run TestAcc
|
||||
TF_ACC=1 DYNU_API_KEY="your-dynu-api-key" ./scripts/testacc.sh
|
||||
```
|
||||
|
||||
Optional environment variable:
|
||||
- `DYNU_DOMAIN` (for future domain-specific acceptance test cases)
|
||||
|
||||
## Developer workflow
|
||||
|
||||
- `./scripts/setup-dev.sh` – validates required local tools
|
||||
- `./scripts/check.sh` – runs formatting and unit checks
|
||||
- `./scripts/testacc.sh` – runs acceptance tests
|
||||
|
||||
Repository-local Codex helpers are also available under `codex/` for agent-oriented workflows.
|
||||
|
||||
## Limitations
|
||||
|
||||
- No Terraform resources are implemented in this phase.
|
||||
- No write operations are supported by provider code in this phase.
|
||||
- Read-only provider phase only
|
||||
- No writable Terraform resources yet
|
||||
|
||||
+8
-11
@@ -13,7 +13,7 @@ echo "time: $(date -u +%FT%TZ)"
|
||||
echo
|
||||
|
||||
echo "--- tools ---"
|
||||
for cmd in bash git python3 docker; do
|
||||
for cmd in bash git go terraform; do
|
||||
if have "$cmd"; then
|
||||
echo "$cmd: $(command -v "$cmd")"
|
||||
else
|
||||
@@ -23,17 +23,14 @@ done
|
||||
echo
|
||||
|
||||
echo "--- repo ---"
|
||||
[[ -f services-up.sh ]] && echo "services-up.sh: present" || echo "services-up.sh: missing"
|
||||
[[ -d core ]] && echo "core/: present" || true
|
||||
[[ -d apps ]] && echo "apps/: present" || true
|
||||
[[ -d monitoring ]] && echo "monitoring/: present" || true
|
||||
for path in README.md go.mod main.go internal/provider/provider.go; do
|
||||
if [[ -f "$path" ]]; then
|
||||
echo "$path: present"
|
||||
else
|
||||
echo "$path: missing"
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
echo "--- git status ---"
|
||||
git status --short || true
|
||||
echo
|
||||
|
||||
if have docker && docker compose version >/dev/null 2>&1; then
|
||||
echo "--- docker compose ---"
|
||||
docker compose version || true
|
||||
fi
|
||||
|
||||
+7
-72
@@ -7,80 +7,15 @@ source "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
cd_repo_root
|
||||
|
||||
log "Starting Codex environment setup in $(pwd)"
|
||||
log "Refreshing Codex environment and running repository checks"
|
||||
|
||||
if ! have git; then
|
||||
die "git is required"
|
||||
fi
|
||||
"$SCRIPT_DIR/setup.sh"
|
||||
|
||||
if ! have bash; then
|
||||
die "bash is required"
|
||||
fi
|
||||
|
||||
# Keep all Codex-local state inside the repo or user home.
|
||||
ensure_dir .codex
|
||||
ensure_dir .codex/bin
|
||||
ensure_dir .codex/cache
|
||||
ensure_dir .codex/tmp
|
||||
ensure_dir .codex/logs
|
||||
|
||||
# Useful environment defaults for repeatable non-interactive runs.
|
||||
cat > .codex/env <<'EOF'
|
||||
export CI=1
|
||||
export TERM=xterm-256color
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
export PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
export PIP_NO_INPUT=1
|
||||
export GIT_PAGER=cat
|
||||
EOF
|
||||
|
||||
# Optional Python venv for helper tooling.
|
||||
if have python3; then
|
||||
log "python3 detected"
|
||||
if [[ ! -d .codex/venv ]]; then
|
||||
python3 -m venv .codex/venv
|
||||
fi
|
||||
# shellcheck disable=SC1091
|
||||
source .codex/venv/bin/activate
|
||||
python -m pip install --upgrade pip setuptools wheel >/dev/null
|
||||
|
||||
# Install only lightweight tooling that is broadly useful.
|
||||
python -m pip install \
|
||||
pyyaml \
|
||||
requests \
|
||||
jinja2 \
|
||||
>/dev/null
|
||||
if [[ -x scripts/check.sh ]]; then
|
||||
./scripts/check.sh
|
||||
else
|
||||
warn "python3 not found; skipping virtualenv setup"
|
||||
log "scripts/check.sh not found; running go test ./..."
|
||||
go test ./...
|
||||
fi
|
||||
|
||||
# Basic repo checks based on your environment style.
|
||||
if [[ -f services-up.sh ]]; then
|
||||
log "Found services-up.sh"
|
||||
chmod +x services-up.sh || true
|
||||
else
|
||||
warn "services-up.sh not found at repo root"
|
||||
fi
|
||||
|
||||
# Make codex scripts executable.
|
||||
find codex -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} +
|
||||
|
||||
# Create a simple local ignore file for Codex-generated junk if needed.
|
||||
touch .git/info/exclude
|
||||
append_if_missing ".codex/" .git/info/exclude
|
||||
append_if_missing ".pytest_cache/" .git/info/exclude
|
||||
append_if_missing "__pycache__/" .git/info/exclude
|
||||
|
||||
# Helpful summary file for Codex tasks.
|
||||
cat > .codex/README.md <<'EOF'
|
||||
This directory contains local, disposable Codex environment state.
|
||||
|
||||
Contents:
|
||||
- env: shell exports for non-interactive work
|
||||
- venv: optional Python virtual environment
|
||||
- cache/: tool cache
|
||||
- tmp/: temporary files
|
||||
- logs/: script logs
|
||||
EOF
|
||||
|
||||
log "Setup complete"
|
||||
log "Maintenance complete"
|
||||
|
||||
+7
-46
@@ -7,34 +7,24 @@ source "$SCRIPT_DIR/lib.sh"
|
||||
|
||||
cd_repo_root
|
||||
|
||||
log "Starting Codex environment setup in $(pwd)"
|
||||
log "Preparing repository-local Codex environment in $(pwd)"
|
||||
|
||||
if ! have git; then
|
||||
die "git is required"
|
||||
fi
|
||||
for cmd in bash git; do
|
||||
have "$cmd" || die "$cmd is required"
|
||||
done
|
||||
|
||||
if ! have bash; then
|
||||
die "bash is required"
|
||||
fi
|
||||
|
||||
# Keep all Codex-local state inside the repo or user home.
|
||||
ensure_dir .codex
|
||||
ensure_dir .codex/bin
|
||||
ensure_dir .codex/cache
|
||||
ensure_dir .codex/tmp
|
||||
ensure_dir .codex/logs
|
||||
|
||||
# Useful environment defaults for repeatable non-interactive runs.
|
||||
cat > .codex/env <<'EOF'
|
||||
cat > .codex/env <<'ENVEOF'
|
||||
export CI=1
|
||||
export TERM=xterm-256color
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
export PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
export PIP_NO_INPUT=1
|
||||
export GIT_PAGER=cat
|
||||
EOF
|
||||
ENVEOF
|
||||
|
||||
# Optional Python venv for helper tooling.
|
||||
if have python3; then
|
||||
log "python3 detected"
|
||||
if [[ ! -d .codex/venv ]]; then
|
||||
@@ -43,44 +33,15 @@ if have python3; then
|
||||
# shellcheck disable=SC1091
|
||||
source .codex/venv/bin/activate
|
||||
python -m pip install --upgrade pip setuptools wheel >/dev/null
|
||||
|
||||
# Install only lightweight tooling that is broadly useful.
|
||||
python -m pip install \
|
||||
pyyaml \
|
||||
requests \
|
||||
jinja2 \
|
||||
>/dev/null
|
||||
else
|
||||
warn "python3 not found; skipping virtualenv setup"
|
||||
warn "python3 not found; skipping optional venv setup"
|
||||
fi
|
||||
|
||||
# Basic repo checks based on your environment style.
|
||||
if [[ -f services-up.sh ]]; then
|
||||
log "Found services-up.sh"
|
||||
chmod +x services-up.sh || true
|
||||
else
|
||||
warn "services-up.sh not found at repo root"
|
||||
fi
|
||||
|
||||
# Make codex scripts executable.
|
||||
find codex -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} +
|
||||
|
||||
# Create a simple local ignore file for Codex-generated junk if needed.
|
||||
touch .git/info/exclude
|
||||
append_if_missing ".codex/" .git/info/exclude
|
||||
append_if_missing ".pytest_cache/" .git/info/exclude
|
||||
append_if_missing "__pycache__/" .git/info/exclude
|
||||
|
||||
# Helpful summary file for Codex tasks.
|
||||
cat > .codex/README.md <<'EOF'
|
||||
This directory contains local, disposable Codex environment state.
|
||||
|
||||
Contents:
|
||||
- env: shell exports for non-interactive work
|
||||
- venv: optional Python virtual environment
|
||||
- cache/: tool cache
|
||||
- tmp/: temporary files
|
||||
- logs/: script logs
|
||||
EOF
|
||||
|
||||
log "Setup complete"
|
||||
|
||||
@@ -6,10 +6,13 @@ import (
|
||||
)
|
||||
|
||||
func TestAccScaffold(t *testing.T) {
|
||||
if os.Getenv("TF_ACC") == "" || os.Getenv("DYNU_API_KEY") == "" {
|
||||
if os.Getenv("TF_ACC") != "1" || os.Getenv("DYNU_API_KEY") == "" {
|
||||
t.Skip("set TF_ACC=1 and DYNU_API_KEY to enable acceptance tests")
|
||||
}
|
||||
|
||||
// Optional: DYNU_DOMAIN may be used by future acceptance test cases.
|
||||
_ = os.Getenv("DYNU_DOMAIN")
|
||||
|
||||
// Acceptance tests for read-only data sources are intentionally scaffolded in phase 1.
|
||||
// Add terraform-plugin-testing based test cases in a follow-up with stable fixtures.
|
||||
}
|
||||
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "[check] Running gofmt"
|
||||
files="$(git ls-files '*.go')"
|
||||
if [[ -n "$files" ]]; then
|
||||
# shellcheck disable=SC2086
|
||||
gofmt -w $files
|
||||
fi
|
||||
|
||||
echo "[check] Running go test"
|
||||
go test ./...
|
||||
|
||||
echo "[check] Completed"
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "[setup-dev] Validating local toolchain"
|
||||
|
||||
for cmd in bash git go; do
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "[setup-dev][error] Missing required command: $cmd" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[setup-dev] $cmd: $(command -v "$cmd")"
|
||||
done
|
||||
|
||||
if command -v terraform >/dev/null 2>&1; then
|
||||
echo "[setup-dev] terraform: $(command -v terraform)"
|
||||
else
|
||||
echo "[setup-dev][warn] terraform not found (only required for terraform validate and acceptance workflows)"
|
||||
fi
|
||||
|
||||
echo "[setup-dev] Toolchain validation complete"
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${TF_ACC:-}" != "1" ]]; then
|
||||
echo "[testacc][error] TF_ACC must be set to 1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${DYNU_API_KEY:-}" ]]; then
|
||||
echo "[testacc][error] DYNU_API_KEY must be set" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${DYNU_DOMAIN:-}" ]]; then
|
||||
echo "[testacc][info] DYNU_DOMAIN is not set; running baseline acceptance scaffolding"
|
||||
fi
|
||||
|
||||
echo "[testacc] Running acceptance tests"
|
||||
go test ./internal/provider -run TestAcc -count=1
|
||||
Reference in New Issue
Block a user