Skip to content

Commit 50b570f

Browse files
committed
remove state from renew/close, add deferred action support
1 parent 627a49b commit 50b570f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+525
-976
lines changed

ephemeral/close.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,12 @@ package ephemeral
55
import (
66
"github.com/hashicorp/terraform-plugin-framework/diag"
77
"github.com/hashicorp/terraform-plugin-framework/internal/privatestate"
8-
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
98
)
109

1110
// CloseRequest represents a request for the provider to close an ephemeral
1211
// resource. An instance of this request struct is supplied as an argument to
1312
// the ephemeral resource's Close function.
1413
type CloseRequest struct {
15-
// State is the object representing the values of the ephemeral
16-
// resource following the Open operation.
17-
State tfsdk.EphemeralState
18-
1914
// Private is provider-defined ephemeral resource private state data
2015
// which was previously provided by the latest Open or Renew operation.
2116
//

ephemeral/deferred.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package ephemeral
5+
6+
const (
7+
// DeferredReasonUnknown is used to indicate an invalid `DeferredReason`.
8+
// Provider developers should not use it.
9+
DeferredReasonUnknown DeferredReason = 0
10+
11+
// DeferredReasonEphemeralResourceConfigUnknown is used to indicate that the ephemeral resource configuration
12+
// is partially unknown and the real values need to be known before the change can be planned.
13+
DeferredReasonEphemeralResourceConfigUnknown DeferredReason = 1
14+
15+
// DeferredReasonProviderConfigUnknown is used to indicate that the provider configuration
16+
// is partially unknown and the real values need to be known before the change can be planned.
17+
DeferredReasonProviderConfigUnknown DeferredReason = 2
18+
19+
// DeferredReasonAbsentPrereq is used to indicate that a hard dependency has not been satisfied.
20+
DeferredReasonAbsentPrereq DeferredReason = 3
21+
)
22+
23+
// Deferred is used to indicate to Terraform that a change needs to be deferred for a reason.
24+
//
25+
// NOTE: This functionality is related to deferred action support, which is currently experimental and is subject
26+
// to change or break without warning. It is not protected by version compatibility guarantees.
27+
type Deferred struct {
28+
// Reason is the reason for deferring the change.
29+
Reason DeferredReason
30+
}
31+
32+
// DeferredReason represents different reasons for deferring a change.
33+
//
34+
// NOTE: This functionality is related to deferred action support, which is currently experimental and is subject
35+
// to change or break without warning. It is not protected by version compatibility guarantees.
36+
type DeferredReason int32
37+
38+
func (d DeferredReason) String() string {
39+
switch d {
40+
case 0:
41+
return "Unknown"
42+
case 1:
43+
return "Ephemeral Resource Config Unknown"
44+
case 2:
45+
return "Provider Config Unknown"
46+
case 3:
47+
return "Absent Prerequisite"
48+
}
49+
return "Unknown"
50+
}

ephemeral/open.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,41 @@ import (
1010
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
1111
)
1212

13+
// OpenClientCapabilities allows Terraform to publish information
14+
// regarding optionally supported protocol features for the OpenEphemeralResource RPC,
15+
// such as forward-compatible Terraform behavior changes.
16+
type OpenClientCapabilities struct {
17+
// DeferralAllowed indicates whether the Terraform client initiating
18+
// the request allows a deferral response.
19+
//
20+
// NOTE: This functionality is related to deferred action support, which is currently experimental and is subject
21+
// to change or break without warning. It is not protected by version compatibility guarantees.
22+
DeferralAllowed bool
23+
}
24+
1325
// OpenRequest represents a request for the provider to open an ephemeral
1426
// resource. An instance of this request struct is supplied as an argument to
1527
// the ephemeral resource's Open function.
1628
type OpenRequest struct {
1729
// Config is the configuration the user supplied for the ephemeral
1830
// resource.
1931
Config tfsdk.Config
32+
33+
// ClientCapabilities defines optionally supported protocol features for the
34+
// OpenEphemeralResource RPC, such as forward-compatible Terraform behavior changes.
35+
ClientCapabilities OpenClientCapabilities
2036
}
2137

2238
// OpenResponse represents a response to a OpenRequest. An
2339
// instance of this response struct is supplied as an argument
2440
// to the ephemeral resource's Open function, in which the provider
2541
// should set values on the OpenResponse as appropriate.
2642
type OpenResponse struct {
27-
// State is the object representing the values of the ephemeral
43+
// Result is the object representing the values of the ephemeral
2844
// resource following the Open operation. This field is pre-populated
2945
// from OpenRequest.Config and should be set during the resource's Open
3046
// operation.
31-
State tfsdk.EphemeralState
47+
Result tfsdk.EphemeralResultData
3248

3349
// Private is the private state ephemeral resource data following the
3450
// Open operation. This field is not pre-populated as there is no
@@ -50,4 +66,14 @@ type OpenResponse struct {
5066
// resource. An empty slice indicates a successful operation with no
5167
// warnings or errors generated.
5268
Diagnostics diag.Diagnostics
69+
70+
// Deferred indicates that Terraform should defer opening this
71+
// ephemeral resource until a followup apply operation.
72+
//
73+
// This field can only be set if
74+
// `(ephemeral.OpenRequest).ClientCapabilities.DeferralAllowed` is true.
75+
//
76+
// NOTE: This functionality is related to deferred action support, which is currently experimental and is subject
77+
// to change or break without warning. It is not protected by version compatibility guarantees.
78+
Deferred *Deferred
5379
}

ephemeral/renew.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,12 @@ import (
77

88
"github.com/hashicorp/terraform-plugin-framework/diag"
99
"github.com/hashicorp/terraform-plugin-framework/internal/privatestate"
10-
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
1110
)
1211

1312
// RenewRequest represents a request for the provider to renew an ephemeral
1413
// resource. An instance of this request struct is supplied as an argument to
1514
// the ephemeral resource's Renew function.
1615
type RenewRequest struct {
17-
// State is the object representing the values of the ephemeral
18-
// resource following the Open operation.
19-
State tfsdk.EphemeralState
20-
2116
// Private is provider-defined ephemeral resource private state data
2217
// which was previously provided by the latest Open or Renew operation.
2318
// Any existing data is copied to RenewResponse.Private to prevent

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ toolchain go1.22.7
66

77
require (
88
github.com/google/go-cmp v0.6.0
9-
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20240924154457-cd3b6654adf0
9+
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20241003195015-94a6f8ce9ce7
1010
github.com/hashicorp/terraform-plugin-log v0.9.0
1111
)
1212

@@ -29,6 +29,6 @@ require (
2929
golang.org/x/sys v0.24.0 // indirect
3030
golang.org/x/text v0.17.0 // indirect
3131
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
32-
google.golang.org/grpc v1.67.0 // indirect
32+
google.golang.org/grpc v1.67.1 // indirect
3333
google.golang.org/protobuf v1.34.2 // indirect
3434
)

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOs
1515
github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0=
1616
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
1717
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
18-
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20240924154457-cd3b6654adf0 h1:WgAlLzllo3v6BeZccPW5IETHgRylr/9y37X314C+09I=
19-
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20240924154457-cd3b6654adf0/go.mod h1:zoSM9LyEFI4iVkDeKXgwBHV0uTuIIXydtK1fy9J4wBA=
18+
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20241003195015-94a6f8ce9ce7 h1:Qrnz5z9gKKn7oDhWNKPLzl7yygiz322p1Rkzx5uqLiA=
19+
github.com/hashicorp/terraform-plugin-go v0.24.1-0.20241003195015-94a6f8ce9ce7/go.mod h1:lmP6B7frH0MrScpBN0x9kY8DSFSUWX54NmeL00knT9c=
2020
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
2121
github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
2222
github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
@@ -59,8 +59,8 @@ golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
5959
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
6060
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
6161
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
62-
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
63-
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
62+
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
63+
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
6464
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
6565
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
6666
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/fromproto5/client_capabilities.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
88

99
"github.com/hashicorp/terraform-plugin-framework/datasource"
10+
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
1011
"github.com/hashicorp/terraform-plugin-framework/provider"
1112
"github.com/hashicorp/terraform-plugin-framework/resource"
1213
)
@@ -75,3 +76,16 @@ func ImportStateClientCapabilities(in *tfprotov5.ImportResourceStateClientCapabi
7576
DeferralAllowed: in.DeferralAllowed,
7677
}
7778
}
79+
80+
func OpenEphemeralResourceClientCapabilities(in *tfprotov5.OpenEphemeralResourceClientCapabilities) ephemeral.OpenClientCapabilities {
81+
if in == nil {
82+
// Client did not indicate any supported capabilities
83+
return ephemeral.OpenClientCapabilities{
84+
DeferralAllowed: false,
85+
}
86+
}
87+
88+
return ephemeral.OpenClientCapabilities{
89+
DeferralAllowed: in.DeferralAllowed,
90+
}
91+
}

internal/fromproto5/closeephemeralresource.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ func CloseEphemeralResourceRequest(ctx context.Context, proto5 *tfprotov5.CloseE
4242
EphemeralResourceSchema: ephemeralResourceSchema,
4343
}
4444

45-
state, stateDiags := EphemeralState(ctx, proto5.State, ephemeralResourceSchema)
46-
47-
diags.Append(stateDiags...)
48-
49-
fw.State = state
50-
5145
privateData, privateDataDiags := privatestate.NewData(ctx, proto5.Private)
5246

5347
diags.Append(privateDataDiags...)

internal/fromproto5/closeephemeralresource_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"github.com/google/go-cmp/cmp"
1111
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
12-
"github.com/hashicorp/terraform-plugin-go/tftypes"
1312

1413
"github.com/hashicorp/terraform-plugin-framework/diag"
1514
"github.com/hashicorp/terraform-plugin-framework/ephemeral"
@@ -18,28 +17,11 @@ import (
1817
"github.com/hashicorp/terraform-plugin-framework/internal/fwschema"
1918
"github.com/hashicorp/terraform-plugin-framework/internal/fwserver"
2019
"github.com/hashicorp/terraform-plugin-framework/internal/privatestate"
21-
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
2220
)
2321

2422
func TestCloseEphemeralResourceRequest(t *testing.T) {
2523
t.Parallel()
2624

27-
testProto5Type := tftypes.Object{
28-
AttributeTypes: map[string]tftypes.Type{
29-
"test_attribute": tftypes.String,
30-
},
31-
}
32-
33-
testProto5Value := tftypes.NewValue(testProto5Type, map[string]tftypes.Value{
34-
"test_attribute": tftypes.NewValue(tftypes.String, "test-value"),
35-
})
36-
37-
testProto5DynamicValue, err := tfprotov5.NewDynamicValue(testProto5Type, testProto5Value)
38-
39-
if err != nil {
40-
t.Fatalf("unexpected error calling tfprotov5.NewDynamicValue(): %s", err)
41-
}
42-
4325
testFwSchema := schema.Schema{
4426
Attributes: map[string]schema.Attribute{
4527
"test_attribute": schema.StringAttribute{
@@ -97,34 +79,6 @@ func TestCloseEphemeralResourceRequest(t *testing.T) {
9779
EphemeralResourceSchema: testFwSchema,
9880
},
9981
},
100-
"state-missing-schema": {
101-
input: &tfprotov5.CloseEphemeralResourceRequest{
102-
State: &testProto5DynamicValue,
103-
},
104-
expected: nil,
105-
expectedDiagnostics: diag.Diagnostics{
106-
diag.NewErrorDiagnostic(
107-
"Missing EphemeralResource Schema",
108-
"An unexpected error was encountered when handling the request. "+
109-
"This is always an issue in terraform-plugin-framework used to implement the provider and should be reported to the provider developers.\n\n"+
110-
"Please report this to the provider developer:\n\n"+
111-
"Missing schema.",
112-
),
113-
},
114-
},
115-
"state": {
116-
input: &tfprotov5.CloseEphemeralResourceRequest{
117-
State: &testProto5DynamicValue,
118-
},
119-
ephemeralResourceSchema: testFwSchema,
120-
expected: &fwserver.CloseEphemeralResourceRequest{
121-
State: &tfsdk.EphemeralState{
122-
Raw: testProto5Value,
123-
Schema: testFwSchema,
124-
},
125-
EphemeralResourceSchema: testFwSchema,
126-
},
127-
},
12882
}
12983

13084
for name, testCase := range testCases {

internal/fromproto5/ephemeral_state.go renamed to internal/fromproto5/ephemeral_result_data.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
1414
)
1515

16-
// EphemeralState returns the *tfsdk.EphemeralState for a *tfprotov5.DynamicValue and
16+
// EphemeralResultData returns the *tfsdk.EphemeralResultData for a *tfprotov5.DynamicValue and
1717
// fwschema.Schema.
18-
func EphemeralState(ctx context.Context, proto5DynamicValue *tfprotov5.DynamicValue, schema fwschema.Schema) (*tfsdk.EphemeralState, diag.Diagnostics) {
18+
func EphemeralResultData(ctx context.Context, proto5DynamicValue *tfprotov5.DynamicValue, schema fwschema.Schema) (*tfsdk.EphemeralResultData, diag.Diagnostics) {
1919
if proto5DynamicValue == nil {
2020
return nil, nil
2121
}
@@ -26,8 +26,8 @@ func EphemeralState(ctx context.Context, proto5DynamicValue *tfprotov5.DynamicVa
2626
// This should not happen, but just in case.
2727
if schema == nil {
2828
diags.AddError(
29-
"Unable to Convert Ephemeral State",
30-
"An unexpected error was encountered when converting the ephemeral state from the protocol type. "+
29+
"Unable to Convert Ephemeral Result Data",
30+
"An unexpected error was encountered when converting the ephemeral result data from the protocol type. "+
3131
"This is always an issue in terraform-plugin-framework used to implement the provider and should be reported to the provider developers.\n\n"+
3232
"Please report this to the provider developer:\n\n"+
3333
"Missing schema.",
@@ -36,15 +36,15 @@ func EphemeralState(ctx context.Context, proto5DynamicValue *tfprotov5.DynamicVa
3636
return nil, diags
3737
}
3838

39-
data, dynamicValueDiags := DynamicValue(ctx, proto5DynamicValue, schema, fwschemadata.DataDescriptionEphemeralState)
39+
data, dynamicValueDiags := DynamicValue(ctx, proto5DynamicValue, schema, fwschemadata.DataDescriptionEphemeralResultData)
4040

4141
diags.Append(dynamicValueDiags...)
4242

4343
if diags.HasError() {
4444
return nil, diags
4545
}
4646

47-
fw := &tfsdk.EphemeralState{
47+
fw := &tfsdk.EphemeralResultData{
4848
Raw: data.TerraformValue,
4949
Schema: schema,
5050
}

0 commit comments

Comments
 (0)