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.
6.7 KiB
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, Plan Checks
Table of Contents
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:
statecheck.ExpectKnownValue("example_widget.test",
tfjsonpath.New("name"),
knownvalue.StringExact("my-widget"))
ExpectSensitiveValue
Assert an attribute is marked sensitive (requires Terraform 1.4.6+):
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:
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:
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:
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
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:
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
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
// 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:
Steps: []resource.TestStep{
{
Config: testAccConfig_basic(rName),
},
{
Config: testAccConfig_updated(rName),
},
{
Config: testAccConfig_basic(rName),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectEmptyPlan(),
},
},
},
},