Expert guidance for developing and maintaining the Terraform provider for UniFi network infrastructure management, including resource implementation, testing, and API integration patterns.
Expert guidance for developing and maintaining the Terraform provider for UniFi network infrastructure management.
This skill provides comprehensive knowledge for working on the `terraform-provider-unifi` codebase, including:
```
internal/provider/
├── provider.go # Provider configuration and initialization
├── client.go # Auto-relogin client with retry logic
├── utils.go # Pointer helpers, error handling
├── traffic_types.go # Shared nested types for traffic rules/routes
├── *_resource.go # Resource implementations
├── *_data_source.go # Data source implementations
├── *_test.go # Acceptance tests
├── testutils_test.go # Shared test utilities
└── sweep_test.go # Test resource cleanup sweepers
```
1. **Define the Model Struct**
- Use `tfsdk` tags for Terraform state mapping
- Mark sensitive fields (passwords, secrets) as `Sensitive: true`
- Use `types.String`, `types.Bool`, `types.Int64`, `types.List`, etc.
2. **Implement Schema Method**
- Use **ListNestedAttribute** or **SingleNestedAttribute** (NOT blocks)
- Add validators from `terraform-plugin-framework-validators`
- Add `UseStateForUnknown()` plan modifier for write-only fields
- Include `MarkdownDescription` for documentation generation
3. **Implement Conversion Functions**
- `planToSDK(plan *Model, diags *diag.Diagnostics) *sdktype.Request`
- `sdkToState(resp *sdktype.Response, priorState *Model) diag.Diagnostics`
- Handle write-only fields by preserving prior state values
4. **Implement CRUD Methods**
- `Create()` - Call API, handle errors with `handleSDKError()`, use `sdkToState()`
- `Read()` - Fetch resource, use `isNotFoundError()` for drift detection
- `Update()` - Call update API, handle partial updates if needed
- `Delete()` - Call delete API, handle already-deleted gracefully
- `ImportState()` - Use passthrough ID import
5. **Handle Write-Only Fields**
- Save value from plan before `sdkToState()`, restore after
- In `Read()`, pass `priorState` to preserve values not returned by API
- Resources with this pattern: `unifi_wlan`, `unifi_radius_profile`, `unifi_dynamic_dns`
1. **Reuse Resource Model** - Same struct but all fields marked `Computed: true`
2. **Add Lookup Field Validators** - Use `AtLeastOneOf` for id/name/key/hostname/description
3. **Implement Read Method**
- If ID provided, fetch directly
- Otherwise, list all resources and filter by lookup field
- Return error if not found or multiple matches
4. **Reuse sdkToState()** - Use resource's conversion function where possible
1. **Test Coverage Requirements**
- Basic creation test
- All attribute combinations
- Default value verification
- Update/modification scenarios
- Import state verification
- Destruction/cleanup verification
2. **Test Naming Convention**
- Function: `TestAcc{Resource}_{scenario}` (e.g., `TestAccNetworkResource_basic`)
- Resource names: `tf-acc-test-{resource}` prefix
- VLAN IDs: Use 3900+ range
- Rule indices: Use 2000+ range
3. **Controller Compatibility**
- Use `testAccPreCheckZoneBasedFirewall()` for v2 API features
- Implement skip logic for unsupported controllers
- Document compatibility in resource table
4. **Use Test Helpers**
- `testAccPreCheck(t)` - Standard pre-check
- `testAccCheckResourceDestroy()` - Verify cleanup
- Config builders for consistent test configs
5. **Implement Sweepers** - Add cleanup functions in `sweep_test.go`
Always use `ListNestedAttribute`/`SingleNestedAttribute` for new implementations.
**Schema:**
```go
"servers": schema.ListNestedAttribute{
Optional: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{...},
},
}
```
**HCL (with = and brackets):**
```hcl
servers = [{
ip = "10.0.0.1"
port = 1812
}]
```
| Controller Type | API Path | Zone-Based Firewall | Legacy Rules |
|----------------|----------|---------------------|--------------|
| UniFi OS (UDM, Network 10.x) | `/proxy/network/api/` | ✅ | ❌ |
| Legacy (standalone) | `/api/` | ❌ | ✅ |
| Resource | Limitation | Reason |
|----------|------------|--------|
| `unifi_firewall_zone` | No `site_id` attribute | API doesn't return it |
| `unifi_firewall_policy` | No `site_id` attribute | API doesn't return it |
| `unifi_wlan` | Import loses passphrase | Write-only field |
| `unifi_radius_profile` | Import loses server secrets | Write-only field |
| `unifi_dynamic_dns` | Import loses password | Write-only field |
```bash
make build # Build provider
make test # Unit tests
make testacc # All acceptance tests
make testacc-run TEST=TestAccName # Run specific test
make sweep # Clean up test resources
make docs # Generate documentation
make fmt # Format code
```
Create `.env` from `.env.example`:
```bash
UNIFI_BASE_URL=https://192.168.1.1
UNIFI_API_KEY=your-api-key # Recommended
UNIFI_USERNAME=admin # Alternative
UNIFI_PASSWORD=your-password # Alternative
UNIFI_INSECURE=true
```
API key authentication takes priority over username/password.
After completing tasks, provide:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/terraform-provider-unifi/raw