mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
don't lose checks from refresh-only plan
If there are no changes, then there is no reason to create an apply graph since all objects are known. We however do need the walk to match the expected state structure. This is probably only cleanup of empty nested modules and outputs, but some investigation is needed before making the full change. For now we can store the checks from the plan directly into the new state, since the apply walk overwrote the results we had already.
This commit is contained in:
parent
ff68c8d129
commit
b61c02da05
@ -69,6 +69,18 @@ Note that the -target option is not suitable for routine use, and is provided on
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: we cannot check for an empty plan for refresh-only, because root
|
||||||
|
// outputs are always stored as changes. The final condition of the state
|
||||||
|
// also depends on some cleanup which happens during the apply walk. It
|
||||||
|
// would probably make more sense if applying a refresh-only plan were
|
||||||
|
// simply just returning the planned state and checks, but some extra
|
||||||
|
// cleanup is going to be needed to make the plan state match what apply
|
||||||
|
// would do. For now we can copy the checks over which were overwritten
|
||||||
|
// during the apply walk.
|
||||||
|
if len(plan.Changes.Resources) == 0 {
|
||||||
|
newState.CheckResults = plan.Checks.DeepCopy()
|
||||||
|
}
|
||||||
|
|
||||||
return newState, diags
|
return newState, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1641,3 +1641,75 @@ output "from_resource" {
|
|||||||
_, diags = ctx.Apply(plan, m)
|
_, diags = ctx.Apply(plan, m)
|
||||||
assertNoErrors(t, diags)
|
assertNoErrors(t, diags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -refresh-only should update checks
|
||||||
|
func TestContext2Apply_refreshApplyUpdatesChecks(t *testing.T) {
|
||||||
|
m := testModuleInline(t, map[string]string{
|
||||||
|
"main.tf": `
|
||||||
|
resource "test_object" "x" {
|
||||||
|
test_string = "ok"
|
||||||
|
lifecycle {
|
||||||
|
postcondition {
|
||||||
|
condition = self.test_string == "ok"
|
||||||
|
error_message = "wrong val"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "from_resource" {
|
||||||
|
value = test_object.x.test_string
|
||||||
|
precondition {
|
||||||
|
condition = test_object.x.test_string == "ok"
|
||||||
|
error_message = "wrong val"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`})
|
||||||
|
|
||||||
|
p := simpleMockProvider()
|
||||||
|
p.ReadResourceResponse = &providers.ReadResourceResponse{
|
||||||
|
NewState: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"test_string": cty.StringVal("ok"),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
state := states.NewState()
|
||||||
|
mod := state.EnsureModule(addrs.RootModuleInstance)
|
||||||
|
mod.SetResourceInstanceCurrent(
|
||||||
|
mustResourceInstanceAddr("test_object.x").Resource,
|
||||||
|
&states.ResourceInstanceObjectSrc{
|
||||||
|
Status: states.ObjectReady,
|
||||||
|
AttrsJSON: []byte(`{"test_string":"wrong val"}`),
|
||||||
|
},
|
||||||
|
mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`),
|
||||||
|
)
|
||||||
|
mod.SetOutputValue("from_resource", cty.StringVal("wrong val"), false)
|
||||||
|
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Providers: map[addrs.Provider]providers.Factory{
|
||||||
|
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
opts := SimplePlanOpts(plans.RefreshOnlyMode, nil)
|
||||||
|
plan, diags := ctx.Plan(m, state, opts)
|
||||||
|
assertNoErrors(t, diags)
|
||||||
|
|
||||||
|
state, diags = ctx.Apply(plan, m)
|
||||||
|
assertNoErrors(t, diags)
|
||||||
|
|
||||||
|
resCheck := state.CheckResults.GetObjectResult(mustResourceInstanceAddr("test_object.x"))
|
||||||
|
if resCheck.Status != checks.StatusPass {
|
||||||
|
t.Fatalf("unexpected check %s: %s\n", resCheck.Status, resCheck.FailureMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
outAddr := addrs.AbsOutputValue{
|
||||||
|
Module: addrs.RootModuleInstance,
|
||||||
|
OutputValue: addrs.OutputValue{
|
||||||
|
Name: "from_resource",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
outCheck := state.CheckResults.GetObjectResult(outAddr)
|
||||||
|
if outCheck.Status != checks.StatusPass {
|
||||||
|
t.Fatalf("unexpected check %s: %s\n", outCheck.Status, outCheck.FailureMessages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user