Skip to content

Commit c3810b1

Browse files
authored
Simplify actions to one schema type (#559)
* Update protocol v5 to remove other action types * Update protocol v6 to remove other action types * update protoc version * downgrade protoc version * Remove additional references to linked actions
1 parent 0d697e5 commit c3810b1

28 files changed

+1148
-3449
lines changed

tfprotov5/action.go

Lines changed: 12 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,12 @@ type ActionServer interface {
2424
ValidateActionConfig(context.Context, *ValidateActionConfigRequest) (*ValidateActionConfigResponse, error)
2525

2626
// PlanAction is called when Terraform is attempting to
27-
// calculate a plan for an action. Depending on the type defined in
28-
// the action schema, Terraform may also pass the plan of linked resources
29-
// that the action can modify or return unmodified to influence Terraform's plan.
27+
// calculate a plan for an action.
3028
PlanAction(context.Context, *PlanActionRequest) (*PlanActionResponse, error)
3129

3230
// InvokeAction is called when Terraform wants to execute the logic of an action.
33-
// Depending on the type defined in the action schema, Terraform may also pass the
34-
// state of linked resources. The provider runs the logic of the action, reporting progress
35-
// events as desired, then sends a final complete event that has the linked resource's resulting
36-
// state and identity.
31+
// The provider runs the logic of the action, reporting progress
32+
// events as desired, then sends a final complete event.
3733
//
3834
// If an error occurs, the provider sends a complete event with the relevant diagnostics.
3935
InvokeAction(context.Context, *InvokeActionRequest) (*InvokeActionServerStream, error)
@@ -57,30 +53,6 @@ type ValidateActionConfigRequest struct {
5753
// from knowing the value at request time. Any attributes not directly
5854
// set in the configuration will be null.
5955
Config *DynamicValue
60-
61-
// LinkedResources contains the configuration data of the managed resource types that are linked to this action.
62-
//
63-
// - If the action schema type is Unlinked, this field will be empty.
64-
LinkedResources []*LinkedResourceConfig
65-
}
66-
67-
// LinkedResourceConfig represents linked resource config data used in the ValidateActionConfig RPC.
68-
type LinkedResourceConfig struct {
69-
// TypeName is the type of linked resource Terraform is validating.
70-
TypeName string
71-
72-
// Config is the configuration the user supplied for the linked resource. See
73-
// the documentation on `DynamicValue` for more information about
74-
// safely accessing the configuration.
75-
//
76-
// The configuration is represented as a tftypes.Object, with each
77-
// attribute and nested block getting its own key and value.
78-
//
79-
// This configuration may contain unknown values if a user uses
80-
// interpolation or other functionality that would prevent Terraform
81-
// from knowing the value at request time. Any attributes not directly
82-
// set in the configuration will be null.
83-
Config *DynamicValue
8456
}
8557

8658
// ValidateActionConfigResponse is the response from the provider about
@@ -98,11 +70,6 @@ type PlanActionRequest struct {
9870
// ActionType is the name of the action being called.
9971
ActionType string
10072

101-
// LinkedResources contains the data of the managed resource types that are linked to this action.
102-
//
103-
// - If the action schema type is Unlinked, this field will be empty.
104-
LinkedResources []*ProposedLinkedResource
105-
10673
// Config is the configuration the user supplied for the action. See
10774
// the documentation on `DynamicValue` for more information about
10875
// safely accessing the configuration.
@@ -113,43 +80,9 @@ type PlanActionRequest struct {
11380
ClientCapabilities *PlanActionClientCapabilities
11481
}
11582

116-
// ProposedLinkedResource represents linked resource data before PlanAction is called.
117-
type ProposedLinkedResource struct {
118-
// PriorState is the state of the linked resource before the plan is applied,
119-
// represented as a `DynamicValue`. See the documentation for
120-
// `DynamicValue` for information about safely accessing the state.
121-
PriorState *DynamicValue
122-
123-
// PlannedState is the latest indication of what the state for the
124-
// linked resource should be after apply, represented as a `DynamicValue`.
125-
// See the documentation for `DynamicValue` for information about safely
126-
// accessing the planned state.
127-
//
128-
// Since PlannedState is the most recent plan for the linked resource, it could
129-
// be the result of an RPC call to PlanResourceChange or an RPC call to PlanAction
130-
// for a predecessor action
131-
PlannedState *DynamicValue
132-
133-
// Config is the configuration the user supplied for the linked resource. See
134-
// the documentation on `DynamicValue` for more information about
135-
// safely accessing the configuration.
136-
Config *DynamicValue
137-
138-
// PriorIdentity is the identity of the resource before the plan is
139-
// applied, represented as a `ResourceIdentityData`.
140-
PriorIdentity *ResourceIdentityData
141-
}
142-
143-
// PlanActionResponse is the response from the provider when planning an action. If the action
144-
// has linked resources, it will contain any modifications made to the planned state or identity.
83+
// PlanActionResponse is the response from the provider when planning an action.
14584
type PlanActionResponse struct {
146-
// LinkedResources contains the provider modified data of the managed resource types that are linked to this action.
147-
//
148-
// This field is not currently in-use, but future action schema types will use this field to plan modifications of state data for linked resources.
149-
LinkedResources []*PlannedLinkedResource
150-
151-
// Diagnostics report errors or warnings related to plannning the action and calculating
152-
// the planned state of the requested linked resources. Returning an empty slice
85+
// Diagnostics report errors or warnings related to planning the action. Returning an empty slice
15386
// indicates a successful validation with no warnings or errors generated.
15487
Diagnostics []*Diagnostic
15588

@@ -158,61 +91,20 @@ type PlanActionResponse struct {
15891
Deferred *Deferred
15992
}
16093

161-
// PlannedLinkedResource represents linked resource data that was planned during PlanAction and returned.
162-
type PlannedLinkedResource struct {
163-
// PlannedState is the provider's indication of what the state for the
164-
// linked resource should be after apply, represented as a `DynamicValue`. See
165-
// the documentation for `DynamicValue` for information about safely
166-
// creating the `DynamicValue`.
167-
PlannedState *DynamicValue
168-
169-
// PlannedIdentity is the provider's indication of what the identity for the
170-
// linked resource should be after apply, represented as a `ResourceIdentityData`
171-
PlannedIdentity *ResourceIdentityData
172-
}
173-
17494
// InvokeActionRequest is the request Terraform sends when it wants to execute
17595
// the logic of an action.
17696
type InvokeActionRequest struct {
17797
// ActionType is the name of the action being called.
17898
ActionType string
17999

180-
// LinkedResources contains the data of the managed resource types that are linked to this action.
181-
//
182-
// - If the action schema type is Unlinked, this field will be empty.
183-
LinkedResources []*InvokeLinkedResource
184-
185100
// Config is the configuration the user supplied for the action. See
186101
// the documentation on `DynamicValue` for more information about
187102
// safely accessing the configuration.
188103
Config *DynamicValue
189-
}
190-
191-
// InvokeLinkedResource represents linked resource data before InvokeAction is called.
192-
type InvokeLinkedResource struct {
193-
// PriorState is the state of the linked resource before changes are applied,
194-
// represented as a `DynamicValue`. See the documentation for
195-
// `DynamicValue` for information about safely accessing the state.
196-
PriorState *DynamicValue
197-
198-
// PlannedState is the latest indication of what the state for the
199-
// linked resource should look like after changes are applied, represented
200-
// as a `DynamicValue`. See the documentation for `DynamicValue` for
201-
// information about safely accessing the planned state.
202-
//
203-
// Since PlannedState is the most recent state for the linked resource, it could
204-
// be the result of an RPC call to ApplyResourceChange or an RPC call to InvokeAction
205-
// for a predecessor action.
206-
PlannedState *DynamicValue
207104

208-
// Config is the configuration the user supplied for the linked resource. See
209-
// the documentation on `DynamicValue` for more information about
210-
// safely accessing the configuration.
211-
Config *DynamicValue
212-
213-
// PlannedIdentity is Terraform's plan for what the linked resource identity should
214-
// look like after the changes are applied, represented as a `ResourceIdentityData`.
215-
PlannedIdentity *ResourceIdentityData
105+
// ClientCapabilities defines optionally supported protocol features for the
106+
// InvokeAction RPC, such as forward-compatible Terraform behavior changes.
107+
ClientCapabilities *InvokeActionClientCapabilities
216108
}
217109

218110
// InvokeActionServerStream represents a streaming response to an
@@ -222,8 +114,8 @@ type InvokeLinkedResource struct {
222114
type InvokeActionServerStream struct {
223115
// Events is the iterator that the provider can stream progress messages back to Terraform
224116
// as the action is executing. Once the provider has completed the action invocation, the provider must
225-
// respond with a completed event with the new linked resource state or diagnostics explaining why
226-
// the action failed.
117+
// respond with a completed event. If the action failed, the completed event must contain
118+
// diagnostics explaining why the action failed.
227119
Events iter.Seq[InvokeActionEvent]
228120
}
229121

@@ -255,42 +147,13 @@ type ProgressInvokeActionEventType struct {
255147

256148
func (a ProgressInvokeActionEventType) isInvokeActionEventType() {}
257149

258-
// CompletedInvokeActionEventType represents the final completed event, along with all of the linked resource
259-
// data modified by the provider or diagnostics about an action invocation failure.
150+
// CompletedInvokeActionEventType represents the final completed event, along with
151+
// potential diagnostics about an action invocation failure.
260152
type CompletedInvokeActionEventType struct {
261-
// LinkedResources contains the provider modified data of the managed resource types that are linked to this action.
262-
//
263-
// This field is not currently in-use, but future action schema types will use this field to modify state data for linked resources.
264-
LinkedResources []*NewLinkedResource
265-
266153
// Diagnostics report errors or warnings related to invoking an action.
267154
// Returning an empty slice indicates a successful invocation with no warnings
268155
// or errors generated.
269156
Diagnostics []*Diagnostic
270157
}
271158

272159
func (a CompletedInvokeActionEventType) isInvokeActionEventType() {}
273-
274-
// NewLinkedResource represents linked resource data that was changed during InvokeAction and returned.
275-
//
276-
// Depending on how the action was invoked, the modified state data will either be immediately recorded in
277-
// state or reconcicled in a future terraform apply operation.
278-
type NewLinkedResource struct {
279-
// NewState is the provider's understanding of what the linked resource's
280-
// state is after changes are applied, represented as a `DynamicValue`.
281-
// See the documentation for `DynamicValue` for information about
282-
// safely creating the `DynamicValue`.
283-
//
284-
// Any attribute, whether computed or not, that has a known value in
285-
// the PlannedState in the InvokeActionRequest must be preserved
286-
// exactly as it was in NewState.
287-
NewState *DynamicValue
288-
289-
// NewIdentity is the provider's understanding of what the linked resource's
290-
// identity is after changes are applied, represented as a `ResourceIdentityData`.
291-
NewIdentity *ResourceIdentityData
292-
293-
// RequiresReplace can only be set if diagnostics are returned for the action and indicate
294-
// the linked resource must be replaced as a result of the action invocation error.
295-
RequiresReplace bool
296-
}

tfprotov5/action_schema.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,8 @@
33

44
package tfprotov5
55

6-
// ActionSchema is how Terraform defines the shape of action data and
7-
// how the practitioner can interact with the action.
6+
// ActionSchema is how Terraform defines the shape of action data.
87
type ActionSchema struct {
98
// Schema is the definition for the action data itself, which will be specified in an action block in the user's configuration.
109
Schema *Schema
11-
12-
// Type defines how a practitioner can trigger an action, as well as what effect the action can have on the state
13-
// of the linked managed resources. There is currently only one type of action supported:
14-
// - Unlinked actions are actions that cannot cause changes to resource states.
15-
Type ActionSchemaType
16-
}
17-
18-
// ActionSchemaType is an intentionally unimplementable interface that
19-
// functions as an enum, allowing us to use different strongly-typed action schema types
20-
// that contain additional, but different data, as a generic "action" type.
21-
//
22-
// An action can currently only be one type (Unlinked), which is statically defined in the protocol. Future action types
23-
// will be added to the protocol first, then implemented in this package.
24-
type ActionSchemaType interface {
25-
isActionSchemaType()
2610
}
27-
28-
var (
29-
_ ActionSchemaType = UnlinkedActionSchemaType{}
30-
)
31-
32-
// UnlinkedActionSchemaType represents an unlinked action, which cannot cause changes to resource states.
33-
type UnlinkedActionSchemaType struct{}
34-
35-
func (a UnlinkedActionSchemaType) isActionSchemaType() {}

tfprotov5/client_capabilities.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,12 @@ type PlanActionClientCapabilities struct {
7474
// handle deferred responses from the provider.
7575
DeferralAllowed bool
7676
}
77+
78+
// InvokeActionClientCapabilities allows Terraform to publish information
79+
// regarding optionally supported protocol features for the InvokeAction RPC,
80+
// such as forward-compatible Terraform behavior changes.
81+
//
82+
// Maintainer Note: This is in the protocol in Terraform Core,
83+
// but currently they are not sending any capabilities for this RPC.
84+
type InvokeActionClientCapabilities struct {
85+
}

tfprotov5/internal/fromproto/action.go

Lines changed: 5 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,79 +14,34 @@ func ValidateActionConfigRequest(in *tfplugin5.ValidateActionConfig_Request) *tf
1414
}
1515

1616
return &tfprotov5.ValidateActionConfigRequest{
17-
ActionType: in.ActionType,
18-
Config: DynamicValue(in.Config),
19-
LinkedResources: LinkedResourceConfigs(in.LinkedResources),
17+
ActionType: in.ActionType,
18+
Config: DynamicValue(in.Config),
2019
}
2120
}
2221

23-
func LinkedResourceConfigs(in []*tfplugin5.LinkedResourceConfig) []*tfprotov5.LinkedResourceConfig {
24-
resp := make([]*tfprotov5.LinkedResourceConfig, 0, len(in))
25-
26-
for _, inLinkedResource := range in {
27-
resp = append(resp, &tfprotov5.LinkedResourceConfig{
28-
TypeName: inLinkedResource.TypeName,
29-
Config: DynamicValue(inLinkedResource.Config),
30-
})
31-
}
32-
33-
return resp
34-
}
35-
3622
func PlanActionRequest(in *tfplugin5.PlanAction_Request) *tfprotov5.PlanActionRequest {
3723
if in == nil {
3824
return nil
3925
}
4026

4127
resp := &tfprotov5.PlanActionRequest{
4228
ActionType: in.ActionType,
43-
LinkedResources: ProposedLinkedResources(in.LinkedResources),
4429
Config: DynamicValue(in.Config),
4530
ClientCapabilities: PlanActionClientCapabilities(in.ClientCapabilities),
4631
}
4732

4833
return resp
4934
}
5035

51-
func ProposedLinkedResources(in []*tfplugin5.PlanAction_Request_LinkedResource) []*tfprotov5.ProposedLinkedResource {
52-
resp := make([]*tfprotov5.ProposedLinkedResource, 0, len(in))
53-
54-
for _, inLinkedResource := range in {
55-
resp = append(resp, &tfprotov5.ProposedLinkedResource{
56-
PriorState: DynamicValue(inLinkedResource.PriorState),
57-
PlannedState: DynamicValue(inLinkedResource.PlannedState),
58-
Config: DynamicValue(inLinkedResource.Config),
59-
PriorIdentity: ResourceIdentityData(inLinkedResource.PriorIdentity),
60-
})
61-
}
62-
63-
return resp
64-
}
65-
6636
func InvokeActionRequest(in *tfplugin5.InvokeAction_Request) *tfprotov5.InvokeActionRequest {
6737
if in == nil {
6838
return nil
6939
}
7040

7141
resp := &tfprotov5.InvokeActionRequest{
72-
ActionType: in.ActionType,
73-
LinkedResources: InvokeLinkedResources(in.LinkedResources),
74-
Config: DynamicValue(in.Config),
75-
}
76-
77-
return resp
78-
}
79-
80-
func InvokeLinkedResources(in []*tfplugin5.InvokeAction_Request_LinkedResource) []*tfprotov5.InvokeLinkedResource {
81-
resp := make([]*tfprotov5.InvokeLinkedResource, 0, len(in))
82-
83-
for _, inLinkedResource := range in {
84-
resp = append(resp, &tfprotov5.InvokeLinkedResource{
85-
PriorState: DynamicValue(inLinkedResource.PriorState),
86-
PlannedState: DynamicValue(inLinkedResource.PlannedState),
87-
Config: DynamicValue(inLinkedResource.Config),
88-
PlannedIdentity: ResourceIdentityData(inLinkedResource.PlannedIdentity),
89-
})
42+
ActionType: in.ActionType,
43+
Config: DynamicValue(in.Config),
44+
ClientCapabilities: InvokeActionClientCapabilities(in.ClientCapabilities),
9045
}
9146

9247
return resp

0 commit comments

Comments
 (0)