stackruntime: Fix some quirks of data sent from plan to apply

We previously took a few shortcuts just to more quickly produce a proof
of concept. This gets us considerably closer to a properly-working handoff
from plan to apply, at least for create, update, and replace actions.

Destroying stuff that's been removed from the configuration will take some
further work since currently everything we do is driven by objects in the
configuration. That will follow in later commits.
pull/34738/head
Martin Atkins 3 years ago
parent 7b41a968a9
commit 69aa51b9ff

File diff suppressed because it is too large Load Diff

@ -658,11 +658,11 @@ message PlannedChange {
// incomplete if isolated.
oneof description {
ComponentInstance component_instance_planned = 2;
ResourceInstance resource_instance_drifted = 3;
ResourceInstance resource_instance_planned = 4;
OutputValue output_value_planned = 5;
bool plan_applyable = 6;
}
reserved 3; // formerly "resource_instance_drifted" in the oneof above.
// A set of provider selections that will be needed to apply this
// change, which the caller should remember and use to populate the
@ -690,6 +690,29 @@ message PlannedChange {
ResourceMode resource_mode = 6;
string resource_type = 7;
string provider_addr = 8;
// previous_run_value is included only if it would be
// different from values.old, which typically means that
// Terraform detected some changes made outside of Terraform
// since the previous run. In that case, this field is
// the un-refreshed (but still upgraded) value from
// the previous run and values.old is the refreshed version.
//
// If this isn't set then values.old should be used as the
// previous run value, if needed.
DynamicValue previous_run_value = 9;
// This flag is set if Terraform Core considers the difference
// between previous_run_value and values.old to be "notable",
// which is a heuristic subject to change over time but is
// broadly intended to mean that it would be worth mentioning
// the difference between the two in the UI as a
// "change outside of Terraform". If this isn't set then the
// difference is probably not worth mentioning to the user
// by default, although it could still be shown behind an
// optional disclosure in UI contexts where such things are possible.
bool notable_change_outside = 10;
// TODO: Everything else we need for feature-parity with the
// existing JSON plan export format.
@ -796,6 +819,29 @@ message AppliedChange {
message ResourceInstance {
ResourceInstanceInStackAddr addr = 1;
DynamicValue new_value = 2;
// Sometimes Terraform needs to make changes to a resource in
// multiple steps during the apply phase, with each step
// changing something about the state. This flag will be set
// for such interim updates, and left unset for whatever
// description Terraform Core considers to be "final", at
// which point the new value should be converged with the
// desired state.
//
// The intended use for this is when presenting updated values
// to users in the UI, where it might be best to ignore or
// present differently interim updates to avoid creating
// confusion by showing the not-yet-converged intermediate
// states.
//
// If Terraform encounters a problem during the apply phase
// and needs to stop partway through then a "final" change
// description might never arrive. In that case, callers
// should save the most recent interim object as the final
// description, since it would represent the most accurate
// description of the state the remote system has been left
// in.
bool interim = 3;
}
message OutputValue {
string name = 1;

@ -18,18 +18,10 @@ import (
// Terraform language runtime to apply all of the described changes together as
// a single operation.
type Component struct {
// ResourceInstanceChangedOutside describes changes that Terraform has
// detected were made outside of Terraform since the last run.
ResourceInstanceChangedOutside addrs.Map[addrs.AbsResourceInstance, *plans.ResourceInstanceChangeSrc]
// ResourceInstancePlanned describes the changes that Terraform is proposing
// to make to try to converge the real system state with the desired state
// as described by the configuration.
//
// FIXME: This modelling is incorrect, because it doesn't handle the fact that
// a resource instance change might actually be for a deposed object
// rather than the current object.
ResourceInstancePlanned addrs.Map[addrs.AbsResourceInstance, *plans.ResourceInstanceChangeSrc]
ResourceInstancePlanned addrs.Map[addrs.AbsResourceInstanceObject, *plans.ResourceInstanceChangeSrc]
// TODO: Something for deferred resource instance changes, once we have
// such a concept.

@ -70,8 +70,7 @@ func LoadFromProto(msgs []*anypb.Any) (*Plan, error) {
}
if !ret.Components.HasKey(addr) {
ret.Components.Put(addr, &Component{
ResourceInstanceChangedOutside: addrs.MakeMap[addrs.AbsResourceInstance, *plans.ResourceInstanceChangeSrc](),
ResourceInstancePlanned: addrs.MakeMap[addrs.AbsResourceInstance, *plans.ResourceInstanceChangeSrc](),
ResourceInstancePlanned: addrs.MakeMap[addrs.AbsResourceInstanceObject, *plans.ResourceInstanceChangeSrc](),
})
}
c := ret.Components.Get(addr)
@ -96,25 +95,11 @@ func LoadFromProto(msgs []*anypb.Any) (*Plan, error) {
if err != nil {
return nil, fmt.Errorf("invalid resource instance change: %w", err)
}
c.ResourceInstancePlanned.Put(riPlan.Addr, riPlan)
case *tfstackdata1.PlanResourceInstanceChangeOutside:
if msg.Change == nil {
return nil, fmt.Errorf("%T has nil Change", msg)
}
cAddr, diags := stackaddrs.ParseAbsComponentInstanceStr(msg.ComponentInstanceAddr)
if diags.HasErrors() {
return nil, fmt.Errorf("invalid component instance address syntax in %q", msg.ComponentInstanceAddr)
}
c, ok := ret.Components.GetOk(cAddr)
if !ok {
return nil, fmt.Errorf("resource instance change for unannounced component instance %s", cAddr)
}
riPlan, err := planfile.ResourceChangeFromProto(msg.Change)
if err != nil {
return nil, fmt.Errorf("invalid resource instance change: %w", err)
fullAddr := addrs.AbsResourceInstanceObject{
ResourceInstance: riPlan.Addr,
DeposedKey: riPlan.DeposedKey,
}
c.ResourceInstanceChangedOutside.Put(riPlan.Addr, riPlan)
c.ResourceInstancePlanned.Put(fullAddr, riPlan)
default:
// Should not get here, because a stack plan can only be loaded by

@ -123,10 +123,16 @@ func (pc *PlannedChangeComponentInstance) PlannedChangeProto() (*terraform1.Plan
}
}
var planTimestampStr string
var zeroTime time.Time
if pc.PlanTimestamp != zeroTime {
planTimestampStr = pc.PlanTimestamp.Format(time.RFC3339)
}
var raw anypb.Any
err := anypb.MarshalFrom(&raw, &tfstackdata1.PlanComponentInstance{
ComponentInstanceAddr: pc.Addr.String(),
PlanTimestamp: pc.PlanTimestamp.Format(time.RFC3339),
PlanTimestamp: planTimestampStr,
PlannedInputValues: plannedInputValues,
// We don't track the action as part of the raw data because we
// don't actually need it to apply the change; it's only included
@ -221,62 +227,6 @@ func (pc *PlannedChangeResourceInstancePlanned) PlannedChangeProto() (*terraform
}, nil
}
// PlannedChangeResourceInstanceOutside announces that Terraform has detected
// some action taken outside of Terraform since the last apply.
type PlannedChangeResourceInstanceOutside struct {
ComponentInstanceAddr stackaddrs.AbsComponentInstance
ChangeSrc *plans.ResourceInstanceChangeSrc
// Schema MUST be the same schema that was used to encode the dynamic
// values inside ChangeSrc.
Schema *configschema.Block
}
var _ PlannedChange = (*PlannedChangeResourceInstanceOutside)(nil)
// PlannedChangeProto implements PlannedChange.
func (pc *PlannedChangeResourceInstanceOutside) PlannedChangeProto() (*terraform1.PlannedChange, error) {
if pc.ChangeSrc == nil {
return nil, fmt.Errorf("nil ChangeSrc")
}
changeProto, err := planfile.ResourceChangeToProto(pc.ChangeSrc)
if err != nil {
return nil, fmt.Errorf("converting resource instance change to proto: %w", err)
}
var raw anypb.Any
err = anypb.MarshalFrom(&raw, &tfstackdata1.PlanResourceInstanceChangeOutside{
ComponentInstanceAddr: pc.ComponentInstanceAddr.String(),
Change: changeProto,
}, proto.MarshalOptions{})
if err != nil {
return nil, err
}
protoChangeTypes, err := terraform1.ChangeTypesForPlanAction(pc.ChangeSrc.Action)
if err != nil {
return nil, err
}
return &terraform1.PlannedChange{
Raw: []*anypb.Any{&raw},
Description: &terraform1.PlannedChange_ResourceInstanceDrifted{
ResourceInstanceDrifted: &terraform1.PlannedChange_ResourceInstance{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: pc.ComponentInstanceAddr.String(),
ResourceInstanceAddr: pc.ChangeSrc.Addr.String(),
},
Actions: protoChangeTypes,
Values: &terraform1.DynamicValueChange{
Old: terraform1.NewDynamicValue(pc.ChangeSrc.Before, pc.ChangeSrc.BeforeValMarks),
New: terraform1.NewDynamicValue(pc.ChangeSrc.After, pc.ChangeSrc.AfterValMarks),
},
// TODO: Moved, Imported
},
},
}, nil
}
// PlannedChangeOutputValue announces the change action for one output value
// declared in the top-level stack configuration.
//

@ -5,6 +5,7 @@ package stackplan
import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/go-version"
@ -30,6 +31,10 @@ func TestPlannedChangeAsProto(t *testing.T) {
if err != nil {
t.Fatal(err)
}
fakePlanTimestamp, err := time.Parse(time.RFC3339, "2017-03-27T10:00:00-08:00")
if err != nil {
t.Fatal(err)
}
tests := map[string]struct {
Receiver PlannedChange
@ -85,12 +90,14 @@ func TestPlannedChangeAsProto(t *testing.T) {
Component: stackaddrs.Component{Name: "foo"},
},
},
Action: plans.Create,
Action: plans.Create,
PlanTimestamp: fakePlanTimestamp,
},
Want: &terraform1.PlannedChange{
Raw: []*anypb.Any{
mustMarshalAnyPb(&tfstackdata1.PlanComponentInstance{
ComponentInstanceAddr: "component.foo",
PlanTimestamp: "2017-03-27T10:00:00-08:00",
}),
},
Description: &terraform1.PlannedChange_ComponentInstancePlanned{
@ -113,12 +120,14 @@ func TestPlannedChangeAsProto(t *testing.T) {
Key: addrs.StringKey("bar"),
},
},
Action: plans.NoOp,
Action: plans.NoOp,
PlanTimestamp: fakePlanTimestamp,
},
Want: &terraform1.PlannedChange{
Raw: []*anypb.Any{
mustMarshalAnyPb(&tfstackdata1.PlanComponentInstance{
ComponentInstanceAddr: `component.foo["bar"]`,
PlanTimestamp: "2017-03-27T10:00:00-08:00",
}),
},
Description: &terraform1.PlannedChange_ComponentInstancePlanned{
@ -224,69 +233,6 @@ func TestPlannedChangeAsProto(t *testing.T) {
},
},
},
"resource instance deleted outside": {
Receiver: &PlannedChangeResourceInstanceOutside{
ComponentInstanceAddr: stackaddrs.AbsComponentInstance{
Stack: stackaddrs.RootStackInstance.Child("a", addrs.StringKey("boop")),
Item: stackaddrs.ComponentInstance{
Component: stackaddrs.Component{Name: "foo"},
Key: addrs.StringKey("beep"),
},
},
ChangeSrc: &plans.ResourceInstanceChangeSrc{
Addr: addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "thingy",
Name: "wotsit",
}.Instance(addrs.IntKey(1)).Absolute(
addrs.RootModuleInstance.Child("pizza", addrs.StringKey("chicken")),
),
ProviderAddr: addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.MustParseProviderSourceString("example.com/thingers/thingy"),
},
ChangeSrc: plans.ChangeSrc{
Action: plans.Delete,
Before: emptyObjectForPlan,
After: nullObjectForPlan,
},
},
},
Want: &terraform1.PlannedChange{
Raw: []*anypb.Any{
mustMarshalAnyPb(&tfstackdata1.PlanResourceInstanceChangeOutside{
ComponentInstanceAddr: `stack.a["boop"].component.foo["beep"]`,
Change: &planproto.ResourceInstanceChange{
Addr: `module.pizza["chicken"].thingy.wotsit[1]`,
Change: &planproto.Change{
Action: planproto.Action_DELETE,
Values: []*planproto.DynamicValue{
{Msgpack: []byte{'\x80'}}, // zero-length mapping
},
},
Provider: `provider["example.com/thingers/thingy"]`,
},
}),
},
Description: &terraform1.PlannedChange_ResourceInstanceDrifted{
ResourceInstanceDrifted: &terraform1.PlannedChange_ResourceInstance{
Addr: &terraform1.ResourceInstanceInStackAddr{
ComponentInstanceAddr: `stack.a["boop"].component.foo["beep"]`,
ResourceInstanceAddr: `module.pizza["chicken"].thingy.wotsit[1]`,
},
Actions: []terraform1.ChangeType{terraform1.ChangeType_DELETE},
Values: &terraform1.DynamicValueChange{
Old: &terraform1.DynamicValue{
Msgpack: []byte{'\x80'}, // zero-length mapping
},
New: &terraform1.DynamicValue{
Msgpack: []byte{'\xc0'}, // null
},
},
},
},
},
},
"output value updated": {
Receiver: &PlannedChangeOutputValue{
Addr: stackaddrs.OutputValue{Name: "thingy_id"},

@ -525,6 +525,10 @@ func (c *ComponentInstance) CheckModuleTreePlan(ctx context.Context) (*plans.Pla
Mode: stackPlanOpts.PlanningMode,
SetVariables: inputValues,
ExternalProviders: providerClients,
// This is set by some tests but should not be used in main code.
// (nil means to use the real time when tfCtx.Plan was called.)
ForcePlanTimestamp: stackPlanOpts.ForcePlanTimestamp,
})
diags = diags.Append(moreDiags)
@ -870,31 +874,6 @@ func (c *ComponentInstance) PlanChanges(ctx context.Context) ([]stackplan.Planne
PlanTimestamp: corePlan.Timestamp,
})
for _, rsrcChange := range corePlan.DriftedResources {
schema, err := c.resourceTypeSchema(
ctx,
rsrcChange.ProviderAddr.Provider,
rsrcChange.Addr.Resource.Resource.Mode,
rsrcChange.Addr.Resource.Resource.Type,
)
if err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Can't fetch provider schema to save plan",
fmt.Sprintf(
"Failed to retrieve the schema for %s from provider %s: %s. This is a bug in Terraform.",
rsrcChange.Addr, rsrcChange.ProviderAddr.Provider, err,
),
))
continue
}
changes = append(changes, &stackplan.PlannedChangeResourceInstanceOutside{
ComponentInstanceAddr: c.Addr(),
ChangeSrc: rsrcChange,
Schema: schema,
})
}
for _, rsrcChange := range corePlan.Changes.Resources {
schema, err := c.resourceTypeSchema(
ctx,
@ -918,6 +897,11 @@ func (c *ComponentInstance) PlanChanges(ctx context.Context) ([]stackplan.Planne
ComponentInstanceAddr: c.Addr(),
ChangeSrc: rsrcChange,
Schema: schema,
// TODO: Also provide the previous run state, if it's
// different from the prior state already captured
// inside rsrcChange, and signal whether the difference
// from previous run seems "notable" per Terraform Core's
// heuristics.
})
}
}

@ -7,6 +7,7 @@ import (
"context"
"fmt"
"sync"
"time"
"github.com/hashicorp/go-slug/sourcebundle"
"github.com/hashicorp/terraform/internal/addrs"
@ -66,6 +67,10 @@ type mainValidating struct {
type mainPlanning struct {
opts PlanOpts
prevState *stackstate.State
// This is a utility for unit tests that want to encourage stable output
// to assert against. Not for real use.
forcePlanTimestamp *time.Time
}
type mainApplying struct {

@ -54,6 +54,19 @@ func ApplyPlan(ctx context.Context, config *stackconfig.Config, rawPlan []*anypb
hs, ctx := hookBegin(ctx, hooks.BeginApply, hooks.ContextAttach, struct{}{})
defer hookMore(ctx, hs, hooks.EndApply, struct{}{})
// TODO: Somewhere in all of this we need to deal with two bits of
// general bookkeeping to ensure the state stays consistent:
// 1. Emitting interim "applied change" events for resource instances
// whose prior state changed during the refresh step in the plan,
// so we have those refreshes committed even if errors block us
// from completing other updates.
// 2. Emitting events to let the caller know it should drop any
// raw state or state description keys that the plan phase didn't
// understand and that were marked as needing to be discarded in
// that case. Otherwise they'll stick around after this work is
// complete and possibly leave us with an inconsistent or invalid
// state overall.
withDiags, err := promising.MainTask(ctx, func(ctx context.Context) (withDiagnostics[*Main], error) {
// We'll register all of the changes we intend to make up front, so we
// can error rather than deadlock if something goes wrong and causes

@ -40,6 +40,10 @@ func (m *Main) PlanAll(ctx context.Context, outp PlanOutput) {
TerraformVersion: version.SemVer,
})
// TODO: Announce an extra planned change here if we have any unrecognized
// raw state or state description keys that we'll need to delete during the
// apply phase.
diags, err := promising.MainTask(ctx, func(ctx context.Context) (tfdiags.Diagnostics, error) {
// The idea here is just to iterate over everything in the configuration,
// find its corresponding evaluation object, and then ask it to validate

@ -5,6 +5,7 @@ package stackeval
import (
"context"
"time"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
@ -18,6 +19,11 @@ type PlanOpts struct {
InputVariableValues map[stackaddrs.InputVariable]ExternalInputValue
ProviderFactories ProviderFactories
// ForcePlanTimestamp, if not nil, will force the plantimestamp function
// to return the given time instead of whatever real time the plan was
// started. This is here for unit testing only.
ForcePlanTimestamp *time.Time
}
// Plannable is implemented by objects that can participate in planning.

@ -6,6 +6,7 @@ package stackruntime
import (
"context"
"sync"
"time"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/providers"
@ -43,6 +44,8 @@ func Plan(ctx context.Context, req *PlanRequest, resp *PlanResponse) {
main := stackeval.NewForPlanning(req.Config, req.PrevState, stackeval.PlanOpts{
InputVariableValues: req.InputValues,
ProviderFactories: req.ProviderFactories,
ForcePlanTimestamp: req.ForcePlanTimestamp,
})
main.PlanAll(ctx, stackeval.PlanOutput{
AnnouncePlannedChange: func(ctx context.Context, change stackplan.PlannedChange) {
@ -85,6 +88,11 @@ type PlanRequest struct {
InputValues map[stackaddrs.InputVariable]ExternalInputValue
ProviderFactories map[addrs.Provider]providers.Factory
// ForcePlanTimestamp, if not nil, will force the plantimestamp function
// to return the given value instead of whatever real time the plan
// operation started. This is for testing purposes only.
ForcePlanTimestamp *time.Time
}
// PlanResponse is used by [Plan] to describe the results of planning.

@ -8,6 +8,7 @@ import (
"fmt"
"sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform/internal/addrs"
@ -20,6 +21,7 @@ import (
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/internal/tfdiags"
"github.com/hashicorp/terraform/version"
"github.com/zclconf/go-cty-debug/ctydebug"
"github.com/zclconf/go-cty/cty"
)
@ -27,6 +29,11 @@ func TestPlanWithSingleResource(t *testing.T) {
ctx := context.Background()
cfg := loadMainBundleConfigForTest(t, "with-single-resource")
fakePlanTimestamp, err := time.Parse(time.RFC3339, "1994-09-05T08:50:00Z")
if err != nil {
t.Fatal(err)
}
changesCh := make(chan stackplan.PlannedChange, 8)
diagsCh := make(chan tfdiags.Diagnostic, 2)
req := PlanRequest{
@ -36,6 +43,8 @@ func TestPlanWithSingleResource(t *testing.T) {
return terraformProvider.NewProvider(), nil
},
},
ForcePlanTimestamp: &fakePlanTimestamp,
}
resp := PlanResponse{
PlannedChanges: changesCh,
@ -70,7 +79,9 @@ func TestPlanWithSingleResource(t *testing.T) {
Component: stackaddrs.Component{Name: "self"},
},
),
Action: plans.Create,
Action: plans.Create,
PlannedInputValues: make(map[string]plans.DynamicValue),
PlanTimestamp: fakePlanTimestamp,
},
&stackplan.PlannedChangeHeader{
TerraformVersion: version.SemVer,
@ -131,10 +142,23 @@ func TestPlanWithSingleResource(t *testing.T) {
},
},
},
// The following is schema for the real terraform_data resource
// type from the real terraform.io/builtin/terraform provider
// maintained elsewhere in this codebase. If that schema changes
// in future then this should change to match it.
Schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"input": {Type: cty.DynamicPseudoType, Optional: true},
"output": {Type: cty.DynamicPseudoType, Computed: true},
"triggers_replace": {Type: cty.DynamicPseudoType, Optional: true},
"id": {Type: cty.String, Computed: true},
},
},
},
}
if diff := cmp.Diff(wantChanges, gotChanges); diff != "" {
if diff := cmp.Diff(wantChanges, gotChanges, ctydebug.CmpOptions); diff != "" {
t.Errorf("wrong changes\n%s", diff)
}
}
@ -161,6 +185,9 @@ func TestPlanVariableOutputRoundtripNested(t *testing.T) {
}
wantChanges := []stackplan.PlannedChange{
&stackplan.PlannedChangeApplyable{
Applyable: true,
},
&stackplan.PlannedChangeHeader{
TerraformVersion: version.SemVer,
},
@ -170,12 +197,19 @@ func TestPlanVariableOutputRoundtripNested(t *testing.T) {
OldValue: plans.DynamicValue{0xc0}, // MessagePack nil
NewValue: plans.DynamicValue([]byte("\xa7default")), // MessagePack string "default"
},
&stackplan.PlannedChangeApplyable{
Applyable: true,
&stackplan.PlannedChangeRootInputValue{
Addr: stackaddrs.InputVariable{
Name: "msg",
},
Value: cty.NullVal(cty.String),
},
}
sort.SliceStable(gotChanges, func(i, j int) bool {
// An arbitrary sort just to make the result stable for comparison.
return fmt.Sprintf("%T", gotChanges[i]) < fmt.Sprintf("%T", gotChanges[j])
})
if diff := cmp.Diff(wantChanges, gotChanges); diff != "" {
if diff := cmp.Diff(wantChanges, gotChanges, ctydebug.CmpOptions); diff != "" {
t.Errorf("wrong changes\n%s", diff)
}
}

@ -383,22 +383,27 @@ func (x *PlanResourceInstanceChangePlanned) GetChange() *planproto.ResourceInsta
return nil
}
// Represents a change to a particular resource instance within a particular
// component instance that Terraform has detected was made outside of Terraform
// since the most recent apply.
type PlanResourceInstanceChangeOutside struct {
// Represents that we need to emit "delete" requests for one or more raw
// state and/or state description objects during the apply phase.
//
// This situation arises if the previous state (given as input to the apply
// phase) contains keys that are of a type unrecognized by the current
// version of Terraform and that are marked as "discard if unrecognized",
// suggesting that their content is likely to become somehow invalid if
// other parts of the state were to get updated.
type PlanDiscardStateMapKeys struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The same string must previously have been announced with a
// PlanComponentInstance message, or the overall plan sequence is invalid.
ComponentInstanceAddr string `protobuf:"bytes,1,opt,name=component_instance_addr,json=componentInstanceAddr,proto3" json:"component_instance_addr,omitempty"`
Change *planproto.ResourceInstanceChange `protobuf:"bytes,2,opt,name=change,proto3" json:"change,omitempty"`
// A set of keys to delete from the "raw state".
RawStateKeys []string `protobuf:"bytes,1,rep,name=raw_state_keys,json=rawStateKeys,proto3" json:"raw_state_keys,omitempty"`
// A set of keys to delete from the "state description".
DescriptionKeys []string `protobuf:"bytes,2,rep,name=description_keys,json=descriptionKeys,proto3" json:"description_keys,omitempty"`
}
func (x *PlanResourceInstanceChangeOutside) Reset() {
*x = PlanResourceInstanceChangeOutside{}
func (x *PlanDiscardStateMapKeys) Reset() {
*x = PlanDiscardStateMapKeys{}
if protoimpl.UnsafeEnabled {
mi := &file_tfstackdata1_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -406,13 +411,13 @@ func (x *PlanResourceInstanceChangeOutside) Reset() {
}
}
func (x *PlanResourceInstanceChangeOutside) String() string {
func (x *PlanDiscardStateMapKeys) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PlanResourceInstanceChangeOutside) ProtoMessage() {}
func (*PlanDiscardStateMapKeys) ProtoMessage() {}
func (x *PlanResourceInstanceChangeOutside) ProtoReflect() protoreflect.Message {
func (x *PlanDiscardStateMapKeys) ProtoReflect() protoreflect.Message {
mi := &file_tfstackdata1_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -424,21 +429,21 @@ func (x *PlanResourceInstanceChangeOutside) ProtoReflect() protoreflect.Message
return mi.MessageOf(x)
}
// Deprecated: Use PlanResourceInstanceChangeOutside.ProtoReflect.Descriptor instead.
func (*PlanResourceInstanceChangeOutside) Descriptor() ([]byte, []int) {
// Deprecated: Use PlanDiscardStateMapKeys.ProtoReflect.Descriptor instead.
func (*PlanDiscardStateMapKeys) Descriptor() ([]byte, []int) {
return file_tfstackdata1_proto_rawDescGZIP(), []int{5}
}
func (x *PlanResourceInstanceChangeOutside) GetComponentInstanceAddr() string {
func (x *PlanDiscardStateMapKeys) GetRawStateKeys() []string {
if x != nil {
return x.ComponentInstanceAddr
return x.RawStateKeys
}
return ""
return nil
}
func (x *PlanResourceInstanceChangeOutside) GetChange() *planproto.ResourceInstanceChange {
func (x *PlanDiscardStateMapKeys) GetDescriptionKeys() []string {
if x != nil {
return x.Change
return x.DescriptionKeys
}
return nil
}
@ -667,49 +672,46 @@ var file_tfstackdata1_proto_rawDesc = []byte{
0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x93, 0x01,
0x0a, 0x21, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e,
0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x75, 0x74, 0x73,
0x69, 0x64, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49,
0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x36, 0x0a, 0x06, 0x63,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x66,
0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73,
0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61,
0x6e, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70,
0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x56, 0x31, 0x22,
0xd7, 0x03, 0x0a, 0x1d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x6a, 0x0a,
0x17, 0x50, 0x6c, 0x61, 0x6e, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x74,
0x65, 0x4d, 0x61, 0x70, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x61, 0x77, 0x5f,
0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
0x52, 0x0c, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x29,
0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65,
0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x74, 0x61,
0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61,
0x6e, 0x63, 0x65, 0x56, 0x31, 0x22, 0xd7, 0x03, 0x0a, 0x1d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x56, 0x31, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74,
0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0e, 0x73,
0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x25, 0x0a,
0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61,
0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x56,
0x31, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x73, 0x6f, 0x6e,
0x12, 0x35, 0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61,
0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c,
0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69,
0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d,
0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
0x0d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a,
0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32,
0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74,
0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61,
0x6e, 0x63, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x56, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65,
0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09,
0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x32,
0x0a, 0x15, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f,
0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x63,
0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x44, 0x65, 0x73, 0x74, 0x72,
0x6f, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
0x52, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x41, 0x64, 0x64, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x70,
0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x22, 0x2d, 0x0a, 0x06, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07,
0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x44, 0x10, 0x02, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73,
0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e,
0x63, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x62,
0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x18, 0x06, 0x20,
0x01, 0x28, 0x08, 0x52, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x65, 0x66, 0x6f, 0x72,
0x65, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72,
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x72,
0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x5f,
0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x64, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61,
0x22, 0x2d, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e,
0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59,
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x44, 0x10, 0x02, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -733,7 +735,7 @@ var file_tfstackdata1_proto_goTypes = []interface{}{
(*PlanRootInputValue)(nil), // 3: tfstackdata1.PlanRootInputValue
(*PlanComponentInstance)(nil), // 4: tfstackdata1.PlanComponentInstance
(*PlanResourceInstanceChangePlanned)(nil), // 5: tfstackdata1.PlanResourceInstanceChangePlanned
(*PlanResourceInstanceChangeOutside)(nil), // 6: tfstackdata1.PlanResourceInstanceChangeOutside
(*PlanDiscardStateMapKeys)(nil), // 6: tfstackdata1.PlanDiscardStateMapKeys
(*StateComponentInstanceV1)(nil), // 7: tfstackdata1.StateComponentInstanceV1
(*StateResourceInstanceObjectV1)(nil), // 8: tfstackdata1.StateResourceInstanceObjectV1
nil, // 9: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry
@ -745,15 +747,14 @@ var file_tfstackdata1_proto_depIdxs = []int32{
10, // 0: tfstackdata1.PlanRootInputValue.value:type_name -> tfplan.DynamicValue
9, // 1: tfstackdata1.PlanComponentInstance.planned_input_values:type_name -> tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry
11, // 2: tfstackdata1.PlanResourceInstanceChangePlanned.change:type_name -> tfplan.ResourceInstanceChange
11, // 3: tfstackdata1.PlanResourceInstanceChangeOutside.change:type_name -> tfplan.ResourceInstanceChange
12, // 4: tfstackdata1.StateResourceInstanceObjectV1.sensitive_paths:type_name -> tfplan.Path
0, // 5: tfstackdata1.StateResourceInstanceObjectV1.status:type_name -> tfstackdata1.StateResourceInstanceObjectV1.Status
10, // 6: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry.value:type_name -> tfplan.DynamicValue
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
12, // 3: tfstackdata1.StateResourceInstanceObjectV1.sensitive_paths:type_name -> tfplan.Path
0, // 4: tfstackdata1.StateResourceInstanceObjectV1.status:type_name -> tfstackdata1.StateResourceInstanceObjectV1.Status
10, // 5: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry.value:type_name -> tfplan.DynamicValue
6, // [6:6] is the sub-list for method output_type
6, // [6:6] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_tfstackdata1_proto_init() }
@ -823,7 +824,7 @@ func file_tfstackdata1_proto_init() {
}
}
file_tfstackdata1_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PlanResourceInstanceChangeOutside); i {
switch v := v.(*PlanDiscardStateMapKeys); i {
case 0:
return &v.state
case 1:

@ -100,15 +100,20 @@ message PlanResourceInstanceChangePlanned {
tfplan.ResourceInstanceChange change = 2;
}
// Represents a change to a particular resource instance within a particular
// component instance that Terraform has detected was made outside of Terraform
// since the most recent apply.
message PlanResourceInstanceChangeOutside {
// The same string must previously have been announced with a
// PlanComponentInstance message, or the overall plan sequence is invalid.
string component_instance_addr = 1;
tfplan.ResourceInstanceChange change = 2;
// Represents that we need to emit "delete" requests for one or more raw
// state and/or state description objects during the apply phase.
//
// This situation arises if the previous state (given as input to the apply
// phase) contains keys that are of a type unrecognized by the current
// version of Terraform and that are marked as "discard if unrecognized",
// suggesting that their content is likely to become somehow invalid if
// other parts of the state were to get updated.
message PlanDiscardStateMapKeys {
// A set of keys to delete from the "raw state".
repeated string raw_state_keys = 1;
// A set of keys to delete from the "state description".
repeated string description_keys = 2;
}
///////////// STATE MAP MESSAGES

Loading…
Cancel
Save