diff --git a/internal/addrs/action.go b/internal/addrs/action.go index 4ed1a55b8e..8392a5847e 100644 --- a/internal/addrs/action.go +++ b/internal/addrs/action.go @@ -7,6 +7,9 @@ import ( "fmt" "strings" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/hashicorp/terraform/internal/tfdiags" ) @@ -284,7 +287,7 @@ func (a AbsActionInstance) UniqueKey() UniqueKey { return absActionInstanceKey(a.String()) } -func (r absActionInstanceKey) uniqueKeySigil() {} +func (a absActionInstanceKey) uniqueKeySigil() {} // ConfigAction is the address for an action within the configuration. type ConfigAction struct { @@ -337,7 +340,7 @@ type AbsActionInvocationInstance struct { TriggerIndex int // TriggerBlockSourceRange is the location of the action_trigger block - // within the resources lifecyclye block that triggered this action. + // within the resources lifecycle block that triggered this action. TriggerBlockSourceRange *tfdiags.SourceRange // ActionReferenceSourceRange is the location of the action reference @@ -348,3 +351,152 @@ type AbsActionInvocationInstance struct { func (a AbsActionInvocationInstance) String() string { return fmt.Sprintf("%s.%d.%s", a.TriggeringResource.String(), a.TriggerIndex, a.Action.String()) } + +// ParseAbsActionInstanceStr is a helper wrapper around +// ParseAbsActionInstance that takes a string and parses it with the HCL +// native syntax traversal parser before interpreting it. +// +// Error diagnostics are returned if either the parsing fails or the analysis +// of the traversal fails. There is no way for the caller to distinguish the +// two kinds of diagnostics programmatically. If error diagnostics are returned +// the returned address may be incomplete. +// +// Since this function has no context about the source of the given string, +// any returned diagnostics will not have meaningful source location +// information. +func ParseAbsActionInstanceStr(str string) (AbsActionInstance, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1}) + diags = diags.Append(parseDiags) + if parseDiags.HasErrors() { + return AbsActionInstance{}, diags + } + + addr, addrDiags := ParseAbsActionInstance(traversal) + diags = diags.Append(addrDiags) + return addr, diags +} + +// ParseAbsActionInstance attempts to interpret the given traversal as an +// absolute action instance address, using the same syntax as expected by +// ParseTarget. +// +// If no error diagnostics are returned, the returned target includes the +// address that was extracted and the source range it was extracted from. +// +// If error diagnostics are returned then the AbsResource value is invalid and +// must not be used. +func ParseAbsActionInstance(traversal hcl.Traversal) (AbsActionInstance, tfdiags.Diagnostics) { + moduleAddr, remain, diags := parseModuleInstancePrefix(traversal, false) + if diags.HasErrors() { + return AbsActionInstance{}, diags + } + + if remain.IsRelative() { + // (relative means that there's either nothing left or what's next isn't an identifier) + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid action address", + Detail: "Module path must be followed by an action instance address.", + Subject: remain.SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + + if remain.RootName() != "action" { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "Action address must start with \"action.\".", + Subject: remain[0].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + remain = remain[1:] + + if len(remain) < 2 { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "Action specification must include an action type and name.", + Subject: remain.SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + + var actionType, name string + switch tt := remain[0].(type) { + case hcl.TraverseRoot: + actionType = tt.Name + case hcl.TraverseAttr: + actionType = tt.Name + default: + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid action address", + Detail: "An action name is required.", + Subject: remain[0].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + + switch tt := remain[1].(type) { + case hcl.TraverseAttr: + name = tt.Name + default: + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "An action name is required.", + Subject: remain[1].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + + remain = remain[2:] + switch len(remain) { + case 0: + return moduleAddr.ActionInstance(actionType, name, NoKey), diags + case 1: + switch tt := remain[0].(type) { + case hcl.TraverseIndex: + key, err := ParseInstanceKey(tt.Key) + if err != nil { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: fmt.Sprintf("Invalid resource instance key: %s.", err), + Subject: remain[0].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + return moduleAddr.ActionInstance(actionType, name, key), diags + case hcl.TraverseSplat: + // Not yet supported! + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "Action instance key must be given in square brackets.", + Subject: remain[0].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + default: + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "Action instance key must be given in square brackets.", + Subject: remain[0].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } + default: + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: "Unexpected extra operators after address.", + Subject: remain[1].SourceRange().Ptr(), + }) + return AbsActionInstance{}, diags + } +} diff --git a/internal/addrs/action_test.go b/internal/addrs/action_test.go index 9415958759..b72f96c3f4 100644 --- a/internal/addrs/action_test.go +++ b/internal/addrs/action_test.go @@ -341,3 +341,75 @@ func TestAbsActionUniqueKey(t *testing.T) { }) } } + +func TestParseAbsActionInstance(t *testing.T) { + tests := []struct { + input string + want AbsActionInstance + expectErr bool + }{ + { + "", + AbsActionInstance{}, + true, + }, + { + "action.example.foo", + AbsActionInstance{ + Action: ActionInstance{ + Action: Action{ + Type: "example", + Name: "foo", + }, + Key: NoKey, + }, + Module: RootModuleInstance, + }, + false, + }, + { + "action.example.foo[0]", + AbsActionInstance{ + Action: ActionInstance{ + Action: Action{ + Type: "example", + Name: "foo", + }, + Key: IntKey(0), + }, + Module: RootModuleInstance, + }, + false, + }, + { + "action.example.foo[\"bar\"]", + AbsActionInstance{ + Action: ActionInstance{ + Action: Action{ + Type: "example", + Name: "foo", + }, + Key: StringKey("bar"), + }, + Module: RootModuleInstance, + }, + false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("ParseAbsActionStr(%s)", test.input), func(t *testing.T) { + got, gotDiags := ParseAbsActionInstanceStr(test.input) + if gotDiags.HasErrors() != test.expectErr { + if !test.expectErr { + t.Fatalf("wrong results! Expected success, got error: %s\n", gotDiags.Err()) + } else { + t.Fatal("wrong results! Expected error(s), got success!") + } + } + if !got.Equal(test.want) { + t.Fatalf("wrong result! Got %s, wanted %s", got.String(), test.want.String()) + } + }) + } +} diff --git a/internal/command/jsonformat/plan.go b/internal/command/jsonformat/plan.go index ab33da9eb0..5e4f0539c8 100644 --- a/internal/command/jsonformat/plan.go +++ b/internal/command/jsonformat/plan.go @@ -7,11 +7,10 @@ import ( "bytes" "encoding/json" "fmt" + "slices" "sort" "strings" - "slices" - "github.com/hashicorp/terraform/internal/command/format" "github.com/hashicorp/terraform/internal/command/jsonformat/computed" "github.com/hashicorp/terraform/internal/command/jsonformat/computed/renderers" @@ -33,6 +32,7 @@ type Plan struct { ResourceDrift []jsonplan.ResourceChange `json:"resource_drift,omitempty"` RelevantAttributes []jsonplan.ResourceAttr `json:"relevant_attributes,omitempty"` DeferredChanges []jsonplan.DeferredResourceChange `json:"deferred_changes,omitempty"` + ActionInvocations []jsonplan.ActionInvocation `json:"action_invocations,omitempty"` ProviderFormatVersion string `json:"provider_format_version"` ProviderSchemas map[string]*jsonprovider.Provider `json:"provider_schemas,omitempty"` diff --git a/internal/command/jsonformat/state_test.go b/internal/command/jsonformat/state_test.go index 2a4e3979f6..9c4eafa50b 100644 --- a/internal/command/jsonformat/state_test.go +++ b/internal/command/jsonformat/state_test.go @@ -9,19 +9,17 @@ import ( "github.com/google/go-cmp/cmp" "github.com/mitchellh/colorstring" - - "github.com/hashicorp/terraform/internal/command/jsonprovider" - "github.com/hashicorp/terraform/internal/command/jsonstate" - testing_provider "github.com/hashicorp/terraform/internal/providers/testing" - "github.com/hashicorp/terraform/internal/states/statefile" - "github.com/hashicorp/terraform/internal/terminal" - "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/command/jsonprovider" + "github.com/hashicorp/terraform/internal/command/jsonstate" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/providers" + testing_provider "github.com/hashicorp/terraform/internal/providers/testing" "github.com/hashicorp/terraform/internal/states" + "github.com/hashicorp/terraform/internal/states/statefile" + "github.com/hashicorp/terraform/internal/terminal" "github.com/hashicorp/terraform/internal/terraform" ) diff --git a/internal/command/jsonplan/action_invocations.go b/internal/command/jsonplan/action_invocations.go new file mode 100644 index 0000000000..1954cc78df --- /dev/null +++ b/internal/command/jsonplan/action_invocations.go @@ -0,0 +1,34 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package jsonplan + +import ( + "github.com/hashicorp/terraform/internal/plans" +) + +type ActionInvocation struct { + // Address is the absolute action address + Address string `json:"address,omitempty"` + + // ProviderName allows the property "type" to be interpreted unambiguously + // in the unusual situation where a provider offers a type whose + // name does not start with its own name, such as the "googlebeta" provider + // offering "google_compute_instance". + ProviderName string `json:"provider_name,omitempty"` +} + +func MarshalActionInvocations(actions []*plans.ActionInvocationInstanceSrc) ([]ActionInvocation, error) { + ret := make([]ActionInvocation, 0, len(actions)) + + for _, action := range actions { + ai := ActionInvocation{ + Address: action.Addr.String(), + ProviderName: action.ProviderAddr.String(), + } + + ret = append(ret, ai) + } + + return ret, nil +} diff --git a/internal/command/jsonplan/plan.go b/internal/command/jsonplan/plan.go index 16bd9d07e7..9531742c5a 100644 --- a/internal/command/jsonplan/plan.go +++ b/internal/command/jsonplan/plan.go @@ -68,6 +68,7 @@ type plan struct { ResourceChanges []ResourceChange `json:"resource_changes,omitempty"` DeferredChanges []DeferredResourceChange `json:"deferred_changes,omitempty"` OutputChanges map[string]Change `json:"output_changes,omitempty"` + ActionInvocations []ActionInvocation `json:"action_invocations,omitempty"` PriorState json.RawMessage `json:"prior_state,omitempty"` Config json.RawMessage `json:"configuration,omitempty"` RelevantAttributes []ResourceAttr `json:"relevant_attributes,omitempty"` @@ -201,16 +202,16 @@ type variable struct { func MarshalForRenderer( p *plans.Plan, schemas *terraform.Schemas, -) (map[string]Change, []ResourceChange, []ResourceChange, []ResourceAttr, error) { +) (map[string]Change, []ResourceChange, []ResourceChange, []ResourceAttr, []ActionInvocation, error) { output := newPlan() var err error if output.OutputChanges, err = MarshalOutputChanges(p.Changes); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } if output.ResourceChanges, err = MarshalResourceChanges(p.Changes.Resources, schemas); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } if len(p.DriftedResources) > 0 { @@ -230,15 +231,19 @@ func MarshalForRenderer( } output.ResourceDrift, err = MarshalResourceChanges(driftedResources, schemas) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } } if err := output.marshalRelevantAttrs(p); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } - return output.OutputChanges, output.ResourceChanges, output.ResourceDrift, output.RelevantAttributes, nil + if output.ActionInvocations, err = MarshalActionInvocations(p.ActionInvocations); err != nil { + return nil, nil, nil, nil, nil, err + } + + return output.OutputChanges, output.ResourceChanges, output.ResourceDrift, output.RelevantAttributes, output.ActionInvocations, nil } // Marshal returns the json encoding of a terraform plan. @@ -331,6 +336,13 @@ func Marshal( return nil, fmt.Errorf("error marshaling config: %s", err) } + // output.ActionInvocations + if p.ActionInvocations != nil { + if output.ActionInvocations, err = MarshalActionInvocations(p.ActionInvocations); err != nil { + return nil, fmt.Errorf("error marshaling action invocations: %s", err) + } + } + return json.Marshal(output) } diff --git a/internal/command/views/hook_ui.go b/internal/command/views/hook_ui.go index 1090d656b2..4b1fd8865a 100644 --- a/internal/command/views/hook_ui.go +++ b/internal/command/views/hook_ui.go @@ -12,9 +12,9 @@ import ( "time" "unicode" + "github.com/hashicorp/go-hclog" "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/command/format" "github.com/hashicorp/terraform/internal/logging" diff --git a/internal/command/views/operation.go b/internal/command/views/operation.go index b5e0d388a3..f9f4e2c84e 100644 --- a/internal/command/views/operation.go +++ b/internal/command/views/operation.go @@ -92,7 +92,7 @@ func (v *OperationHuman) EmergencyDumpState(stateFile *statefile.File) error { } func (v *OperationHuman) Plan(plan *plans.Plan, schemas *terraform.Schemas) { - outputs, changed, drift, attrs, err := jsonplan.MarshalForRenderer(plan, schemas) + outputs, changed, drift, attrs, actions, err := jsonplan.MarshalForRenderer(plan, schemas) if err != nil { v.view.streams.Eprintf("Failed to marshal plan to json: %s", err) return @@ -112,6 +112,7 @@ func (v *OperationHuman) Plan(plan *plans.Plan, schemas *terraform.Schemas) { ResourceDrift: drift, ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, + ActionInvocations: actions, } // Side load some data that we can't extract from the JSON plan. diff --git a/internal/command/views/show.go b/internal/command/views/show.go index 87692b5aa5..50429aa315 100644 --- a/internal/command/views/show.go +++ b/internal/command/views/show.go @@ -71,7 +71,7 @@ func (v *ShowHuman) Display(config *configs.Config, plan *plans.Plan, planJSON * renderer.RenderHumanPlan(p, planJSON.Mode, planJSON.Qualities...) v.view.streams.Print(v.view.colorize.Color("\n" + planJSON.RunFooter + "\n")) } else if plan != nil { - outputs, changed, drift, attrs, err := jsonplan.MarshalForRenderer(plan, schemas) + outputs, changed, drift, attrs, actions, err := jsonplan.MarshalForRenderer(plan, schemas) if err != nil { v.view.streams.Eprintf("Failed to marshal plan to json: %s", err) return 1 @@ -85,6 +85,7 @@ func (v *ShowHuman) Display(config *configs.Config, plan *plans.Plan, planJSON * ResourceDrift: drift, ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, + ActionInvocations: actions, } var opts []plans.Quality diff --git a/internal/command/views/test.go b/internal/command/views/test.go index e4a5b0acd8..77540aded0 100644 --- a/internal/command/views/test.go +++ b/internal/command/views/test.go @@ -208,7 +208,7 @@ func (t *TestHuman) Run(run *moduletest.Run, file *moduletest.File, progress mod } } else { // We'll print the plan. - outputs, changed, drift, attrs, err := jsonplan.MarshalForRenderer(run.Verbose.Plan, schemas) + outputs, changed, drift, attrs, actions, err := jsonplan.MarshalForRenderer(run.Verbose.Plan, schemas) if err != nil { run.Diagnostics = run.Diagnostics.Append(tfdiags.Sourceless( tfdiags.Warning, @@ -223,6 +223,7 @@ func (t *TestHuman) Run(run *moduletest.Run, file *moduletest.File, progress mod ResourceDrift: drift, ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, + ActionInvocations: actions, } var opts []plans.Quality @@ -571,7 +572,7 @@ func (t *TestJSON) Run(run *moduletest.Run, file *moduletest.File, progress modu "@testrun", run.Name) } } else { - outputs, changed, drift, attrs, err := jsonplan.MarshalForRenderer(run.Verbose.Plan, schemas) + outputs, changed, drift, attrs, actions, err := jsonplan.MarshalForRenderer(run.Verbose.Plan, schemas) if err != nil { run.Diagnostics = run.Diagnostics.Append(tfdiags.Sourceless( tfdiags.Warning, @@ -586,6 +587,7 @@ func (t *TestJSON) Run(run *moduletest.Run, file *moduletest.File, progress modu ResourceDrift: drift, ProviderSchemas: jsonprovider.MarshalForRenderer(schemas, false), RelevantAttributes: attrs, + ActionInvocations: actions, } t.view.log.Info( diff --git a/internal/grpcwrap/provider.go b/internal/grpcwrap/provider.go index ad5f6020f4..8f3cc2496c 100644 --- a/internal/grpcwrap/provider.go +++ b/internal/grpcwrap/provider.go @@ -106,7 +106,7 @@ func (p *provider) GetSchema(_ context.Context, req *tfplugin5.GetProviderSchema } else if act.Lifecycle != nil { newAct.Type = &tfplugin5.ActionSchema_Lifecycle_{ Lifecycle: &tfplugin5.ActionSchema_Lifecycle{ - Executes: convert.ExecutionOrderToProto(act.Lifecycle.Exectues), + Executes: convert.ExecutionOrderToProto(act.Lifecycle.Executes), LinkedResource: convert.LinkedResourceToProto(act.Lifecycle.LinkedResource), }, } diff --git a/internal/grpcwrap/provider6.go b/internal/grpcwrap/provider6.go index 3a0583e9ca..e475fbf637 100644 --- a/internal/grpcwrap/provider6.go +++ b/internal/grpcwrap/provider6.go @@ -115,7 +115,7 @@ func (p *provider6) GetProviderSchema(_ context.Context, req *tfplugin6.GetProvi } else if act.Lifecycle != nil { newAct.Type = &tfplugin6.ActionSchema_Lifecycle_{ Lifecycle: &tfplugin6.ActionSchema_Lifecycle{ - Executes: convert.ExecutionOrderToProto(act.Lifecycle.Exectues), + Executes: convert.ExecutionOrderToProto(act.Lifecycle.Executes), LinkedResource: convert.LinkedResourceToProto(act.Lifecycle.LinkedResource), }, } diff --git a/internal/plans/action_invocation.go b/internal/plans/action_invocation.go new file mode 100644 index 0000000000..bacfff1e72 --- /dev/null +++ b/internal/plans/action_invocation.go @@ -0,0 +1,51 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package plans + +import ( + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/providers" +) + +type ActionInvocationInstance struct { + Addr addrs.AbsActionInstance // mildwonkey TODO: this will be a *trigger* instance when that pr merges + + // Provider is the address of the provider configuration that was used + // to plan this action, and thus the configuration that must also be + // used to apply it. + ProviderAddr addrs.AbsProviderConfig +} + +// Encode produces a variant of the receiver that has its change values +// serialized so it can be written to a plan file. Pass the implied type of the +// corresponding resource type schema for correct operation. +func (ai *ActionInvocationInstance) Encode(schema providers.Schema) (*ActionInvocationInstanceSrc, error) { + return &ActionInvocationInstanceSrc{ + Addr: ai.Addr, + ProviderAddr: ai.ProviderAddr, + }, nil +} + +type ActionInvocationInstances []*ActionInvocationInstance + +func (ais ActionInvocationInstances) DeepCopy() ActionInvocationInstances { + if ais == nil { + return ais + } + + ret := make(ActionInvocationInstances, len(ais)) + for i, ai := range ais { + ret[i] = ai.DeepCopy() + } + return ret +} + +func (ai *ActionInvocationInstance) DeepCopy() *ActionInvocationInstance { + if ai == nil { + return ai + } + + ret := *ai + return &ret +} diff --git a/internal/plans/changes.go b/internal/plans/changes.go index 5ed41122ac..209a650838 100644 --- a/internal/plans/changes.go +++ b/internal/plans/changes.go @@ -25,6 +25,10 @@ type Changes struct { Queries []*QueryInstance + // ActionInvocations tracks planned action invocations, which may have + // embedded resource instance changes. + ActionInvocations ActionInvocationInstances + // Outputs tracks planned changes output values. // // Note that although an in-memory plan contains planned changes for @@ -243,6 +247,29 @@ func (c *Changes) SyncWrapper() *ChangesSync { } } +// ActionInvocations returns planned action invocations for all module instances +// that reside in the parent path. Returns nil if no changes are planned. +func (c *Changes) ActionInstances(parent addrs.ModuleInstance, module addrs.ModuleCall) []*ActionInvocationInstance { + var ret []*ActionInvocationInstance + + for _, a := range c.ActionInvocations { + changeMod, changeCall := a.Addr.Module.Call() + // this does not reside on our parent instance path + if !changeMod.Equal(parent) { + continue + } + + // this is not the module you're looking for + if changeCall.Name != module.Name { + continue + } + + ret = append(ret, a) + } + + return ret +} + type QueryInstance struct { Addr addrs.AbsResourceInstance @@ -347,7 +374,7 @@ type ResourceInstanceChange struct { Private []byte } -// Encode produces a variant of the reciever that has its change values +// Encode produces a variant of the receiver that has its change values // serialized so it can be written to a plan file. Pass the implied type of the // corresponding resource type schema for correct operation. func (rc *ResourceInstanceChange) Encode(schema providers.Schema) (*ResourceInstanceChangeSrc, error) { @@ -387,7 +414,7 @@ func (rc *ResourceInstanceChange) Moved() bool { } // Simplify will, where possible, produce a change with a simpler action than -// the receiever given a flag indicating whether the caller is dealing with +// the receiver given a flag indicating whether the caller is dealing with // a normal apply or a destroy. This flag deals with the fact that Terraform // Core uses a specialized graph node type for destroying; only that // specialized node should set "destroying" to true. @@ -601,7 +628,7 @@ type OutputChange struct { Sensitive bool } -// Encode produces a variant of the reciever that has its change values +// Encode produces a variant of the receiver that has its change values // serialized so it can be written to a plan file. func (oc *OutputChange) Encode() (*OutputChangeSrc, error) { cs, err := oc.Change.Encode(nil) @@ -689,7 +716,7 @@ type Change struct { GeneratedConfig string } -// Encode produces a variant of the reciever that has its change values +// Encode produces a variant of the receiver that has its change values // serialized so it can be written to a plan file. Pass the type constraint // that the values are expected to conform to; to properly decode the values // later an identical type constraint must be provided at that time. diff --git a/internal/plans/changes_src.go b/internal/plans/changes_src.go index 8df9f78640..8cff2688eb 100644 --- a/internal/plans/changes_src.go +++ b/internal/plans/changes_src.go @@ -27,6 +27,10 @@ type ChangesSrc struct { Queries []*QueryInstanceSrc + // ActionInvocations tracks planned action invocations, which may have + // embedded resource instance changes. + Actions []*ActionInvocationInstanceSrc + // Outputs tracks planned changes output values. // // Note that although an in-memory plan contains planned changes for @@ -155,6 +159,20 @@ func (c *ChangesSrc) Decode(schemas *schemarepo.Schemas) (*Changes, error) { changes.Queries = append(changes.Queries, query) } + for _, ais := range c.Actions { + p, ok := schemas.Providers[ais.ProviderAddr.Provider] + if !ok { + return nil, fmt.Errorf("ChangesSrc.Decode: missing provider %s for action %s", ais.ProviderAddr, ais.Addr) + } + + action, err := ais.Decode(p) + if err != nil { + return nil, err + } + + changes.ActionInvocations = append(changes.ActionInvocations, action) + } + for _, ocs := range c.Outputs { oc, err := ocs.Decode() if err != nil { @@ -530,3 +548,42 @@ func (cs *ChangeSrc) Decode(schema *providers.Schema) (*Change, error) { GeneratedConfig: cs.GeneratedConfig, }, nil } + +// AppendResourceInstanceChange records the given resource instance change in +// the set of planned resource changes. +func (c *ChangesSrc) AppendActionInvocationInstanceChange(action *ActionInvocationInstanceSrc) { + if c == nil { + panic("AppendResourceInstanceChange on nil ChangesSync") + } + + a := action.DeepCopy() + c.Actions = append(c.Actions, a) +} + +type ActionInvocationInstanceSrc struct { + Addr addrs.AbsActionInstance + + ProviderAddr addrs.AbsProviderConfig +} + +// Decode unmarshals the raw representation of any linked resources. +func (acs *ActionInvocationInstanceSrc) Decode(schema providers.ProviderSchema) (*ActionInvocationInstance, error) { + as := schema.Actions[acs.Addr.Action.Action.Type] + + if as.IsNil() { + return nil, fmt.Errorf("ActionInstanceSrc.Decode: missing schema for %s", acs.Addr) + } + + ai := &ActionInvocationInstance{ + Addr: acs.Addr, + } + return ai, nil +} + +func (acs *ActionInvocationInstanceSrc) DeepCopy() *ActionInvocationInstanceSrc { + if acs == nil { + return acs + } + ret := *acs + return &ret +} diff --git a/internal/plans/changes_sync.go b/internal/plans/changes_sync.go index 8a6b7e5cc3..c346474708 100644 --- a/internal/plans/changes_sync.go +++ b/internal/plans/changes_sync.go @@ -238,3 +238,50 @@ func (cs *ChangesSync) RemoveOutputChange(addr addrs.AbsOutputValue) { return } } + +// GetActionInvocation +func (cs *ChangesSync) GetActionInvocation(addr addrs.AbsActionInstance) *ActionInvocationInstance { + if cs == nil { + panic("GetActionInvocation on nil ChangesSync") + } + cs.lock.Lock() + defer cs.lock.Unlock() + + for _, a := range cs.changes.ActionInvocations { + if a.Addr.Equal(addr) { + return a + } + } + return nil +} + +// AppendActionInvocation +func (cs *ChangesSync) AppendActionInvocation(action *ActionInvocationInstance) { + if cs == nil { + panic("AppendActionInvocation on nil ChangesSync") + } + cs.lock.Lock() + defer cs.lock.Unlock() + + cs.changes.ActionInvocations = append(cs.changes.ActionInvocations, action) +} + +// RemoveActionInvocation searches the set of action invocations for one +// matching the given address, and removes it from the set if it exists. +func (cs *ChangesSync) RemoveActionInvocation(addr addrs.AbsActionInstance) { + if cs == nil { + panic("RemoveActionInvocation on nil ChangesSync") + } + cs.lock.Lock() + defer cs.lock.Unlock() + + addrStr := addr.String() + for i, a := range cs.changes.ActionInvocations { + if a.Addr.String() != addrStr { + continue + } + copy(cs.changes.ActionInvocations[i:], cs.changes.ActionInvocations[i+1:]) + cs.changes.ActionInvocations = cs.changes.ActionInvocations[:len(cs.changes.ActionInvocations)-1] + return + } +} diff --git a/internal/plans/changes_test.go b/internal/plans/changes_test.go index b20fd4f045..c5f2e799cd 100644 --- a/internal/plans/changes_test.go +++ b/internal/plans/changes_test.go @@ -7,10 +7,11 @@ import ( "fmt" "testing" + "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/lang/marks" "github.com/hashicorp/terraform/internal/providers" - "github.com/zclconf/go-cty/cty" ) func TestChangeEncodeSensitive(t *testing.T) { @@ -98,7 +99,7 @@ func TestChangeEncodeError(t *testing.T) { Change: Change{ Before: cty.NullVal(cty.DynamicPseudoType), // can't encode a marked value - After: cty.StringVal("test").Mark("shoult not be here"), + After: cty.StringVal("test").Mark("should not be here"), }, }, }, diff --git a/internal/plans/plan.go b/internal/plans/plan.go index 7b43f5b020..c4669b64e5 100644 --- a/internal/plans/plan.go +++ b/internal/plans/plan.go @@ -7,10 +7,10 @@ import ( "sort" "time" - "github.com/zclconf/go-cty/cty" - version "github.com/hashicorp/go-version" tfaddr "github.com/hashicorp/terraform-registry-address" + "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/configs/configschema" @@ -67,6 +67,7 @@ type Plan struct { ApplyTimeVariables collections.Set[string] Changes *ChangesSrc + ActionInvocations []*ActionInvocationInstanceSrc DriftedResources []*ResourceInstanceChangeSrc DeferredResources []*DeferredResourceInstanceChangeSrc TargetAddrs []addrs.Targetable diff --git a/internal/plans/planfile/planfile_test.go b/internal/plans/planfile/planfile_test.go index b2819be8d8..e3d22bf5e9 100644 --- a/internal/plans/planfile/planfile_test.go +++ b/internal/plans/planfile/planfile_test.go @@ -68,7 +68,8 @@ func TestRoundtrip(t *testing.T) { Config: plans.DynamicValue([]byte("config placeholder")), Workspace: "default", }, - Checks: &states.CheckResults{}, + Checks: &states.CheckResults{}, + ActionInvocations: []*plans.ActionInvocationInstanceSrc{}, // Due to some historical oddities in how we've changed modelling over // time, we also include the states (without the corresponding file diff --git a/internal/plans/planfile/tfplan.go b/internal/plans/planfile/tfplan.go index 743472be58..632b639bc3 100644 --- a/internal/plans/planfile/tfplan.go +++ b/internal/plans/planfile/tfplan.go @@ -68,6 +68,7 @@ func readTfplan(r io.Reader) (*plans.Plan, error) { DriftedResources: []*plans.ResourceInstanceChangeSrc{}, DeferredResources: []*plans.DeferredResourceInstanceChangeSrc{}, Checks: &states.CheckResults{}, + ActionInvocations: []*plans.ActionInvocationInstanceSrc{}, } plan.Applyable = rawPlan.Applyable @@ -179,6 +180,16 @@ func readTfplan(r io.Reader) (*plans.Plan, error) { ) } + for _, rawAction := range rawPlan.ActionInvocations { + action, err := actionInvocationFromTfplan(rawAction) + if err != nil { + // errors from actionInvocationFromTfplan already include context + return nil, err + } + + plan.ActionInvocations = append(plan.ActionInvocations, action) + } + switch { case rawPlan.Backend == nil && rawPlan.StateStore == nil: // Similar validation in writeTfPlan should prevent this occurring @@ -561,12 +572,13 @@ func writeTfplan(plan *plans.Plan, w io.Writer) error { Version: tfplanFormatVersion, TerraformVersion: version.String(), - Variables: map[string]*planproto.DynamicValue{}, - OutputChanges: []*planproto.OutputChange{}, - CheckResults: []*planproto.CheckResults{}, - ResourceChanges: []*planproto.ResourceInstanceChange{}, - ResourceDrift: []*planproto.ResourceInstanceChange{}, - DeferredChanges: []*planproto.DeferredResourceInstanceChange{}, + Variables: map[string]*planproto.DynamicValue{}, + OutputChanges: []*planproto.OutputChange{}, + CheckResults: []*planproto.CheckResults{}, + ResourceChanges: []*planproto.ResourceInstanceChange{}, + ResourceDrift: []*planproto.ResourceInstanceChange{}, + DeferredChanges: []*planproto.DeferredResourceInstanceChange{}, + ActionInvocations: []*planproto.ActionInvocation{}, } rawPlan.Applyable = plan.Applyable @@ -666,6 +678,14 @@ func writeTfplan(plan *plans.Plan, w io.Writer) error { ) } + for _, action := range plan.ActionInvocations { + rawAction, err := actionInvocationToTfPlan(action) + if err != nil { + return err + } + rawPlan.ActionInvocations = append(rawPlan.ActionInvocations, rawAction) + } + // Store details about accessing state backendInUse := plan.Backend.Type != "" && plan.Backend.Config != nil stateStoreInUse := plan.StateStore.Type != "" && plan.StateStore.Config != nil @@ -752,7 +772,7 @@ func resourceAttrFromTfplan(ra *planproto.PlanResourceAttr) (globalref.ResourceA // in its own wire format while using a different overall container. func ResourceChangeToProto(change *plans.ResourceInstanceChangeSrc) (*planproto.ResourceInstanceChange, error) { if change == nil { - // We assume this represents the absense of a change, then. + // We assume this represents the absence of a change, then. return nil, nil } return resourceChangeToTfplan(change) @@ -1224,3 +1244,38 @@ func CheckResultsToPlanProto(checkResults *states.CheckResults) ([]*planproto.Ch return nil, nil } } + +func actionInvocationFromTfplan(rawAction *planproto.ActionInvocation) (*plans.ActionInvocationInstanceSrc, error) { + if rawAction == nil { + // Should never happen in practice, since protobuf can't represent + // a nil value in a list. + return nil, fmt.Errorf("action invocation object is absent") + } + + ret := &plans.ActionInvocationInstanceSrc{} + actionAddr, diags := addrs.ParseAbsActionInstanceStr(rawAction.Addr) + if diags.HasErrors() { + return nil, fmt.Errorf("invalid resource instance address %q: %w", rawAction.Addr, diags.Err()) + } + ret.Addr = actionAddr + + providerAddr, diags := addrs.ParseAbsProviderConfigStr(rawAction.Provider) + if diags.HasErrors() { + return nil, diags.Err() + } + ret.ProviderAddr = providerAddr + + return ret, nil +} + +func actionInvocationToTfPlan(action *plans.ActionInvocationInstanceSrc) (*planproto.ActionInvocation, error) { + if action == nil { + return nil, nil + } + + ret := &planproto.ActionInvocation{ + Addr: action.Addr.String(), + Provider: action.ProviderAddr.String(), + } + return ret, nil +} diff --git a/internal/plans/planfile/tfplan_test.go b/internal/plans/planfile/tfplan_test.go index 0992cd6fd9..f9eafb47fa 100644 --- a/internal/plans/planfile/tfplan_test.go +++ b/internal/plans/planfile/tfplan_test.go @@ -176,6 +176,11 @@ func examplePlanForTest(t *testing.T) *plans.Plan { applyTimeVariables := collections.NewSetCmp[string]() applyTimeVariables.Add("bar") + provider := addrs.AbsProviderConfig{ + Provider: addrs.NewDefaultProvider("test"), + Module: addrs.RootModule, + } + return &plans.Plan{ Applyable: true, Complete: true, @@ -224,10 +229,7 @@ func examplePlanForTest(t *testing.T) *plans.Plan { Type: "test_thing", Name: "woot", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("test"), - Module: addrs.RootModule, - }, + ProviderAddr: provider, ChangeSrc: plans.ChangeSrc{ Action: plans.DeleteThenCreate, Before: mustNewDynamicValue(cty.ObjectVal(map[string]cty.Value{ @@ -286,10 +288,7 @@ func examplePlanForTest(t *testing.T) *plans.Plan { Type: "test_thing", Name: "importing", }.Instance(addrs.IntKey(1)).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("test"), - Module: addrs.RootModule, - }, + ProviderAddr: provider, ChangeSrc: plans.ChangeSrc{ Action: plans.NoOp, Before: mustNewDynamicValue(cty.ObjectVal(map[string]cty.Value{ @@ -316,10 +315,7 @@ func examplePlanForTest(t *testing.T) *plans.Plan { Type: "test_thing", Name: "woot", }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("test"), - Module: addrs.RootModule, - }, + ProviderAddr: provider, ChangeSrc: plans.ChangeSrc{ Action: plans.DeleteThenCreate, Before: mustNewDynamicValue(cty.ObjectVal(map[string]cty.Value{ @@ -350,10 +346,7 @@ func examplePlanForTest(t *testing.T) *plans.Plan { Type: "test_thing", Name: "woot", }.Instance(addrs.WildcardKey).Absolute(addrs.RootModuleInstance), - ProviderAddr: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("test"), - Module: addrs.RootModule, - }, + ProviderAddr: provider, ChangeSrc: plans.ChangeSrc{ Action: plans.Create, After: mustNewDynamicValue(cty.ObjectVal(map[string]cty.Value{ @@ -379,10 +372,7 @@ func examplePlanForTest(t *testing.T) *plans.Plan { InstanceKey: addrs.WildcardKey, }, }), - ProviderAddr: addrs.AbsProviderConfig{ - Provider: addrs.NewDefaultProvider("test"), - Module: addrs.RootModule, - }, + ProviderAddr: provider, ChangeSrc: plans.ChangeSrc{ Action: plans.Create, After: mustNewDynamicValue(cty.ObjectVal(map[string]cty.Value{ @@ -471,6 +461,12 @@ func examplePlanForTest(t *testing.T) *plans.Plan { ), Workspace: "default", }, + ActionInvocations: []*plans.ActionInvocationInstanceSrc{ + { + Addr: addrs.Action{Type: "example", Name: "foo"}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + ProviderAddr: provider, + }, + }, } } diff --git a/internal/plans/planproto/planfile.pb.go b/internal/plans/planproto/planfile.pb.go index 23a2ae8699..381e6ad28e 100644 --- a/internal/plans/planproto/planfile.pb.go +++ b/internal/plans/planproto/planfile.pb.go @@ -10,11 +10,12 @@ package planproto import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" unsafe "unsafe" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( @@ -472,6 +473,9 @@ type Plan struct { // checks, and each of those may have zero or more dynamic objects that // the checks were applied to nested within. CheckResults []*CheckResults `protobuf:"bytes,19,rep,name=check_results,json=checkResults,proto3" json:"check_results,omitempty"` + // An unordered set of proposed action invocations. This includes any + // embedded ResourceInstanceActionChanges for LinkedResources + ActionInvocations []*ActionInvocation `protobuf:"bytes,30,rep,name=action_invocations,json=actionInvocations,proto3" json:"action_invocations,omitempty"` // An unordered set of target addresses to include when applying. If no // target addresses are present, the plan applies to the whole // configuration. @@ -613,6 +617,13 @@ func (x *Plan) GetCheckResults() []*CheckResults { return nil } +func (x *Plan) GetActionInvocations() []*ActionInvocation { + if x != nil { + return x.ActionInvocations + } + return nil +} + func (x *Plan) GetTargetAddrs() []string { if x != nil { return x.TargetAddrs @@ -1569,6 +1580,138 @@ func (x *Deferred) GetReason() DeferredReason { return DeferredReason_INVALID } +// ActionInvocation contains a planned action invocation and any embedded ResourceInstanceActionChanges +type ActionInvocation struct { + state protoimpl.MessageState `protogen:"open.v1"` + // addr is a string representation of the action invocation instance address of this change + Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` + // provider is the address of the provider configuration that this change + // was planned with, and thus the configuration that must be used to + // apply it. + Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"` + LinkedResources []*ResourceInstanceActionChange `protobuf:"bytes,3,rep,name=linked_resources,json=linkedResources,proto3" json:"linked_resources,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ActionInvocation) Reset() { + *x = ActionInvocation{} + mi := &file_planfile_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ActionInvocation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ActionInvocation) ProtoMessage() {} + +func (x *ActionInvocation) ProtoReflect() protoreflect.Message { + mi := &file_planfile_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ActionInvocation.ProtoReflect.Descriptor instead. +func (*ActionInvocation) Descriptor() ([]byte, []int) { + return file_planfile_proto_rawDescGZIP(), []int{14} +} + +func (x *ActionInvocation) GetAddr() string { + if x != nil { + return x.Addr + } + return "" +} + +func (x *ActionInvocation) GetProvider() string { + if x != nil { + return x.Provider + } + return "" +} + +func (x *ActionInvocation) GetLinkedResources() []*ResourceInstanceActionChange { + if x != nil { + return x.LinkedResources + } + return nil +} + +type ResourceInstanceActionChange struct { + state protoimpl.MessageState `protogen:"open.v1"` + // addr is a string representation of the resource instance address that + // this change will apply to. + Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` + // deposed_key, if set, indicates that this change applies to a deposed + // object for the indicated instance with the given deposed key. If not + // set, the change applies to the instance's current object. + DeposedKey string `protobuf:"bytes,2,opt,name=deposed_key,json=deposedKey,proto3" json:"deposed_key,omitempty"` + // Description of the proposed change. + // May use "update", "replace", "delete" and "no-op" actions. + Change *Change `protobuf:"bytes,3,opt,name=change,proto3" json:"change,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResourceInstanceActionChange) Reset() { + *x = ResourceInstanceActionChange{} + mi := &file_planfile_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResourceInstanceActionChange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceInstanceActionChange) ProtoMessage() {} + +func (x *ResourceInstanceActionChange) ProtoReflect() protoreflect.Message { + mi := &file_planfile_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResourceInstanceActionChange.ProtoReflect.Descriptor instead. +func (*ResourceInstanceActionChange) Descriptor() ([]byte, []int) { + return file_planfile_proto_rawDescGZIP(), []int{15} +} + +func (x *ResourceInstanceActionChange) GetAddr() string { + if x != nil { + return x.Addr + } + return "" +} + +func (x *ResourceInstanceActionChange) GetDeposedKey() string { + if x != nil { + return x.DeposedKey + } + return "" +} + +func (x *ResourceInstanceActionChange) GetChange() *Change { + if x != nil { + return x.Change + } + return nil +} + type PlanResourceAttr struct { state protoimpl.MessageState `protogen:"open.v1"` Resource string `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` @@ -1579,7 +1722,7 @@ type PlanResourceAttr struct { func (x *PlanResourceAttr) Reset() { *x = PlanResourceAttr{} - mi := &file_planfile_proto_msgTypes[15] + mi := &file_planfile_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1591,7 +1734,7 @@ func (x *PlanResourceAttr) String() string { func (*PlanResourceAttr) ProtoMessage() {} func (x *PlanResourceAttr) ProtoReflect() protoreflect.Message { - mi := &file_planfile_proto_msgTypes[15] + mi := &file_planfile_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1632,7 +1775,7 @@ type CheckResults_ObjectResult struct { func (x *CheckResults_ObjectResult) Reset() { *x = CheckResults_ObjectResult{} - mi := &file_planfile_proto_msgTypes[16] + mi := &file_planfile_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1644,7 +1787,7 @@ func (x *CheckResults_ObjectResult) String() string { func (*CheckResults_ObjectResult) ProtoMessage() {} func (x *CheckResults_ObjectResult) ProtoReflect() protoreflect.Message { - mi := &file_planfile_proto_msgTypes[16] + mi := &file_planfile_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1694,7 +1837,7 @@ type Path_Step struct { func (x *Path_Step) Reset() { *x = Path_Step{} - mi := &file_planfile_proto_msgTypes[17] + mi := &file_planfile_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1706,7 +1849,7 @@ func (x *Path_Step) String() string { func (*Path_Step) ProtoMessage() {} func (x *Path_Step) ProtoReflect() protoreflect.Message { - mi := &file_planfile_proto_msgTypes[17] + mi := &file_planfile_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1771,7 +1914,7 @@ var File_planfile_proto protoreflect.FileDescriptor var file_planfile_proto_rawDesc = string([]byte{ 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x06, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0x98, 0x09, 0x0a, 0x04, 0x50, 0x6c, 0x61, + 0x12, 0x06, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0xe1, 0x09, 0x0a, 0x04, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x07, 0x75, 0x69, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x74, @@ -1810,241 +1953,263 @@ var file_planfile_proto_rawDesc = string([]byte{ 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x0c, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, - 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x64, - 0x64, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x29, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, - 0x6e, 0x64, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x0b, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, - 0x12, 0x4b, 0x0a, 0x13, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x76, - 0x61, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x66, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, - 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x46, - 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6c, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x52, - 0x0f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x1a, 0x52, 0x0a, 0x0e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 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, 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, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x61, 0x74, 0x74, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x20, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x61, - 0x74, 0x74, 0x72, 0x22, 0x69, 0x0a, 0x07, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x9a, - 0x01, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x1c, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2c, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x3c, 0x0a, 0x08, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xbc, 0x03, 0x0a, 0x06, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x06, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, + 0x12, 0x47, 0x0a, 0x12, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, + 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, + 0x72, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x07, 0x62, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x61, 0x6e, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x07, 0x62, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x61, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x13, 0x72, 0x65, 0x6c, + 0x65, 0x76, 0x61, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, + 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, + 0x74, 0x72, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x61, 0x6c, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x52, 0x0f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x52, 0x0a, 0x0e, 0x56, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 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, 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, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x16, 0x62, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, - 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x14, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, - 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x40, - 0x0a, 0x15, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x13, 0x61, 0x66, 0x74, - 0x65, 0x72, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, - 0x12, 0x2f, 0x0a, 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x49, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, - 0x67, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x0f, - 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, - 0x07, 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, 0x0e, 0x62, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0e, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x08, 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, 0x0d, 0x61, 0x66, 0x74, 0x65, 0x72, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xd3, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x5f, - 0x72, 0x75, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x70, 0x72, 0x65, 0x76, 0x52, 0x75, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, - 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, - 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x10, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x0b, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, - 0x74, 0x68, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, - 0x61, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x74, 0x66, 0x70, - 0x6c, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x86, - 0x01, 0x0a, 0x1e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x66, - 0x65, 0x72, 0x72, 0x65, 0x64, 0x52, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 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, 0x68, 0x0a, 0x0c, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, - 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x22, 0xfc, 0x03, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x12, 0x33, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, - 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, - 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x0a, - 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x1a, 0x8f, 0x01, 0x0a, 0x0c, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, - 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x29, 0x0a, 0x10, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x41, 0x53, 0x53, 0x10, 0x01, 0x12, 0x08, 0x0a, - 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x03, 0x22, 0x5c, 0x0a, 0x0a, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, - 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x01, 0x12, - 0x10, 0x0a, 0x0c, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, - 0x02, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, - 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x56, 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x04, - 0x22, 0x3c, 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6c, 0x6c, - 0x48, 0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x28, - 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, 0x6b, 0x22, 0xa5, 0x01, 0x0a, 0x04, 0x50, 0x61, 0x74, - 0x68, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x53, - 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x1a, 0x74, 0x0a, 0x04, 0x53, 0x74, - 0x65, 0x70, 0x12, 0x27, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 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, 0x48, 0x00, 0x52, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x22, 0x67, 0x0a, 0x09, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x30, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x18, 0x03, 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, - 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x3a, 0x0a, 0x08, 0x44, 0x65, 0x66, - 0x65, 0x72, 0x72, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, - 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a, 0x31, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, - 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, - 0x54, 0x52, 0x4f, 0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, - 0x48, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x2a, 0x94, 0x01, 0x0a, 0x06, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x45, 0x41, - 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, - 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, - 0x45, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x48, - 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x46, - 0x4f, 0x52, 0x47, 0x45, 0x54, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, - 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x47, 0x45, 0x54, 0x10, 0x09, 0x2a, - 0xc8, 0x03, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, - 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x54, 0x41, - 0x49, 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x50, 0x4c, 0x41, - 0x43, 0x45, 0x5f, 0x42, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, - 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, - 0x53, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, - 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, - 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x45, 0x4c, - 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x57, 0x52, 0x4f, 0x4e, - 0x47, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x1e, - 0x0a, 0x1a, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, - 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x06, 0x12, 0x1b, - 0x0a, 0x17, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, - 0x5f, 0x45, 0x41, 0x43, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, - 0x5f, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x50, - 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x59, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x53, - 0x10, 0x09, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, - 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x0a, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, - 0x55, 0x53, 0x45, 0x5f, 0x44, 0x45, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x50, - 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0b, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x41, 0x44, - 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x5f, 0x4e, - 0x45, 0x53, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x45, 0x4c, 0x45, 0x54, - 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x4f, 0x56, - 0x45, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x10, 0x0c, 0x2a, 0x9b, 0x01, 0x0a, 0x0e, 0x44, - 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, - 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, - 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, - 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, - 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, - 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x42, 0x53, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x45, 0x52, 0x45, - 0x51, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, 0x5f, - 0x50, 0x52, 0x45, 0x52, 0x45, 0x51, 0x10, 0x05, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2f, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4d, 0x0a, + 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x12, 0x1a, + 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x04, 0x61, 0x74, + 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, + 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x61, 0x74, 0x74, 0x72, 0x22, 0x69, 0x0a, 0x07, + 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 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, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, + 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x22, 0x3c, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x22, 0xbc, 0x03, 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x0a, + 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, + 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 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, 0x06, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x16, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x65, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, + 0x68, 0x52, 0x14, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x40, 0x0a, 0x15, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x13, 0x61, 0x66, 0x74, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x73, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x2f, 0x0a, 0x09, 0x69, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x09, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x0f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x07, 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, 0x0e, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0e, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x08, 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, 0x0d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x22, 0xd3, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x61, 0x64, 0x64, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, + 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x52, 0x75, 0x6e, + 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x6f, 0x73, + 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, + 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0f, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0d, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x86, 0x01, 0x0a, 0x1e, 0x44, 0x65, 0x66, 0x65, + 0x72, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x64, 0x65, + 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x52, 0x08, + 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 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, 0x68, 0x0a, 0x0c, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x22, 0xfc, 0x03, 0x0a, 0x0c, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x33, 0x0a, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x41, 0x64, 0x64, + 0x72, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x1a, 0x8f, 0x01, 0x0a, 0x0c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x66, 0x61, + 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, + 0x50, 0x41, 0x53, 0x53, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x02, + 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x22, 0x5c, 0x0a, 0x0a, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4f, 0x55, 0x54, 0x50, + 0x55, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x48, + 0x45, 0x43, 0x4b, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x56, + 0x41, 0x52, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x04, 0x22, 0x3c, 0x0a, 0x10, 0x46, 0x75, 0x6e, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6c, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x28, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, + 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, + 0x6b, 0x22, 0xa5, 0x01, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, + 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, + 0x65, 0x70, 0x73, 0x1a, 0x74, 0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12, 0x27, 0x0a, 0x0e, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x6b, 0x65, 0x79, 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, 0x48, + 0x00, 0x52, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, + 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x67, 0x0a, 0x09, 0x49, 0x6d, 0x70, + 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x12, 0x30, 0x0a, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 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, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x22, 0x3a, 0x0a, 0x08, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x12, 0x2e, + 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x93, + 0x01, 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x10, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x5f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x0f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x22, 0x7b, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6f, + 0x73, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, + 0x65, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x2a, 0x31, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, + 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, + 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, 0x48, 0x5f, 0x4f, 0x4e, + 0x4c, 0x59, 0x10, 0x02, 0x2a, 0x94, 0x01, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12, + 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x4c, 0x45, 0x54, + 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x06, 0x12, + 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x44, + 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x4f, 0x52, 0x47, 0x45, + 0x54, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x48, + 0x45, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x47, 0x45, 0x54, 0x10, 0x09, 0x2a, 0xc8, 0x03, 0x0a, 0x1c, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, + 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, + 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x54, 0x41, 0x49, 0x4e, 0x54, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, + 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x52, + 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, + 0x41, 0x4e, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x25, + 0x0a, 0x21, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, + 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, + 0x46, 0x49, 0x47, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, + 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x57, 0x52, 0x4f, 0x4e, 0x47, 0x5f, 0x52, 0x45, + 0x50, 0x45, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x45, + 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x55, + 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x06, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, + 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x45, 0x41, 0x43, + 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x45, 0x4c, 0x45, 0x54, + 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x4f, 0x44, + 0x55, 0x4c, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, + 0x5f, 0x42, 0x59, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x53, 0x10, 0x09, 0x12, 0x1f, + 0x0a, 0x1b, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, + 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x0a, 0x12, + 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, + 0x44, 0x45, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, + 0x4e, 0x47, 0x10, 0x0b, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, + 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x5f, 0x4e, 0x45, 0x53, 0x54, 0x45, + 0x44, 0x10, 0x0d, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, + 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x54, 0x41, + 0x52, 0x47, 0x45, 0x54, 0x10, 0x0c, 0x2a, 0x9b, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x66, 0x65, 0x72, + 0x72, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, + 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, + 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, + 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x02, 0x12, + 0x1b, 0x0a, 0x17, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, + 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, + 0x41, 0x42, 0x53, 0x45, 0x4e, 0x54, 0x5f, 0x50, 0x52, 0x45, 0x52, 0x45, 0x51, 0x10, 0x04, 0x12, + 0x13, 0x0a, 0x0f, 0x44, 0x45, 0x46, 0x45, 0x52, 0x52, 0x45, 0x44, 0x5f, 0x50, 0x52, 0x45, 0x52, + 0x45, 0x51, 0x10, 0x05, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x74, 0x65, 0x72, + 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -2060,7 +2225,7 @@ func file_planfile_proto_rawDescGZIP() []byte { } var file_planfile_proto_enumTypes = make([]protoimpl.EnumInfo, 6) -var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_planfile_proto_goTypes = []any{ (Mode)(0), // 0: tfplan.Mode (Action)(0), // 1: tfplan.Action @@ -2082,54 +2247,59 @@ var file_planfile_proto_goTypes = []any{ (*Path)(nil), // 17: tfplan.Path (*Importing)(nil), // 18: tfplan.Importing (*Deferred)(nil), // 19: tfplan.Deferred - nil, // 20: tfplan.Plan.VariablesEntry - (*PlanResourceAttr)(nil), // 21: tfplan.Plan.resource_attr - (*CheckResults_ObjectResult)(nil), // 22: tfplan.CheckResults.ObjectResult - (*Path_Step)(nil), // 23: tfplan.Path.Step + (*ActionInvocation)(nil), // 20: tfplan.ActionInvocation + (*ResourceInstanceActionChange)(nil), // 21: tfplan.ResourceInstanceActionChange + nil, // 22: tfplan.Plan.VariablesEntry + (*PlanResourceAttr)(nil), // 23: tfplan.Plan.resource_attr + (*CheckResults_ObjectResult)(nil), // 24: tfplan.CheckResults.ObjectResult + (*Path_Step)(nil), // 25: tfplan.Path.Step } var file_planfile_proto_depIdxs = []int32{ 0, // 0: tfplan.Plan.ui_mode:type_name -> tfplan.Mode - 20, // 1: tfplan.Plan.variables:type_name -> tfplan.Plan.VariablesEntry + 22, // 1: tfplan.Plan.variables:type_name -> tfplan.Plan.VariablesEntry 11, // 2: tfplan.Plan.resource_changes:type_name -> tfplan.ResourceInstanceChange 11, // 3: tfplan.Plan.resource_drift:type_name -> tfplan.ResourceInstanceChange 12, // 4: tfplan.Plan.deferred_changes:type_name -> tfplan.DeferredResourceInstanceChange 13, // 5: tfplan.Plan.output_changes:type_name -> tfplan.OutputChange 14, // 6: tfplan.Plan.check_results:type_name -> tfplan.CheckResults - 7, // 7: tfplan.Plan.backend:type_name -> tfplan.Backend - 8, // 8: tfplan.Plan.state_store:type_name -> tfplan.StateStore - 21, // 9: tfplan.Plan.relevant_attributes:type_name -> tfplan.Plan.resource_attr - 15, // 10: tfplan.Plan.function_results:type_name -> tfplan.FunctionCallHash - 16, // 11: tfplan.Backend.config:type_name -> tfplan.DynamicValue - 16, // 12: tfplan.StateStore.config:type_name -> tfplan.DynamicValue - 9, // 13: tfplan.StateStore.provider:type_name -> tfplan.Provider - 1, // 14: tfplan.Change.action:type_name -> tfplan.Action - 16, // 15: tfplan.Change.values:type_name -> tfplan.DynamicValue - 17, // 16: tfplan.Change.before_sensitive_paths:type_name -> tfplan.Path - 17, // 17: tfplan.Change.after_sensitive_paths:type_name -> tfplan.Path - 18, // 18: tfplan.Change.importing:type_name -> tfplan.Importing - 16, // 19: tfplan.Change.before_identity:type_name -> tfplan.DynamicValue - 16, // 20: tfplan.Change.after_identity:type_name -> tfplan.DynamicValue - 10, // 21: tfplan.ResourceInstanceChange.change:type_name -> tfplan.Change - 17, // 22: tfplan.ResourceInstanceChange.required_replace:type_name -> tfplan.Path - 2, // 23: tfplan.ResourceInstanceChange.action_reason:type_name -> tfplan.ResourceInstanceActionReason - 19, // 24: tfplan.DeferredResourceInstanceChange.deferred:type_name -> tfplan.Deferred - 11, // 25: tfplan.DeferredResourceInstanceChange.change:type_name -> tfplan.ResourceInstanceChange - 10, // 26: tfplan.OutputChange.change:type_name -> tfplan.Change - 5, // 27: tfplan.CheckResults.kind:type_name -> tfplan.CheckResults.ObjectKind - 4, // 28: tfplan.CheckResults.status:type_name -> tfplan.CheckResults.Status - 22, // 29: tfplan.CheckResults.objects:type_name -> tfplan.CheckResults.ObjectResult - 23, // 30: tfplan.Path.steps:type_name -> tfplan.Path.Step - 16, // 31: tfplan.Importing.identity:type_name -> tfplan.DynamicValue - 3, // 32: tfplan.Deferred.reason:type_name -> tfplan.DeferredReason - 16, // 33: tfplan.Plan.VariablesEntry.value:type_name -> tfplan.DynamicValue - 17, // 34: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path - 4, // 35: tfplan.CheckResults.ObjectResult.status:type_name -> tfplan.CheckResults.Status - 16, // 36: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue - 37, // [37:37] is the sub-list for method output_type - 37, // [37:37] is the sub-list for method input_type - 37, // [37:37] is the sub-list for extension type_name - 37, // [37:37] is the sub-list for extension extendee - 0, // [0:37] is the sub-list for field type_name + 20, // 7: tfplan.Plan.action_invocations:type_name -> tfplan.ActionInvocation + 7, // 8: tfplan.Plan.backend:type_name -> tfplan.Backend + 8, // 9: tfplan.Plan.state_store:type_name -> tfplan.StateStore + 23, // 10: tfplan.Plan.relevant_attributes:type_name -> tfplan.Plan.resource_attr + 15, // 11: tfplan.Plan.function_results:type_name -> tfplan.FunctionCallHash + 16, // 12: tfplan.Backend.config:type_name -> tfplan.DynamicValue + 16, // 13: tfplan.StateStore.config:type_name -> tfplan.DynamicValue + 9, // 14: tfplan.StateStore.provider:type_name -> tfplan.Provider + 1, // 15: tfplan.Change.action:type_name -> tfplan.Action + 16, // 16: tfplan.Change.values:type_name -> tfplan.DynamicValue + 17, // 17: tfplan.Change.before_sensitive_paths:type_name -> tfplan.Path + 17, // 18: tfplan.Change.after_sensitive_paths:type_name -> tfplan.Path + 18, // 19: tfplan.Change.importing:type_name -> tfplan.Importing + 16, // 20: tfplan.Change.before_identity:type_name -> tfplan.DynamicValue + 16, // 21: tfplan.Change.after_identity:type_name -> tfplan.DynamicValue + 10, // 22: tfplan.ResourceInstanceChange.change:type_name -> tfplan.Change + 17, // 23: tfplan.ResourceInstanceChange.required_replace:type_name -> tfplan.Path + 2, // 24: tfplan.ResourceInstanceChange.action_reason:type_name -> tfplan.ResourceInstanceActionReason + 19, // 25: tfplan.DeferredResourceInstanceChange.deferred:type_name -> tfplan.Deferred + 11, // 26: tfplan.DeferredResourceInstanceChange.change:type_name -> tfplan.ResourceInstanceChange + 10, // 27: tfplan.OutputChange.change:type_name -> tfplan.Change + 5, // 28: tfplan.CheckResults.kind:type_name -> tfplan.CheckResults.ObjectKind + 4, // 29: tfplan.CheckResults.status:type_name -> tfplan.CheckResults.Status + 24, // 30: tfplan.CheckResults.objects:type_name -> tfplan.CheckResults.ObjectResult + 25, // 31: tfplan.Path.steps:type_name -> tfplan.Path.Step + 16, // 32: tfplan.Importing.identity:type_name -> tfplan.DynamicValue + 3, // 33: tfplan.Deferred.reason:type_name -> tfplan.DeferredReason + 21, // 34: tfplan.ActionInvocation.linked_resources:type_name -> tfplan.ResourceInstanceActionChange + 10, // 35: tfplan.ResourceInstanceActionChange.change:type_name -> tfplan.Change + 16, // 36: tfplan.Plan.VariablesEntry.value:type_name -> tfplan.DynamicValue + 17, // 37: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path + 4, // 38: tfplan.CheckResults.ObjectResult.status:type_name -> tfplan.CheckResults.Status + 16, // 39: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue + 40, // [40:40] is the sub-list for method output_type + 40, // [40:40] is the sub-list for method input_type + 40, // [40:40] is the sub-list for extension type_name + 40, // [40:40] is the sub-list for extension extendee + 0, // [0:40] is the sub-list for field type_name } func init() { file_planfile_proto_init() } @@ -2137,7 +2307,7 @@ func file_planfile_proto_init() { if File_planfile_proto != nil { return } - file_planfile_proto_msgTypes[17].OneofWrappers = []any{ + file_planfile_proto_msgTypes[19].OneofWrappers = []any{ (*Path_Step_AttributeName)(nil), (*Path_Step_ElementKey)(nil), } @@ -2147,7 +2317,7 @@ func file_planfile_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_planfile_proto_rawDesc), len(file_planfile_proto_rawDesc)), NumEnums: 6, - NumMessages: 18, + NumMessages: 20, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/plans/planproto/planfile.proto b/internal/plans/planproto/planfile.proto index 4caf72f592..f9919841ef 100644 --- a/internal/plans/planproto/planfile.proto +++ b/internal/plans/planproto/planfile.proto @@ -5,7 +5,7 @@ syntax = "proto3"; package tfplan; // For Terraform's own parsing, the proto stub types go into an internal Go -// package. The public API is in github.com/hashicorp/terraform/plans/planfile . +// package. The public API is in github.com/hashicorp/terraform/internal/plans/planfile . option go_package = "github.com/hashicorp/terraform/internal/plans/planproto"; // Plan is the root message type for the tfplan file @@ -93,6 +93,10 @@ message Plan { // the checks were applied to nested within. repeated CheckResults check_results = 19; + // An unordered set of proposed action invocations. This includes any + // embedded ResourceInstanceActionChanges for LinkedResources + repeated ActionInvocation action_invocations = 30; + // An unordered set of target addresses to include when applying. If no // target addresses are present, the plan applies to the whole // configuration. @@ -249,7 +253,7 @@ message ResourceInstanceChange { string prev_run_addr = 14; // NOTE: Earlier versions of this format had fields 1 through 6 describing - // various indivdual parts of "addr". We're now using our standard compact + // various individual parts of "addr". We're now using our standard compact // string representation to capture the same information. We don't support // preserving plan files from one Terraform version to the next, so we // no longer declare nor accept those fields. @@ -421,3 +425,31 @@ enum DeferredReason { message Deferred { DeferredReason reason = 1; } + +// ActionInvocationInstance contains a planned action invocation and any embedded ResourceInstanceActionChanges +message ActionInvocationInstance { + // addr is a string representation of the action invocation instance address of this change + string addr = 1; + + // provider is the address of the provider configuration that this change + // was planned with, and thus the configuration that must be used to + // apply it. + string provider = 2; + + repeated ResourceInstanceActionChange linked_resources = 3; +} + +message ResourceInstanceActionChange { + // addr is a string representation of the resource instance address that + // this change will apply to. + string addr = 1; + + // deposed_key, if set, indicates that this change applies to a deposed + // object for the indicated instance with the given deposed key. If not + // set, the change applies to the instance's current object. + string deposed_key = 2; + + // Description of the proposed change. + // May use "update", "replace", "delete" and "no-op" actions. + Change change = 3; +} diff --git a/internal/plugin/convert/schema.go b/internal/plugin/convert/schema.go index a27eacbd56..d04bd0557e 100644 --- a/internal/plugin/convert/schema.go +++ b/internal/plugin/convert/schema.go @@ -173,7 +173,7 @@ func ProtoToActionSchema(s *proto.ActionSchema) providers.ActionSchema { schema.Unlinked = &providers.UnlinkedAction{} case *proto.ActionSchema_Lifecycle_: schema.Lifecycle = &providers.LifecycleAction{ - Exectues: ProtoToExecutionOrder(t.Lifecycle.Executes), + Executes: ProtoToExecutionOrder(t.Lifecycle.Executes), LinkedResource: ProtoToLinkedResource(t.Lifecycle.LinkedResource), } case *proto.ActionSchema_Linked_: diff --git a/internal/plugin6/convert/schema.go b/internal/plugin6/convert/schema.go index a5424da631..175aa9c47c 100644 --- a/internal/plugin6/convert/schema.go +++ b/internal/plugin6/convert/schema.go @@ -8,10 +8,11 @@ import ( "reflect" "sort" + "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/providers" proto "github.com/hashicorp/terraform/internal/tfplugin6" - "github.com/zclconf/go-cty/cty" ) // ConfigSchemaToProto takes a *configschema.Block and converts it to a @@ -121,7 +122,7 @@ func ProtoToActionSchema(s *proto.ActionSchema) providers.ActionSchema { schema.Unlinked = &providers.UnlinkedAction{} case *proto.ActionSchema_Lifecycle_: schema.Lifecycle = &providers.LifecycleAction{ - Exectues: ProtoToExecutionOrder(t.Lifecycle.Executes), + Executes: ProtoToExecutionOrder(t.Lifecycle.Executes), LinkedResource: ProtoToLinkedResource(t.Lifecycle.LinkedResource), } case *proto.ActionSchema_Linked_: @@ -129,7 +130,7 @@ func ProtoToActionSchema(s *proto.ActionSchema) providers.ActionSchema { LinkedResources: ProtoToLinkedResources(t.Linked.LinkedResources), } default: - panic("Unknown Action Type, expected schema to contain either Unlinked, Liefecycle, or Linked") + panic("Unknown Action Type. Expected schema to contain either Unlinked, Lifecycle, or Linked") } return schema } diff --git a/internal/providers/provider.go b/internal/providers/provider.go index c45a74bd5e..786a7a09fe 100644 --- a/internal/providers/provider.go +++ b/internal/providers/provider.go @@ -210,13 +210,16 @@ type LinkedResourceSchema struct { } type UnlinkedAction struct{} + type LifecycleAction struct { - Exectues ExecutionOrder + Executes ExecutionOrder LinkedResource LinkedResourceSchema } + type LinkedAction struct { LinkedResources []LinkedResourceSchema } + type ActionSchema struct { ConfigSchema *configschema.Block @@ -239,6 +242,11 @@ func (a ActionSchema) LinkedResources() []LinkedResourceSchema { panic("ActionSchema must have one of Unlinked, Lifecycle, or Linked set") } +// IsNil() returns true is there is no action schema at all. +func (a ActionSchema) IsNil() bool { + return a.ConfigSchema == nil && a.Unlinked == nil && a.Lifecycle == nil && a.Linked == nil +} + // Schema pairs a provider or resource schema with that schema's version. // This is used to be able to upgrade the schema in UpgradeResourceState. //