Files
Max Vojtkov a6d8aa8b52 A Terraform provider for Dokploy
Plugin-framework provider covering projects, environments, applications,
Compose stacks, managed databases, domains, mounts, ports, redirects,
basic auth, registries, SSH keys, certificates and backup destinations,
over Dokploy's tRPC-over-REST API.

The shim package exposes the provider to other Go modules, which is how
pulumi-dokploy bridges it.
2026-08-09 12:17:26 +03:00

232 lines
6.7 KiB
Markdown

# State Checks and Plan Checks Reference
Detailed reference for `statecheck` and `plancheck` packages from
`terraform-plugin-testing`. Read this when writing assertions for test steps.
Source: [State Checks](https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/state-checks/resource),
[Plan Checks](https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests/plan-checks)
---
## Table of Contents
1. [State Checks](#state-checks)
2. [Known Value Types](#known-value-types)
3. [tfjsonpath Navigation](#tfjsonpath-navigation)
4. [Value Comparers](#value-comparers)
5. [Plan Checks](#plan-checks)
---
## State Checks
Use via `ConfigStateChecks` field on `TestStep`. All assertion errors are
aggregated and reported together.
### ExpectKnownValue
Assert an attribute has a specific type and value:
```go
statecheck.ExpectKnownValue("example_widget.test",
tfjsonpath.New("name"),
knownvalue.StringExact("my-widget"))
```
### ExpectSensitiveValue
Assert an attribute is marked sensitive (requires Terraform 1.4.6+):
```go
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_4_6),
},
// ...
statecheck.ExpectSensitiveValue("example_widget.test",
tfjsonpath.New("api_key"))
```
### CompareValue
Compare the same attribute across sequential test steps:
```go
compareValuesSame := statecheck.CompareValue(compare.ValuesSame())
Steps: []resource.TestStep{
{
Config: testAccConfig_v1(rName),
ConfigStateChecks: []statecheck.StateCheck{
compareValuesSame.AddStateValue("example_widget.test",
tfjsonpath.New("id")),
},
},
{
Config: testAccConfig_v2(rName),
ConfigStateChecks: []statecheck.StateCheck{
compareValuesSame.AddStateValue("example_widget.test",
tfjsonpath.New("id")),
},
},
},
```
### CompareValuePairs
Compare attributes between two resources:
```go
statecheck.CompareValuePairs(
"example_widget.test", tfjsonpath.New("vpc_id"),
"example_vpc.test", tfjsonpath.New("id"),
compare.ValuesSame())
```
### CompareValueCollection
Check if a value exists in a collection attribute:
```go
statecheck.CompareValueCollection(
"example_widget.test", tfjsonpath.New("tags"),
"example_widget.test", tfjsonpath.New("name"),
compare.ValuesSame())
```
---
## Known Value Types
Use with `ExpectKnownValue` to assert attribute values:
| Type | Example |
|------|---------|
| `knownvalue.StringExact("value")` | Exact string match |
| `knownvalue.StringRegexp(regexp.MustCompile(`^arn:`))` | Regex match |
| `knownvalue.Bool(true)` | Boolean value |
| `knownvalue.Int64Exact(42)` | Exact int64 |
| `knownvalue.Float64Exact(3.14)` | Exact float64 |
| `knownvalue.NotNull()` | Value is set (not null) |
| `knownvalue.Null()` | Value is null |
| `knownvalue.ListExact([]knownvalue.Check{...})` | Exact list match |
| `knownvalue.ListPartial(map[int]knownvalue.Check{0: ...})` | Partial list match |
| `knownvalue.ListSizeExact(3)` | List has N elements |
| `knownvalue.SetExact([]knownvalue.Check{...})` | Exact set match |
| `knownvalue.SetPartial([]knownvalue.Check{...})` | Set contains items |
| `knownvalue.SetSizeExact(2)` | Set has N elements |
| `knownvalue.MapExact(map[string]knownvalue.Check{...})` | Exact map match |
| `knownvalue.MapPartial(map[string]knownvalue.Check{...})` | Map contains keys |
| `knownvalue.MapSizeExact(1)` | Map has N keys |
| `knownvalue.ObjectExact(map[string]knownvalue.Check{...})` | Exact object match |
| `knownvalue.ObjectPartial(map[string]knownvalue.Check{...})` | Object has attributes |
| `knownvalue.Float32Exact(1.5)` | Exact float32 |
| `knownvalue.Int32Exact(42)` | Exact int32 |
| `knownvalue.NumberExact(big.NewFloat(42))` | Exact number (`*big.Float`) |
| `knownvalue.TupleExact([]knownvalue.Check{...})` | Exact tuple match |
| `knownvalue.TuplePartial(map[int]knownvalue.Check{0: ...})` | Partial tuple match |
| `knownvalue.TupleSizeExact(3)` | Tuple has N elements |
### Nested Value Example
```go
statecheck.ExpectKnownValue("example_widget.test",
tfjsonpath.New("settings"),
knownvalue.ObjectExact(map[string]knownvalue.Check{
"mode": knownvalue.StringExact("production"),
"enabled": knownvalue.Bool(true),
}))
```
---
## tfjsonpath Navigation
Navigate nested attributes in state:
```go
tfjsonpath.New("attribute") // top-level attribute
tfjsonpath.New("block").AtMapKey("key") // nested map/object key
tfjsonpath.New("list_attr").AtSliceIndex(0) // list element by index
tfjsonpath.New("block").AtMapKey("nested").AtMapKey("deep") // deep nesting
```
---
## Value Comparers
Use with `CompareValue`, `CompareValuePairs`, `CompareValueCollection`:
| Comparer | Purpose |
|----------|---------|
| `compare.ValuesSame()` | Values are identical |
| `compare.ValuesDiffer()` | Values are different |
---
## Plan Checks
Use via `ConfigPlanChecks` or `RefreshPlanChecks` on `TestStep`. Plan checks
inspect the plan file at specific phases.
### ConfigPlanChecks Phases
```go
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{...}, // after plan, before apply
PostApplyPreRefresh: []plancheck.PlanCheck{...}, // after apply, before refresh
PostApplyPostRefresh: []plancheck.PlanCheck{...}, // after refresh
},
```
### Built-in Plan Checks
```go
// Expect no changes in plan
plancheck.ExpectEmptyPlan()
// Expect changes in plan
plancheck.ExpectNonEmptyPlan()
// Expect specific resource action
plancheck.ExpectResourceAction("example_widget.test", plancheck.ResourceActionCreate)
plancheck.ExpectResourceAction("example_widget.test", plancheck.ResourceActionUpdate)
plancheck.ExpectResourceAction("example_widget.test", plancheck.ResourceActionDestroy)
plancheck.ExpectResourceAction("example_widget.test", plancheck.ResourceActionNoop)
// Expect known plan value
plancheck.ExpectKnownValue("example_widget.test",
tfjsonpath.New("name"),
knownvalue.StringExact("my-widget"))
// Expect unknown (computed) value in plan
plancheck.ExpectUnknownValue("example_widget.test",
tfjsonpath.New("computed_field"))
// Expect sensitive value in plan
plancheck.ExpectSensitiveValue("example_widget.test",
tfjsonpath.New("api_key"))
```
### No-Op After Update Example
Verify that updating a config back to original values produces no diff:
```go
Steps: []resource.TestStep{
{
Config: testAccConfig_basic(rName),
},
{
Config: testAccConfig_updated(rName),
},
{
Config: testAccConfig_basic(rName),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectEmptyPlan(),
},
},
},
},
```