Skip to content

Commit bfd8d84

Browse files
authored
Return current state when requesting deferral. (#2570)
* Return unknown value for "object" when asking for a plan deferral * Return current state when requesting deferral of a read. * Return presuo-typed unknown value from deferred import * Bump Terraform version in deferred actions tests to the latest alpha release.
1 parent 6531356 commit bfd8d84

File tree

5 files changed

+53
-33
lines changed

5 files changed

+53
-33
lines changed

.changelog/2570.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:improvement
2+
deferred actions: return unknown value instead of nil when requesting deferral of a planned resource change.
3+
```

.github/workflows/acceptance_test_dfa.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
inputs:
1313
terraformVersion:
1414
description: Terraform version
15-
default: 1.9.0-alpha20240516
15+
default: 1.10.0-alpha20240807
1616

1717
jobs:
1818
acceptance_tests:

manifest/provider/import.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,16 @@ func (s *RawProviderServer) ImportResourceState(ctx context.Context, req *tfprot
2727

2828
cp := req.ClientCapabilities
2929
if cp != nil && cp.DeferralAllowed && s.clientConfigUnknown {
30+
v := tftypes.NewValue(tftypes.DynamicPseudoType, tftypes.UnknownValue)
31+
dv, err := tfprotov5.NewDynamicValue(v.Type(), v)
32+
if err != nil {
33+
return resp, err
34+
}
3035
// if client support it, request deferral when client configuration not fully known
36+
resp.ImportedResources = append(resp.ImportedResources, &tfprotov5.ImportedResource{
37+
TypeName: req.TypeName,
38+
State: &dv,
39+
})
3140
resp.Deferred = &tfprotov5.Deferred{
3241
Reason: tfprotov5.DeferredReasonProviderConfigUnknown,
3342
}

manifest/provider/plan.go

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,49 @@ func isImportedFlagFromPrivate(p []byte) (f bool, d []*tfprotov5.Diagnostic) {
130130
func (s *RawProviderServer) PlanResourceChange(ctx context.Context, req *tfprotov5.PlanResourceChangeRequest) (*tfprotov5.PlanResourceChangeResponse, error) {
131131
resp := &tfprotov5.PlanResourceChangeResponse{}
132132

133+
rt, err := GetResourceType(req.TypeName)
134+
if err != nil {
135+
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
136+
Severity: tfprotov5.DiagnosticSeverityError,
137+
Summary: "Failed to determine planned resource type",
138+
Detail: err.Error(),
139+
})
140+
return resp, nil
141+
}
142+
// Decode proposed resource state
143+
proposedState, err := req.ProposedNewState.Unmarshal(rt)
144+
if err != nil {
145+
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
146+
Severity: tfprotov5.DiagnosticSeverityError,
147+
Summary: "Failed to unmarshal planned resource state",
148+
Detail: err.Error(),
149+
})
150+
return resp, nil
151+
}
152+
s.logger.Trace("[PlanResourceChange]", "[ProposedState]", dump(proposedState))
153+
154+
proposedVal := make(map[string]tftypes.Value)
155+
err = proposedState.As(&proposedVal)
156+
if err != nil {
157+
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
158+
Severity: tfprotov5.DiagnosticSeverityError,
159+
Summary: "Failed to extract planned resource state from tftypes.Value",
160+
Detail: err.Error(),
161+
})
162+
return resp, nil
163+
}
164+
133165
canDeferr := req.ClientCapabilities != nil && req.ClientCapabilities.DeferralAllowed
134166

135167
if canDeferr && s.clientConfigUnknown {
136168
// if client supports it, request deferral when client configuration not fully known
169+
proposedVal["object"] = tftypes.NewValue(tftypes.DynamicPseudoType, tftypes.UnknownValue)
170+
newPlannedState := tftypes.NewValue(proposedState.Type(), proposedVal)
171+
ps, err := tfprotov5.NewDynamicValue(newPlannedState.Type(), newPlannedState)
172+
if err != nil {
173+
return resp, err
174+
}
175+
resp.PlannedState = &ps
137176
resp.Deferred = &tfprotov5.Deferred{
138177
Reason: tfprotov5.DeferredReasonProviderConfigUnknown,
139178
}
@@ -164,38 +203,6 @@ func (s *RawProviderServer) PlanResourceChange(ctx context.Context, req *tfproto
164203
return resp, nil
165204
}
166205

167-
rt, err := GetResourceType(req.TypeName)
168-
if err != nil {
169-
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
170-
Severity: tfprotov5.DiagnosticSeverityError,
171-
Summary: "Failed to determine planned resource type",
172-
Detail: err.Error(),
173-
})
174-
return resp, nil
175-
}
176-
// Decode proposed resource state
177-
proposedState, err := req.ProposedNewState.Unmarshal(rt)
178-
if err != nil {
179-
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
180-
Severity: tfprotov5.DiagnosticSeverityError,
181-
Summary: "Failed to unmarshal planned resource state",
182-
Detail: err.Error(),
183-
})
184-
return resp, nil
185-
}
186-
s.logger.Trace("[PlanResourceChange]", "[ProposedState]", dump(proposedState))
187-
188-
proposedVal := make(map[string]tftypes.Value)
189-
err = proposedState.As(&proposedVal)
190-
if err != nil {
191-
resp.Diagnostics = append(resp.Diagnostics, &tfprotov5.Diagnostic{
192-
Severity: tfprotov5.DiagnosticSeverityError,
193-
Summary: "Failed to extract planned resource state from tftypes.Value",
194-
Detail: err.Error(),
195-
})
196-
return resp, nil
197-
}
198-
199206
computedFields := make(map[string]*tftypes.AttributePath)
200207
var atp *tftypes.AttributePath
201208
cfVal, ok := proposedVal["computed_fields"]

manifest/provider/read.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func (s *RawProviderServer) ReadResource(ctx context.Context, req *tfprotov5.Rea
2323
cp := req.ClientCapabilities
2424
if cp != nil && cp.DeferralAllowed && s.clientConfigUnknown {
2525
// if client support it, request deferral when client configuration not fully known
26+
resp.NewState = req.CurrentState
2627
resp.Deferred = &tfprotov5.Deferred{
2728
Reason: tfprotov5.DeferredReasonProviderConfigUnknown,
2829
}

0 commit comments

Comments
 (0)