diff --git a/internal/plans/planproto/convert.go b/internal/plans/planproto/convert.go index 3b86371f15..ad4507cc61 100644 --- a/internal/plans/planproto/convert.go +++ b/internal/plans/planproto/convert.go @@ -58,3 +58,46 @@ func NewPlanDynamicValue(dv plans.DynamicValue) *DynamicValue { Msgpack: []byte(dv), } } + +func NewAction(action plans.Action) Action { + switch action { + case plans.NoOp: + return Action_NOOP + case plans.Create: + return Action_CREATE + case plans.Read: + return Action_READ + case plans.Update: + return Action_UPDATE + case plans.Delete: + return Action_DELETE + case plans.DeleteThenCreate: + return Action_DELETE_THEN_CREATE + case plans.CreateThenDelete: + return Action_CREATE_THEN_DELETE + default: + // The above should be exhaustive for all possible actions + panic(fmt.Sprintf("unsupported change action %s", action)) + } +} + +func FromAction(protoAction Action) (plans.Action, error) { + switch protoAction { + case Action_NOOP: + return plans.NoOp, nil + case Action_CREATE: + return plans.Create, nil + case Action_READ: + return plans.Read, nil + case Action_UPDATE: + return plans.Update, nil + case Action_DELETE: + return plans.Delete, nil + case Action_DELETE_THEN_CREATE: + return plans.DeleteThenCreate, nil + case Action_CREATE_THEN_DELETE: + return plans.CreateThenDelete, nil + default: + return plans.NoOp, fmt.Errorf("unsupported action %s", protoAction) + } +} diff --git a/internal/stacks/stackplan/component.go b/internal/stacks/stackplan/component.go index 574d20b27f..c573cb0335 100644 --- a/internal/stacks/stackplan/component.go +++ b/internal/stacks/stackplan/component.go @@ -7,8 +7,12 @@ import ( "fmt" "time" + "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/plans" + "github.com/hashicorp/terraform/internal/stacks/stackaddrs" "github.com/hashicorp/terraform/internal/states" ) @@ -19,6 +23,8 @@ import ( // Terraform language runtime to apply all of the described changes together as // a single operation. type Component struct { + PlannedAction plans.Action + // 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. @@ -43,6 +49,17 @@ type Component struct { // timestamp", which is used only for the result of the "plantimestamp" // function during apply and must not be used for any other purpose. PlanTimestamp time.Time + + // Dependencies is a set of addresses of other components that this one + // expects to exist for as long as this one exists. + Dependencies collections.Set[stackaddrs.AbsComponent] + + // Dependents is the reverse of [Component.Dependencies], describing + // the other components that must be destroyed before this one could + // be destroyed. + Dependents collections.Set[stackaddrs.AbsComponent] + + PlannedOutputValues map[addrs.OutputValue]cty.Value } // ForModulesRuntime translates the component instance plan into the form diff --git a/internal/stacks/stackplan/from_proto.go b/internal/stacks/stackplan/from_proto.go index d73c36ad5d..0c7b6252ab 100644 --- a/internal/stacks/stackplan/from_proto.go +++ b/internal/stacks/stackplan/from_proto.go @@ -6,18 +6,20 @@ package stackplan import ( "fmt" + "github.com/zclconf/go-cty/cty" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/plans/planfile" + "github.com/hashicorp/terraform/internal/plans/planproto" "github.com/hashicorp/terraform/internal/stacks/stackaddrs" "github.com/hashicorp/terraform/internal/stacks/stackstate" "github.com/hashicorp/terraform/internal/stacks/tfstackdata1" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/version" - "github.com/zclconf/go-cty/cty" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" ) func LoadFromProto(msgs []*anypb.Any) (*Plan, error) { @@ -71,15 +73,54 @@ func LoadFromProto(msgs []*anypb.Any) (*Plan, error) { // should've been produced by this same version of Terraform. return nil, fmt.Errorf("invalid component instance address syntax in %q", msg.ComponentInstanceAddr) } + + dependencies := collections.NewSet[stackaddrs.AbsComponent]() + for _, rawAddr := range msg.DependsOnComponentAddrs { + // NOTE: We're using the component _instance_ address parser + // here, but we really want just components, so we'll need to + // check afterwards to make sure we don't have an instance key. + addr, diags := stackaddrs.ParseAbsComponentInstanceStr(rawAddr) + if diags.HasErrors() { + return nil, fmt.Errorf("invalid component address syntax in %q", rawAddr) + } + if addr.Item.Key != addrs.NoKey { + return nil, fmt.Errorf("invalid component address syntax in %q: is actually a component instance address", rawAddr) + } + realAddr := stackaddrs.AbsComponent{ + Stack: addr.Stack, + Item: addr.Item.Component, + } + dependencies.Add(realAddr) + } + + plannedAction, err := planproto.FromAction(msg.PlannedAction) + if err != nil { + return nil, fmt.Errorf("decoding plan for %s: %w", addr, err) + } + + outputVals := make(map[addrs.OutputValue]cty.Value) + for name, rawVal := range msg.PlannedOutputValues { + v, err := tfstackdata1.DynamicValueFromTFStackData1(rawVal, cty.DynamicPseudoType) + if err != nil { + return nil, fmt.Errorf("decoding output value %q for %s: %w", name, addr, err) + } + outputVals[addrs.OutputValue{Name: name}] = v + } + if !ret.Components.HasKey(addr) { ret.Components.Put(addr, &Component{ + PlannedAction: plannedAction, + Dependencies: dependencies, + Dependents: collections.NewSet[stackaddrs.AbsComponent](), + PlannedOutputValues: outputVals, + ResourceInstancePlanned: addrs.MakeMap[addrs.AbsResourceInstanceObject, *plans.ResourceInstanceChangeSrc](), ResourceInstancePriorState: addrs.MakeMap[addrs.AbsResourceInstanceObject, *states.ResourceInstanceObjectSrc](), ResourceInstanceProviderConfig: addrs.MakeMap[addrs.AbsResourceInstanceObject, addrs.AbsProviderConfig](), }) } c := ret.Components.Get(addr) - err := c.PlanTimestamp.UnmarshalText([]byte(msg.PlanTimestamp)) + err = c.PlanTimestamp.UnmarshalText([]byte(msg.PlanTimestamp)) if err != nil { return nil, fmt.Errorf("invalid plan timestamp %q for %s", msg.PlanTimestamp, addr) } @@ -171,5 +212,33 @@ func LoadFromProto(msgs []*anypb.Any) (*Plan, error) { return nil, fmt.Errorf("missing PlanHeader") } + // Before we return we'll calculate the reverse dependency information + // based on the forward dependency information we loaded above. + for _, elem := range ret.Components.Elems() { + dependentInstAddr := elem.K + dependentAddr := stackaddrs.AbsComponent{ + Stack: dependentInstAddr.Stack, + Item: dependentInstAddr.Item.Component, + } + + for _, dependencyAddr := range elem.V.Dependencies.Elems() { + // FIXME: This is very inefficient because the current data structure doesn't + // allow looking up all of the component instances that have a particular + // component. This'll be okay as long as the number of components is + // small, but we'll need to improve this if we ever want to support stacks + // with a large number of components. + for _, elem := range ret.Components.Elems() { + maybeDependencyInstAddr := elem.K + maybeDependencyAddr := stackaddrs.AbsComponent{ + Stack: maybeDependencyInstAddr.Stack, + Item: maybeDependencyInstAddr.Item.Component, + } + if dependencyAddr.UniqueKey() == maybeDependencyAddr.UniqueKey() { + elem.V.Dependents.Add(dependentAddr) + } + } + } + } + return ret, nil } diff --git a/internal/stacks/stackplan/planned_change.go b/internal/stacks/stackplan/planned_change.go index fb6ff36563..e0de7e934e 100644 --- a/internal/stacks/stackplan/planned_change.go +++ b/internal/stacks/stackplan/planned_change.go @@ -152,14 +152,28 @@ func (pc *PlannedChangeComponentInstance) PlannedChangeProto() (*terraform1.Plan planTimestampStr = pc.PlanTimestamp.Format(time.RFC3339) } + componentAddrsRaw := make([]string, 0, pc.RequiredComponents.Len()) + for _, componentAddr := range pc.RequiredComponents.Elems() { + componentAddrsRaw = append(componentAddrsRaw, componentAddr.String()) + } + + plannedOutputValues := make(map[string]*tfstackdata1.DynamicValue) + for k, v := range pc.PlannedOutputValues { + dv, err := tfstackdata1.DynamicValueToTFStackData1(v, cty.DynamicPseudoType) + if err != nil { + return nil, fmt.Errorf("encoding output value %q: %w", k, err) + } + plannedOutputValues[k] = dv + } + var raw anypb.Any err := anypb.MarshalFrom(&raw, &tfstackdata1.PlanComponentInstance{ - ComponentInstanceAddr: pc.Addr.String(), - 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 - // for external consumption, such as rendering changes in the UI. + ComponentInstanceAddr: pc.Addr.String(), + PlanTimestamp: planTimestampStr, + PlannedInputValues: plannedInputValues, + PlannedAction: planproto.NewAction(pc.Action), + DependsOnComponentAddrs: componentAddrsRaw, + PlannedOutputValues: plannedOutputValues, }, proto.MarshalOptions{}) if err != nil { return nil, err diff --git a/internal/stacks/stackplan/planned_change_test.go b/internal/stacks/stackplan/planned_change_test.go index abef762f0f..a4c01f1681 100644 --- a/internal/stacks/stackplan/planned_change_test.go +++ b/internal/stacks/stackplan/planned_change_test.go @@ -106,6 +106,7 @@ func TestPlannedChangeAsProto(t *testing.T) { mustMarshalAnyPb(&tfstackdata1.PlanComponentInstance{ ComponentInstanceAddr: "component.foo", PlanTimestamp: "2017-03-27T10:00:00-08:00", + PlannedAction: planproto.Action_CREATE, }), }, Descriptions: []*terraform1.PlannedChange_ChangeDescription{ @@ -171,6 +172,7 @@ func TestPlannedChangeAsProto(t *testing.T) { Raw: []*anypb.Any{ mustMarshalAnyPb(&tfstackdata1.PlanComponentInstance{ ComponentInstanceAddr: `stack.a["boop"].component.foo`, + PlannedAction: planproto.Action_DELETE, }), }, Descriptions: []*terraform1.PlannedChange_ChangeDescription{ diff --git a/internal/stacks/stackruntime/internal/stackeval/planning_test.go b/internal/stacks/stackruntime/internal/stackeval/planning_test.go index cd1279366b..7325b6a808 100644 --- a/internal/stacks/stackruntime/internal/stackeval/planning_test.go +++ b/internal/stacks/stackruntime/internal/stackeval/planning_test.go @@ -377,12 +377,80 @@ func TestPlanning_RequiredComponents(t *testing.T) { cmpOpts := collections.CmpOptions t.Run("integrated", func(t *testing.T) { - _, diags := testPlan(t, main) + // This integration tests runs a full plan of the test configuration + // and checks that the resulting plan contains the expected component + // dependency information, without concern for exactly how that + // information got populated. + // + // The other subtests below check that the individual objects + // participating in this plan are reporting their own component + // dependencies correctly, and so if this integrated test fails + // then the simultaneous failure of one of those other tests might be + // a good clue as to what's broken. + + plan, diags := testPlan(t, main) assertNoDiagnostics(t, diags) - // TODO: Once we've got the component dependencies round-tripping - // through the raw plan representation, we should test that the - // plan is capturing the dependencies correctly. + componentPlans := plan.Components + + tests := []struct { + component stackaddrs.AbsComponent + wantDependencies []stackaddrs.AbsComponent + wantDependents []stackaddrs.AbsComponent + }{ + { + component: cmpA, + wantDependencies: []stackaddrs.AbsComponent{}, + wantDependents: []stackaddrs.AbsComponent{ + cmpB, + cmpC, + }, + }, + { + component: cmpB, + wantDependencies: []stackaddrs.AbsComponent{ + cmpA, + }, + wantDependents: []stackaddrs.AbsComponent{ + cmpC, + }, + }, + { + component: cmpC, + wantDependencies: []stackaddrs.AbsComponent{ + cmpA, + cmpB, + }, + wantDependents: []stackaddrs.AbsComponent{}, + }, + } + for _, test := range tests { + t.Run(test.component.String(), func(t *testing.T) { + instAddr := stackaddrs.AbsComponentInstance{ + Stack: test.component.Stack, + Item: stackaddrs.ComponentInstance{ + Component: test.component.Item, + }, + } + cp := componentPlans.Get(instAddr) + { + got := cp.Dependencies + want := collections.NewSet[stackaddrs.AbsComponent]() + want.Add(test.wantDependencies...) + if diff := cmp.Diff(want, got, cmpOpts); diff != "" { + t.Errorf("wrong dependencies\n%s", diff) + } + } + { + got := cp.Dependents + want := collections.NewSet[stackaddrs.AbsComponent]() + want.Add(test.wantDependents...) + if diff := cmp.Diff(want, got, cmpOpts); diff != "" { + t.Errorf("wrong dependents\n%s", diff) + } + } + }) + } }) t.Run("component dependents", func(t *testing.T) { diff --git a/internal/stacks/tfstackdata1/convert.go b/internal/stacks/tfstackdata1/convert.go index 8b907905fd..d6e201ec76 100644 --- a/internal/stacks/tfstackdata1/convert.go +++ b/internal/stacks/tfstackdata1/convert.go @@ -99,6 +99,12 @@ func DynamicValueToTFStackData1(val cty.Value, ty cty.Type) (*DynamicValue, erro return ret, nil } +func DynamicValueFromTFStackData1(protoVal *DynamicValue, ty cty.Type) (cty.Value, error) { + // FIXME: Apply sensitive marks to everything in protoVal.SensitivePath + raw := protoVal.Value.Msgpack + return msgpack.Unmarshal(raw, ty) +} + func Terraform1ToPlanProtoAttributePaths(paths []*terraform1.AttributePath) []*planproto.Path { if len(paths) == 0 { return nil diff --git a/internal/stacks/tfstackdata1/tfstackdata1.pb.go b/internal/stacks/tfstackdata1/tfstackdata1.pb.go index 9c2652aebb..4629a418d1 100644 --- a/internal/stacks/tfstackdata1/tfstackdata1.pb.go +++ b/internal/stacks/tfstackdata1/tfstackdata1.pb.go @@ -280,6 +280,58 @@ type PlanComponentInstance struct { // the input to subsequently applying the component plan but the final // input values should be a valid concretization of what's described here. PlannedInputValues map[string]*DynamicValue `protobuf:"bytes,3,rep,name=planned_input_values,json=plannedInputValues,proto3" json:"planned_input_values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // The action planned for the component as a whole. + // + // This does not directly incorporate actions planned for resource + // instances within this component instance, but does capture a sense + // of the overall action being taken for this particular component + // instance. + // + // The currently-possible values are: + // - CREATE and UPDATE both describe applying a "normal" plan, where + // CREATE additionally represents that the component instance + // did not previously exist. + // - READ describes a refresh-only plan. This is currently possible only + // if the overall stack plan is refresh-only. + // - DELETE describes applying a destroy plan, with the intent of + // deleting all remote objects currently bound to resource instances + // in this component instance. + // + // The value recorded here is used to achieve a few variations needed in + // the apply phase. + PlannedAction planproto.Action `protobuf:"varint,4,opt,name=planned_action,json=plannedAction,proto3,enum=tfplan.Action" json:"planned_action,omitempty"` + // A list of absolute component addresses that this component + // instance depends on according to the configuration the plan was + // created from. (These are components rather than component instances + // because the stacks language evaluation model uses components as the + // most specific granularity for dependency resolution.) + // + // Applying this component instance's plan must wait until any + // CREATE or UPDATE plans for any of the listed component instances have + // completed successfully. Additionally, if any of the component instances + // listed here have DELETE plans then this component instance must also + // have a DELETE plan and the upstream DELETE must wait until this one + // has completed. + // + // A component instance plan that is not DELETE cannot depend on another + // component instance that is not also DELETE, since that would imply that + // this component instance's configuration refers to a component that isn't + // declared, which should therefore have failed validation. + DependsOnComponentAddrs []string `protobuf:"bytes,5,rep,name=depends_on_component_addrs,json=dependsOnComponentAddrs,proto3" json:"depends_on_component_addrs,omitempty"` + // Captures an approximation of the output values for this component with + // as much detail as we knew during the planning phase. + // + // For any planned action other than DELETE this might contain unknown + // values as placeholders for values that won't be determined until the + // apply phase + // + // For a DELETE plan the values should always be known because they are + // based on the prior state for the component, before it has been destroyed. + // The apply phase should use these values to build the representation of + // the component instance as an expression, because for DELETE any + // dependent objects must also be pending DELETE and their delete must + // happen before this instance is destroyed. + PlannedOutputValues map[string]*DynamicValue `protobuf:"bytes,6,rep,name=planned_output_values,json=plannedOutputValues,proto3" json:"planned_output_values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *PlanComponentInstance) Reset() { @@ -335,6 +387,27 @@ func (x *PlanComponentInstance) GetPlannedInputValues() map[string]*DynamicValue return nil } +func (x *PlanComponentInstance) GetPlannedAction() planproto.Action { + if x != nil { + return x.PlannedAction + } + return planproto.Action(0) +} + +func (x *PlanComponentInstance) GetDependsOnComponentAddrs() []string { + if x != nil { + return x.DependsOnComponentAddrs + } + return nil +} + +func (x *PlanComponentInstance) GetPlannedOutputValues() map[string]*DynamicValue { + if x != nil { + return x.PlannedOutputValues + } + return nil +} + // Represents a planned change to a particular resource instance within a // particular component instance. type PlanResourceInstanceChangePlanned struct { @@ -784,7 +857,7 @@ var file_tfstackdata1_proto_rawDesc = []byte{ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc8, 0x02, 0x0a, 0x15, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, + 0x61, 0x6c, 0x75, 0x65, 0x22, 0x92, 0x05, 0x0a, 0x15, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 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, @@ -798,94 +871,114 @@ var file_tfstackdata1_proto_rawDesc = []byte{ 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, - 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x17, - 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, - 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xea, 0x02, 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, 0x50, 0x6c, - 0x61, 0x6e, 0x6e, 0x65, 0x64, 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, 0x34, 0x0a, - 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, - 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x6b, - 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x4b, 0x65, 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, 0x06, 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, 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, 0x12, 0x4c, - 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, - 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 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, 0xd6, 0x01, 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, 0x12, 0x5d, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x74, - 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x56, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x5b, 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x66, 0x73, - 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, - 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 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, + 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x0e, + 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x5f, 0x6f, + 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, + 0x4f, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x73, + 0x12, 0x70, 0x0a, 0x15, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3c, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x50, + 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x70, + 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x17, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x62, 0x0a, 0x18, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, + 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, + 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xea, 0x02, 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, 0x50, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 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, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, + 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x4b, 0x65, 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, 0x06, 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, 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, 0x12, 0x4c, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6f, + 0x72, 0x53, 0x74, 0x61, 0x74, 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, 0xd6, 0x01, 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, 0x12, + 0x5d, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, + 0x64, 0x61, 0x74, 0x61, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x56, 0x31, 0x2e, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x5b, + 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x66, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x64, 0x61, + 0x74, 0x61, 0x31, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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, 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, 0x22, 0x71, 0x0a, 0x0c, 0x44, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, - 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 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, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x22, 0x71, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 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, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -901,7 +994,7 @@ func file_tfstackdata1_proto_rawDescGZIP() []byte { } var file_tfstackdata1_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_tfstackdata1_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_tfstackdata1_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_tfstackdata1_proto_goTypes = []interface{}{ (StateResourceInstanceObjectV1_Status)(0), // 0: tfstackdata1.StateResourceInstanceObjectV1.Status (*PlanHeader)(nil), // 1: tfstackdata1.PlanHeader @@ -915,31 +1008,36 @@ var file_tfstackdata1_proto_goTypes = []interface{}{ (*DynamicValue)(nil), // 9: tfstackdata1.DynamicValue nil, // 10: tfstackdata1.PlanHeader.PrevRunStateRawEntry nil, // 11: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry - nil, // 12: tfstackdata1.StateComponentInstanceV1.OutputValuesEntry - (*planproto.DynamicValue)(nil), // 13: tfplan.DynamicValue - (*planproto.ResourceInstanceChange)(nil), // 14: tfplan.ResourceInstanceChange - (*planproto.Path)(nil), // 15: tfplan.Path - (*anypb.Any)(nil), // 16: google.protobuf.Any + nil, // 12: tfstackdata1.PlanComponentInstance.PlannedOutputValuesEntry + nil, // 13: tfstackdata1.StateComponentInstanceV1.OutputValuesEntry + (*planproto.DynamicValue)(nil), // 14: tfplan.DynamicValue + (planproto.Action)(0), // 15: tfplan.Action + (*planproto.ResourceInstanceChange)(nil), // 16: tfplan.ResourceInstanceChange + (*planproto.Path)(nil), // 17: tfplan.Path + (*anypb.Any)(nil), // 18: google.protobuf.Any } var file_tfstackdata1_proto_depIdxs = []int32{ 10, // 0: tfstackdata1.PlanHeader.prev_run_state_raw:type_name -> tfstackdata1.PlanHeader.PrevRunStateRawEntry - 13, // 1: tfstackdata1.PlanRootInputValue.value:type_name -> tfplan.DynamicValue + 14, // 1: tfstackdata1.PlanRootInputValue.value:type_name -> tfplan.DynamicValue 11, // 2: tfstackdata1.PlanComponentInstance.planned_input_values:type_name -> tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry - 14, // 3: tfstackdata1.PlanResourceInstanceChangePlanned.change:type_name -> tfplan.ResourceInstanceChange - 8, // 4: tfstackdata1.PlanResourceInstanceChangePlanned.prior_state:type_name -> tfstackdata1.StateResourceInstanceObjectV1 - 12, // 5: tfstackdata1.StateComponentInstanceV1.output_values:type_name -> tfstackdata1.StateComponentInstanceV1.OutputValuesEntry - 15, // 6: tfstackdata1.StateResourceInstanceObjectV1.sensitive_paths:type_name -> tfplan.Path - 0, // 7: tfstackdata1.StateResourceInstanceObjectV1.status:type_name -> tfstackdata1.StateResourceInstanceObjectV1.Status - 13, // 8: tfstackdata1.DynamicValue.value:type_name -> tfplan.DynamicValue - 15, // 9: tfstackdata1.DynamicValue.sensitive_paths:type_name -> tfplan.Path - 16, // 10: tfstackdata1.PlanHeader.PrevRunStateRawEntry.value:type_name -> google.protobuf.Any - 9, // 11: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry.value:type_name -> tfstackdata1.DynamicValue - 9, // 12: tfstackdata1.StateComponentInstanceV1.OutputValuesEntry.value:type_name -> tfstackdata1.DynamicValue - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 15, // 3: tfstackdata1.PlanComponentInstance.planned_action:type_name -> tfplan.Action + 12, // 4: tfstackdata1.PlanComponentInstance.planned_output_values:type_name -> tfstackdata1.PlanComponentInstance.PlannedOutputValuesEntry + 16, // 5: tfstackdata1.PlanResourceInstanceChangePlanned.change:type_name -> tfplan.ResourceInstanceChange + 8, // 6: tfstackdata1.PlanResourceInstanceChangePlanned.prior_state:type_name -> tfstackdata1.StateResourceInstanceObjectV1 + 13, // 7: tfstackdata1.StateComponentInstanceV1.output_values:type_name -> tfstackdata1.StateComponentInstanceV1.OutputValuesEntry + 17, // 8: tfstackdata1.StateResourceInstanceObjectV1.sensitive_paths:type_name -> tfplan.Path + 0, // 9: tfstackdata1.StateResourceInstanceObjectV1.status:type_name -> tfstackdata1.StateResourceInstanceObjectV1.Status + 14, // 10: tfstackdata1.DynamicValue.value:type_name -> tfplan.DynamicValue + 17, // 11: tfstackdata1.DynamicValue.sensitive_paths:type_name -> tfplan.Path + 18, // 12: tfstackdata1.PlanHeader.PrevRunStateRawEntry.value:type_name -> google.protobuf.Any + 9, // 13: tfstackdata1.PlanComponentInstance.PlannedInputValuesEntry.value:type_name -> tfstackdata1.DynamicValue + 9, // 14: tfstackdata1.PlanComponentInstance.PlannedOutputValuesEntry.value:type_name -> tfstackdata1.DynamicValue + 9, // 15: tfstackdata1.StateComponentInstanceV1.OutputValuesEntry.value:type_name -> tfstackdata1.DynamicValue + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_tfstackdata1_proto_init() } @@ -1063,7 +1161,7 @@ func file_tfstackdata1_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tfstackdata1_proto_rawDesc, NumEnums: 1, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/stacks/tfstackdata1/tfstackdata1.proto b/internal/stacks/tfstackdata1/tfstackdata1.proto index c7a094e514..018099e174 100644 --- a/internal/stacks/tfstackdata1/tfstackdata1.proto +++ b/internal/stacks/tfstackdata1/tfstackdata1.proto @@ -93,6 +93,61 @@ message PlanComponentInstance { // the input to subsequently applying the component plan but the final // input values should be a valid concretization of what's described here. map planned_input_values = 3; + + // The action planned for the component as a whole. + // + // This does not directly incorporate actions planned for resource + // instances within this component instance, but does capture a sense + // of the overall action being taken for this particular component + // instance. + // + // The currently-possible values are: + // - CREATE and UPDATE both describe applying a "normal" plan, where + // CREATE additionally represents that the component instance + // did not previously exist. + // - READ describes a refresh-only plan. This is currently possible only + // if the overall stack plan is refresh-only. + // - DELETE describes applying a destroy plan, with the intent of + // deleting all remote objects currently bound to resource instances + // in this component instance. + // + // The value recorded here is used to achieve a few variations needed in + // the apply phase. + tfplan.Action planned_action = 4; + + // A list of absolute component addresses that this component + // instance depends on according to the configuration the plan was + // created from. (These are components rather than component instances + // because the stacks language evaluation model uses components as the + // most specific granularity for dependency resolution.) + // + // Applying this component instance's plan must wait until any + // CREATE or UPDATE plans for any of the listed component instances have + // completed successfully. Additionally, if any of the component instances + // listed here have DELETE plans then this component instance must also + // have a DELETE plan and the upstream DELETE must wait until this one + // has completed. + // + // A component instance plan that is not DELETE cannot depend on another + // component instance that is not also DELETE, since that would imply that + // this component instance's configuration refers to a component that isn't + // declared, which should therefore have failed validation. + repeated string depends_on_component_addrs = 5; + + // Captures an approximation of the output values for this component with + // as much detail as we knew during the planning phase. + // + // For any planned action other than DELETE this might contain unknown + // values as placeholders for values that won't be determined until the + // apply phase + // + // For a DELETE plan the values should always be known because they are + // based on the prior state for the component, before it has been destroyed. + // The apply phase should use these values to build the representation of + // the component instance as an expression, because for DELETE any + // dependent objects must also be pending DELETE and their delete must + // happen before this instance is destroyed. + map planned_output_values = 6; } // Represents a planned change to a particular resource instance within a