Skip to content

Commit

Permalink
deferred actions: implement latest provider protocol changes (#35063)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamcervante authored Apr 24, 2024
1 parent f0843ca commit 055dd27
Show file tree
Hide file tree
Showing 9 changed files with 2,238 additions and 2,016 deletions.
29 changes: 15 additions & 14 deletions docs/plugin-protocol/tfplugin5.6.proto
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ message ServerCapabilities {
bool move_resource_state = 3;
}

// ClientCapabilities allows Terraform to publish information regarding
// supported protocol features. This is used to indicate availability of
// certain forward-compatible changes which may be optional in a major
// protocol version, but cannot be tested for directly.
message ClientCapabilities {
// The deferral_allowed capability signals that the client is able to
// handle deferred responses from the provider.
bool deferral_allowed = 1;
}

message Function {
// parameters is the ordered list of positional function parameters.
repeated Parameter parameters = 1;
Expand Down Expand Up @@ -382,6 +392,7 @@ message Configure {
message Request {
string terraform_version = 1;
DynamicValue config = 2;
ClientCapabilities client_capabilities = 3;
}
message Response {
repeated Diagnostic diagnostics = 1;
Expand All @@ -402,10 +413,7 @@ message ReadResource {
DynamicValue current_state = 2;
bytes private = 3;
DynamicValue provider_meta = 4;

// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 5;
ClientCapabilities client_capabilities = 5;
}
message Response {
DynamicValue new_state = 1;
Expand All @@ -425,10 +433,7 @@ message PlanResourceChange {
DynamicValue config = 4;
bytes prior_private = 5;
DynamicValue provider_meta = 6;

// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 7;
ClientCapabilities client_capabilities = 7;
}

message Response {
Expand Down Expand Up @@ -490,9 +495,7 @@ message ImportResourceState {
message Request {
string type_name = 1;
string id = 2;
// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 3;
ClientCapabilities client_capabilities = 3;
}

message ImportedResource {
Expand Down Expand Up @@ -551,9 +554,7 @@ message ReadDataSource {
string type_name = 1;
DynamicValue config = 2;
DynamicValue provider_meta = 3;
// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 4;
ClientCapabilities client_capabilities = 4;
}
message Response {
DynamicValue state = 1;
Expand Down
28 changes: 15 additions & 13 deletions docs/plugin-protocol/tfplugin6.6.proto
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,16 @@ message ServerCapabilities {
bool move_resource_state = 3;
}

// ClientCapabilities allows Terraform to publish information regarding
// supported protocol features. This is used to indicate availability of
// certain forward-compatible changes which may be optional in a major
// protocol version, but cannot be tested for directly.
message ClientCapabilities {
// The deferral_allowed capability signals that the client is able to
// handle deferred responses from the provider.
bool deferral_allowed = 1;
}

// Deferred is a message that indicates that change is deferred for a reason.
message Deferred {
// Reason is the reason for deferring the change.
Expand Down Expand Up @@ -400,6 +410,7 @@ message ConfigureProvider {
message Request {
string terraform_version = 1;
DynamicValue config = 2;
ClientCapabilities client_capabilities = 3;
}
message Response {
repeated Diagnostic diagnostics = 1;
Expand All @@ -420,9 +431,7 @@ message ReadResource {
DynamicValue current_state = 2;
bytes private = 3;
DynamicValue provider_meta = 4;
// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 5;
ClientCapabilities client_capabilities = 5;
}
message Response {
DynamicValue new_state = 1;
Expand All @@ -442,10 +451,7 @@ message PlanResourceChange {
DynamicValue config = 4;
bytes prior_private = 5;
DynamicValue provider_meta = 6;

// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 7;
ClientCapabilities client_capabilities = 7;
}

message Response {
Expand Down Expand Up @@ -506,9 +512,7 @@ message ImportResourceState {
message Request {
string type_name = 1;
string id = 2;
// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 3;
ClientCapabilities client_capabilities = 3;
}

message ImportedResource {
Expand Down Expand Up @@ -567,9 +571,7 @@ message ReadDataSource {
string type_name = 1;
DynamicValue config = 2;
DynamicValue provider_meta = 3;
// deferral_allowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
bool deferral_allowed = 4;
ClientCapabilities client_capabilities = 4;
}
message Response {
DynamicValue state = 1;
Expand Down
21 changes: 15 additions & 6 deletions internal/plugin/grpc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ func (p *GRPCProvider) ConfigureProvider(r providers.ConfigureProviderRequest) (
Config: &proto.DynamicValue{
Msgpack: mp,
},
ClientCapabilities: &proto.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

protoResp, err := p.client.Configure(p.ctx, protoReq)
Expand Down Expand Up @@ -399,10 +402,12 @@ func (p *GRPCProvider) ReadResource(r providers.ReadResourceRequest) (resp provi
}

protoReq := &proto.ReadResource_Request{
TypeName: r.TypeName,
CurrentState: &proto.DynamicValue{Msgpack: mp},
Private: r.Private,
DeferralAllowed: r.DeferralAllowed,
TypeName: r.TypeName,
CurrentState: &proto.DynamicValue{Msgpack: mp},
Private: r.Private,
ClientCapabilities: &proto.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down Expand Up @@ -483,7 +488,9 @@ func (p *GRPCProvider) PlanResourceChange(r providers.PlanResourceChangeRequest)
Config: &proto.DynamicValue{Msgpack: configMP},
ProposedNewState: &proto.DynamicValue{Msgpack: propMP},
PriorPrivate: r.PriorPrivate,
DeferralAllowed: r.DeferralAllowed,
ClientCapabilities: &proto.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down Expand Up @@ -724,7 +731,9 @@ func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp p
Config: &proto.DynamicValue{
Msgpack: config,
},
DeferralAllowed: r.DeferralAllowed,
ClientCapabilities: &proto.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down
21 changes: 15 additions & 6 deletions internal/plugin6/grpc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ func (p *GRPCProvider) ConfigureProvider(r providers.ConfigureProviderRequest) (
Config: &proto6.DynamicValue{
Msgpack: mp,
},
ClientCapabilities: &proto6.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

protoResp, err := p.client.ConfigureProvider(p.ctx, protoReq)
Expand Down Expand Up @@ -388,10 +391,12 @@ func (p *GRPCProvider) ReadResource(r providers.ReadResourceRequest) (resp provi
}

protoReq := &proto6.ReadResource_Request{
TypeName: r.TypeName,
CurrentState: &proto6.DynamicValue{Msgpack: mp},
Private: r.Private,
DeferralAllowed: r.DeferralAllowed,
TypeName: r.TypeName,
CurrentState: &proto6.DynamicValue{Msgpack: mp},
Private: r.Private,
ClientCapabilities: &proto6.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down Expand Up @@ -472,7 +477,9 @@ func (p *GRPCProvider) PlanResourceChange(r providers.PlanResourceChangeRequest)
Config: &proto6.DynamicValue{Msgpack: configMP},
ProposedNewState: &proto6.DynamicValue{Msgpack: propMP},
PriorPrivate: r.PriorPrivate,
DeferralAllowed: r.DeferralAllowed,
ClientCapabilities: &proto6.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down Expand Up @@ -713,7 +720,9 @@ func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp p
Config: &proto6.DynamicValue{
Msgpack: config,
},
DeferralAllowed: r.DeferralAllowed,
ClientCapabilities: &proto6.ClientCapabilities{
DeferralAllowed: r.ClientCapabilities.DeferralAllowed,
},
}

if metaSchema.Block != nil {
Expand Down
28 changes: 19 additions & 9 deletions internal/providers/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ type ServerCapabilities struct {
MoveResourceState bool
}

// ClientCapabilities allows Terraform to publish information regarding
// supported protocol features. This is used to indicate availability of
// certain forward-compatible changes which may be optional in a major
// protocol version, but cannot be tested for directly.
type ClientCapabilities struct {
// The deferral_allowed capability signals that the client is able to
// handle deferred responses from the provider.
DeferralAllowed bool
}

type ValidateProviderConfigRequest struct {
// Config is the raw configuration value for the provider.
Config cty.Value
Expand Down Expand Up @@ -214,6 +224,9 @@ type ConfigureProviderRequest struct {

// Config is the complete configuration value for the provider.
Config cty.Value

// ClientCapabilities contains information about the client's capabilities.
ClientCapabilities ClientCapabilities
}

type ConfigureProviderResponse struct {
Expand All @@ -238,9 +251,8 @@ type ReadResourceRequest struct {
// HashiCorp. It is considered experimental and subject to change.
ProviderMeta cty.Value

// DeferralAllowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
DeferralAllowed bool
// ClientCapabilities contains information about the client's capabilities.
ClientCapabilities ClientCapabilities
}

// DeferredReason is a string that describes why a resource was deferred.
Expand Down Expand Up @@ -325,9 +337,8 @@ type PlanResourceChangeRequest struct {
// HashiCorp. It is considered experimental and subject to change.
ProviderMeta cty.Value

// DeferralAllowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
DeferralAllowed bool
// ClientCapabilities contains information about the client's capabilities.
ClientCapabilities ClientCapabilities
}

type PlanResourceChangeResponse struct {
Expand Down Expand Up @@ -517,9 +528,8 @@ type ReadDataSourceRequest struct {
// HashiCorp. It is considered experimental and subject to change.
ProviderMeta cty.Value

// DeferralAllowed signals that the provider is allowed to defer the
// changes. If set the caller needs to handle the deferred response.
DeferralAllowed bool
// ClientCapabilities contains information about the client's capabilities.
ClientCapabilities ClientCapabilities
}

type ReadDataSourceResponse struct {
Expand Down
3 changes: 3 additions & 0 deletions internal/terraform/eval_context_builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, c
req := providers.ConfigureProviderRequest{
TerraformVersion: version.String(),
Config: cfg,
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
}

resp := p.ConfigureProvider(req)
Expand Down
34 changes: 22 additions & 12 deletions internal/terraform/node_resource_abstract_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,9 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState
ProposedNewState: nullVal,
PriorPrivate: currentState.Private,
ProviderMeta: metaConfigVal,
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
})
deferred = resp.Deferred

Expand Down Expand Up @@ -646,11 +648,13 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state
}
} else {
resp = provider.ReadResource(providers.ReadResourceRequest{
TypeName: n.Addr.Resource.Resource.Type,
PriorState: priorVal,
Private: state.Private,
ProviderMeta: metaConfigVal,
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
TypeName: n.Addr.Resource.Resource.Type,
PriorState: priorVal,
Private: state.Private,
ProviderMeta: metaConfigVal,
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
})

if resp.Deferred != nil {
Expand Down Expand Up @@ -931,7 +935,9 @@ func (n *NodeAbstractResourceInstance) plan(
ProposedNewState: proposedNewVal,
PriorPrivate: priorPrivate,
ProviderMeta: metaConfigVal,
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
})
}
diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config, n.Addr.String()))
Expand Down Expand Up @@ -1086,7 +1092,9 @@ func (n *NodeAbstractResourceInstance) plan(
ProposedNewState: proposedNewVal,
PriorPrivate: plannedPrivate,
ProviderMeta: metaConfigVal,
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
})
}
// We need to tread carefully here, since if there are any warnings
Expand Down Expand Up @@ -1519,10 +1527,12 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
}
} else {
resp = provider.ReadDataSource(providers.ReadDataSourceRequest{
TypeName: n.Addr.ContainingResource().Resource.Type,
Config: configVal,
ProviderMeta: metaConfigVal,
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
TypeName: n.Addr.ContainingResource().Resource.Type,
Config: configVal,
ProviderMeta: metaConfigVal,
ClientCapabilities: providers.ClientCapabilities{
DeferralAllowed: ctx.Deferrals().DeferralAllowed(),
},
})

if resp.Deferred != nil {
Expand Down
Loading

0 comments on commit 055dd27

Please sign in to comment.