rpcapi: Stack plan and apply use the same progress message type

Previously we had the progress messages directly inlined as events of the
PlanStackChanges operation, but that means that there's no common
interface type for progress events across both the plan and apply phases,
making it hard for Go implementations to share marshaling code between
the two phases.

Now we'll use a new StackChangeProgress message type to contain all of
the progress message situations. This makes constructing and using the
progress messages a little more verbose -- an extra layer of message --
but means that we can write code that works generically with the
StackChangeProgress generated struct and thus share it between the two
phases, leading to less code overall.

As of this commit we don't yet have the apply phase generating any
progress messages, but we'll extend it in a subsequent commit now that
it's possible to share more of that event-generating code between the
two phases.
pull/34738/head
Martin Atkins 3 years ago
parent 1943ed2395
commit 947c483c49

@ -484,10 +484,14 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
ias = append(ias, ia.String())
}
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_ComponentInstances{
ComponentInstances: &terraform1.ComponentInstances{
ComponentAddr: ce.ComponentAddr.String(),
InstanceAddrs: ias,
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: &terraform1.StackChangeProgress{
Event: &terraform1.StackChangeProgress_ComponentInstances_{
ComponentInstances: &terraform1.StackChangeProgress_ComponentInstances{
ComponentAddr: ce.ComponentAddr.String(),
InstanceAddrs: ias,
},
},
},
},
})
@ -497,22 +501,38 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
// client, reporting the status of the plan operation. We also create a
// nested tracing span for the component instance.
PendingComponentInstancePlan: func(ctx context.Context, ci stackaddrs.AbsComponentInstance) {
evts.Send(evtComponentInstanceStatus(ci, hooks.ComponentInstancePending))
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: evtComponentInstanceStatus(ci, hooks.ComponentInstancePending),
},
})
},
BeginComponentInstancePlan: func(ctx context.Context, ci stackaddrs.AbsComponentInstance) any {
evts.Send(evtComponentInstanceStatus(ci, hooks.ComponentInstancePlanning))
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: evtComponentInstanceStatus(ci, hooks.ComponentInstancePlanning),
},
})
_, span := tracer.Start(ctx, "planning", trace.WithAttributes(
attribute.String("component_instance", ci.String()),
))
return span
},
EndComponentInstancePlan: func(ctx context.Context, span any, ci stackaddrs.AbsComponentInstance) any {
evts.Send(evtComponentInstanceStatus(ci, hooks.ComponentInstancePlanned))
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: evtComponentInstanceStatus(ci, hooks.ComponentInstancePlanned),
},
})
span.(trace.Span).End()
return nil
},
ErrorComponentInstancePlan: func(ctx context.Context, span any, ci stackaddrs.AbsComponentInstance) any {
evts.Send(evtComponentInstanceStatus(ci, hooks.ComponentInstanceErrored))
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: evtComponentInstanceStatus(ci, hooks.ComponentInstanceErrored),
},
})
span.(trace.Span).End()
return nil
},
@ -521,13 +541,17 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
// forward it to the events client.
ReportResourceInstanceStatus: func(ctx context.Context, span any, rihd *hooks.ResourceInstanceStatusHookData) any {
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_ResourceInstanceStatus{
ResourceInstanceStatus: &terraform1.ResourceInstanceStatus{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: rihd.Addr.Component.String(),
ResourceInstanceAddr: rihd.Addr.Item.String(),
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: &terraform1.StackChangeProgress{
Event: &terraform1.StackChangeProgress_ResourceInstanceStatus_{
ResourceInstanceStatus: &terraform1.StackChangeProgress_ResourceInstanceStatus{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: rihd.Addr.Component.String(),
ResourceInstanceAddr: rihd.Addr.Item.String(),
},
Status: rihd.Status.ForProtobuf(),
},
},
Status: rihd.Status.ForProtobuf(),
},
},
})
@ -543,7 +567,7 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
return span
}
moved := &terraform1.ResourceInstancePlannedChange_Moved{}
moved := &terraform1.StackChangeProgress_ResourceInstancePlannedChange_Moved{}
if !ric.Change.PrevRunAddr.Equal(ric.Change.Addr) {
moved.PrevAddr = &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: ric.Addr.Component.String(),
@ -551,21 +575,25 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
}
}
imported := &terraform1.ResourceInstancePlannedChange_Imported{}
imported := &terraform1.StackChangeProgress_ResourceInstancePlannedChange_Imported{}
if ric.Change.Importing != nil {
imported.ImportId = ric.Change.Importing.ID
}
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_ResourceInstancePlannedChange{
ResourceInstancePlannedChange: &terraform1.ResourceInstancePlannedChange{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: ric.Addr.Component.String(),
ResourceInstanceAddr: ric.Addr.Item.String(),
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: &terraform1.StackChangeProgress{
Event: &terraform1.StackChangeProgress_ResourceInstancePlannedChange_{
ResourceInstancePlannedChange: &terraform1.StackChangeProgress_ResourceInstancePlannedChange{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: ric.Addr.Component.String(),
ResourceInstanceAddr: ric.Addr.Item.String(),
},
Actions: actions,
Moved: moved,
Imported: imported,
},
},
Actions: actions,
Moved: moved,
Imported: imported,
},
},
})
@ -576,17 +604,21 @@ func stackPlanHooks(evts *syncPlanStackChangesServer, mainStackSource sourceaddr
// component instance plan completes.
ReportComponentInstancePlanned: func(ctx context.Context, span any, cic *hooks.ComponentInstanceChange) any {
evts.Send(&terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_ComponentInstanceChanges{
ComponentInstanceChanges: &terraform1.ComponentInstanceChanges{
Addr: &terraform1.ComponentInstanceInStackAddr{
ComponentAddr: stackaddrs.ConfigComponentForAbsInstance(cic.Addr).String(),
ComponentInstanceAddr: cic.Addr.String(),
Event: &terraform1.PlanStackChanges_Event_Progress{
Progress: &terraform1.StackChangeProgress{
Event: &terraform1.StackChangeProgress_ComponentInstanceChanges_{
ComponentInstanceChanges: &terraform1.StackChangeProgress_ComponentInstanceChanges{
Addr: &terraform1.ComponentInstanceInStackAddr{
ComponentAddr: stackaddrs.ConfigComponentForAbsInstance(cic.Addr).String(),
ComponentInstanceAddr: cic.Addr.String(),
},
Total: int32(cic.Total()),
Add: int32(cic.Add),
Change: int32(cic.Change),
Import: int32(cic.Import),
Remove: int32(cic.Remove),
},
},
Total: int32(cic.Total()),
Add: int32(cic.Add),
Change: int32(cic.Change),
Import: int32(cic.Import),
Remove: int32(cic.Remove),
},
},
})
@ -623,14 +655,14 @@ func stackApplyHooks(evts *syncApplyStackChangesServer, mainStackSource sourcead
return nil
},
// TODO: Various other event types
// TODO: other event types
}
}
func evtComponentInstanceStatus(ci stackaddrs.AbsComponentInstance, status hooks.ComponentInstanceStatus) *terraform1.PlanStackChanges_Event {
return &terraform1.PlanStackChanges_Event{
Event: &terraform1.PlanStackChanges_Event_ComponentInstanceStatus{
ComponentInstanceStatus: &terraform1.ComponentInstanceStatus{
func evtComponentInstanceStatus(ci stackaddrs.AbsComponentInstance, status hooks.ComponentInstanceStatus) *terraform1.StackChangeProgress {
return &terraform1.StackChangeProgress{
Event: &terraform1.StackChangeProgress_ComponentInstanceStatus_{
ComponentInstanceStatus: &terraform1.StackChangeProgress_ComponentInstanceStatus{
Addr: &terraform1.ComponentInstanceInStackAddr{
ComponentAddr: stackaddrs.ConfigComponentForAbsInstance(ci).String(),
ComponentInstanceAddr: ci.String(),

File diff suppressed because it is too large Load Diff

@ -479,15 +479,9 @@ message PlanStackChanges {
oneof event {
PlannedChange planned_change = 1;
Diagnostic diagnostic = 2;
ComponentInstanceStatus component_instance_status = 3;
ResourceInstanceStatus resource_instance_status = 4;
ResourceInstancePlannedChange resource_instance_planned_change = 5;
ProvisionerStatus provisioner_status = 6;
ProvisionerOutput provisioner_output = 7;
ComponentInstanceChanges component_instance_changes = 8;
ComponentInstances component_instances = 9;
// TODO
StackChangeProgress progress = 10;
}
reserved 3 to 9; // formerly used for individual progress events
}
}
@ -522,7 +516,7 @@ message ApplyStackChanges {
oneof event {
AppliedChange applied_change = 1;
Diagnostic diagnostic = 2;
// TODO: progress events intended for updating the UI
StackChangeProgress progress = 3;
}
}
}
@ -850,6 +844,128 @@ message AppliedChange {
message Nothing {}
}
// A container for "progress report" events in both Stacks.PlanStackChanges
// and Stacks.ApplyStackChanges, which share this message type to allow
// clients to share event-handling code between the two phases.
message StackChangeProgress {
// Some event types are relevant only to one of the two operations, while
// others are common across both but will include different status codes,
// etc in different phases.
oneof event {
ComponentInstanceStatus component_instance_status = 1;
ResourceInstanceStatus resource_instance_status = 2;
ResourceInstancePlannedChange resource_instance_planned_change = 3;
ProvisionerStatus provisioner_status = 4;
ProvisionerOutput provisioner_output = 5;
ComponentInstanceChanges component_instance_changes = 6;
ComponentInstances component_instances = 7;
}
// ComponentInstanceStatus describes the current status of a component instance
// undergoing a plan or apply operation.
message ComponentInstanceStatus {
ComponentInstanceInStackAddr addr = 1;
Status status = 2;
enum Status {
INVALID = 0;
PENDING = 1;
PLANNING = 2;
PLANNED = 3;
APPLYING = 4;
APPLIED = 5;
ERRORED = 6;
}
}
// ComponentInstanceStatus describes the current status of a resource instance
// undergoing a plan or apply operation.
message ResourceInstanceStatus {
ResourceInstanceInStackAddr addr = 1;
Status status = 2;
enum Status {
INVALID = 0;
PENDING = 1;
REFRESHING = 2;
REFRESHED = 3;
PLANNING = 4;
PLANNED = 5;
APPLYING = 6;
APPLIED = 7;
ERRORED = 8;
}
}
// ResourceInstancePlannedChange describes summary information about a planned
// change for a resource instance. This does not include the full object change,
// which is described in PlannedChange.ResourceChange. The information in this
// message is intended for the event stream and need not include the instance's
// full object values.
message ResourceInstancePlannedChange {
ResourceInstanceInStackAddr addr = 1;
repeated ChangeType actions = 2;
Moved moved = 3;
Imported imported = 4;
message Moved {
ResourceInstanceInStackAddr prev_addr = 1;
}
message Imported {
string import_id = 1;
}
}
// ProvisionerStatus represents the progress of a given provisioner during its
// resource instance's apply operation.
message ProvisionerStatus {
ResourceInstanceInStackAddr addr = 1;
string name = 2;
ProvisionerStatus status = 3;
enum Status {
INVALID = 0;
PROVISIONING = 1;
PROVISIONED = 2;
ERRORED = 3;
}
}
// ProvisionerOutput represents recorded output data emitted by a provisioner
// during a resource instance's apply operation.
message ProvisionerOutput {
ResourceInstanceInStackAddr addr = 1;
string name = 2;
string output = 3;
}
// ComponentInstanceChanges represents a roll-up of change counts for a
// component instance plan or apply operation.
message ComponentInstanceChanges {
ComponentInstanceInStackAddr addr = 1;
// total is the sum of all of the other count fields.
//
// Clients should sum all of the other count fields they know about
// and compare to total. If the sum is less than total then the
// difference should be treated as an "other change types" category,
// for forward-compatibility when the Terraform Core RPC server is
// using a newer version of this protocol than the client.
int32 total = 2;
int32 add = 3;
int32 change = 4;
int32 import = 5;
int32 remove = 6;
}
// ComponentInstances represents the result of expanding a component into zero
// or more instances.
message ComponentInstances {
string component_addr = 1;
repeated string instance_addrs = 2;
}
}
message Diagnostic {
enum Severity {
INVALID = 0;
@ -938,99 +1054,3 @@ message Schema {
}
}
}
// ComponentInstanceStatus describes the current status of a component instance
// undergoing a plan or apply operation.
message ComponentInstanceStatus {
ComponentInstanceInStackAddr addr = 1;
Status status = 2;
enum Status {
INVALID = 0;
PENDING = 1;
PLANNING = 2;
PLANNED = 3;
APPLYING = 4;
APPLIED = 5;
ERRORED = 6;
}
}
// ComponentInstanceStatus describes the current status of a resource instance
// undergoing a plan or apply operation.
message ResourceInstanceStatus {
ResourceInstanceInStackAddr addr = 1;
Status status = 2;
enum Status {
INVALID = 0;
PENDING = 1;
REFRESHING = 2;
REFRESHED = 3;
PLANNING = 4;
PLANNED = 5;
APPLYING = 6;
APPLIED = 7;
ERRORED = 8;
}
}
// ResourceInstancePlannedChange describes summary information about a planned
// change for a resource instance. This does not include the full object change,
// which is described in PlannedChange.ResourceChange. The information in this
// message is intended for the event stream and need not include the instance's
// full object values.
message ResourceInstancePlannedChange {
ResourceInstanceInStackAddr addr = 1;
repeated ChangeType actions = 2;
Moved moved = 3;
Imported imported = 4;
message Moved {
ResourceInstanceInStackAddr prev_addr = 1;
}
message Imported {
string import_id = 1;
}
}
// ProvisionerStatus represents the progress of a given provisioner during its
// resource instance's apply operation.
message ProvisionerStatus {
ResourceInstanceInStackAddr addr = 1;
string name = 2;
ProvisionerStatus status = 3;
enum Status {
INVALID = 0;
PROVISIONING = 1;
PROVISIONED = 2;
ERRORED = 3;
}
}
// ProvisionerOutput represents recorded output data emitted by a provisioner
// during a resource instance's apply operation.
message ProvisionerOutput {
ResourceInstanceInStackAddr addr = 1;
string name = 2;
string output = 3;
}
// ComponentInstanceChanges represents a roll-up of change counts for a
// component instance plan or apply operation.
message ComponentInstanceChanges {
ComponentInstanceInStackAddr addr = 1;
int32 total = 2;
int32 add = 3;
int32 change = 4;
int32 import = 5;
int32 remove = 6;
}
// ComponentInstances represents the result of expanding a component into zero
// or more instances.
message ComponentInstances {
string component_addr = 1;
repeated string instance_addrs = 2;
}

@ -27,22 +27,22 @@ const (
)
// TODO: move this into the rpcapi package somewhere
func (s ComponentInstanceStatus) ForProtobuf() terraform1.ComponentInstanceStatus_Status {
func (s ComponentInstanceStatus) ForProtobuf() terraform1.StackChangeProgress_ComponentInstanceStatus_Status {
switch s {
case ComponentInstancePending:
return terraform1.ComponentInstanceStatus_PENDING
return terraform1.StackChangeProgress_ComponentInstanceStatus_PENDING
case ComponentInstancePlanning:
return terraform1.ComponentInstanceStatus_PLANNING
return terraform1.StackChangeProgress_ComponentInstanceStatus_PLANNING
case ComponentInstancePlanned:
return terraform1.ComponentInstanceStatus_PLANNED
return terraform1.StackChangeProgress_ComponentInstanceStatus_PLANNED
case ComponentInstanceApplying:
return terraform1.ComponentInstanceStatus_APPLYING
return terraform1.StackChangeProgress_ComponentInstanceStatus_APPLYING
case ComponentInstanceApplied:
return terraform1.ComponentInstanceStatus_APPLIED
return terraform1.StackChangeProgress_ComponentInstanceStatus_APPLIED
case ComponentInstanceErrored:
return terraform1.ComponentInstanceStatus_ERRORED
return terraform1.StackChangeProgress_ComponentInstanceStatus_ERRORED
default:
return terraform1.ComponentInstanceStatus_INVALID
return terraform1.StackChangeProgress_ComponentInstanceStatus_INVALID
}
}

@ -30,26 +30,26 @@ const (
)
// TODO: move this into the rpcapi package somewhere
func (s ResourceInstanceStatus) ForProtobuf() terraform1.ResourceInstanceStatus_Status {
func (s ResourceInstanceStatus) ForProtobuf() terraform1.StackChangeProgress_ResourceInstanceStatus_Status {
switch s {
case ResourceInstancePending:
return terraform1.ResourceInstanceStatus_PENDING
return terraform1.StackChangeProgress_ResourceInstanceStatus_PENDING
case ResourceInstanceRefreshing:
return terraform1.ResourceInstanceStatus_REFRESHING
return terraform1.StackChangeProgress_ResourceInstanceStatus_REFRESHING
case ResourceInstanceRefreshed:
return terraform1.ResourceInstanceStatus_REFRESHED
return terraform1.StackChangeProgress_ResourceInstanceStatus_REFRESHED
case ResourceInstancePlanning:
return terraform1.ResourceInstanceStatus_PLANNING
return terraform1.StackChangeProgress_ResourceInstanceStatus_PLANNING
case ResourceInstancePlanned:
return terraform1.ResourceInstanceStatus_PLANNED
return terraform1.StackChangeProgress_ResourceInstanceStatus_PLANNED
case ResourceInstanceApplying:
return terraform1.ResourceInstanceStatus_APPLYING
return terraform1.StackChangeProgress_ResourceInstanceStatus_APPLYING
case ResourceInstanceApplied:
return terraform1.ResourceInstanceStatus_APPLIED
return terraform1.StackChangeProgress_ResourceInstanceStatus_APPLIED
case ResourceInstanceErrored:
return terraform1.ResourceInstanceStatus_ERRORED
return terraform1.StackChangeProgress_ResourceInstanceStatus_ERRORED
default:
return terraform1.ResourceInstanceStatus_INVALID
return terraform1.StackChangeProgress_ResourceInstanceStatus_INVALID
}
}
@ -69,16 +69,16 @@ const (
)
// TODO: move this into the rpcapi package somewhere
func (s ProvisionerStatus) ForProtobuf() terraform1.ProvisionerStatus_Status {
func (s ProvisionerStatus) ForProtobuf() terraform1.StackChangeProgress_ProvisionerStatus_Status {
switch s {
case ProvisionerProvisioning:
return terraform1.ProvisionerStatus_PROVISIONING
return terraform1.StackChangeProgress_ProvisionerStatus_PROVISIONING
case ProvisionerProvisioned:
return terraform1.ProvisionerStatus_PROVISIONING
return terraform1.StackChangeProgress_ProvisionerStatus_PROVISIONING
case ProvisionerErrored:
return terraform1.ProvisionerStatus_ERRORED
return terraform1.StackChangeProgress_ProvisionerStatus_ERRORED
default:
return terraform1.ProvisionerStatus_INVALID
return terraform1.StackChangeProgress_ProvisionerStatus_INVALID
}
}

Loading…
Cancel
Save