diff --git a/docs/plugin-protocol/tfplugin6.5.proto b/docs/plugin-protocol/tfplugin6.5.proto new file mode 100644 index 000000000000..b12f0d63ff38 --- /dev/null +++ b/docs/plugin-protocol/tfplugin6.5.proto @@ -0,0 +1,534 @@ +// Terraform Plugin RPC protocol version 6.5 +// +// This file defines version 6.5 of the RPC protocol. To implement a plugin +// against this protocol, copy this definition into your own codebase and +// use protoc to generate stubs for your target language. +// +// This file will not be updated. Any minor versions of protocol 6 to follow +// should copy this file and modify the copy while maintaing backwards +// compatibility. Breaking changes, if any are required, will come +// in a subsequent major version with its own separate proto definition. +// +// Note that only the proto files included in a release tag of Terraform are +// official protocol releases. Proto files taken from other commits may include +// incomplete changes or features that did not make it into a final release. +// In all reasonable cases, plugin developers should take the proto file from +// the tag of the most recent release of Terraform, and not from the main +// branch or any other development branch. +// +syntax = "proto3"; +option go_package = "github.com/hashicorp/terraform/internal/tfplugin6"; + +package tfplugin6; + +// DynamicValue is an opaque encoding of terraform data, with the field name +// indicating the encoding scheme used. +message DynamicValue { + bytes msgpack = 1; + bytes json = 2; +} + +message Diagnostic { + enum Severity { + INVALID = 0; + ERROR = 1; + WARNING = 2; + } + Severity severity = 1; + string summary = 2; + string detail = 3; + AttributePath attribute = 4; +} + +message AttributePath { + message Step { + oneof selector { + // Set "attribute_name" to represent looking up an attribute + // in the current object value. + string attribute_name = 1; + // Set "element_key_*" to represent looking up an element in + // an indexable collection type. + string element_key_string = 2; + int64 element_key_int = 3; + } + } + repeated Step steps = 1; +} + +message StopProvider { + message Request { + } + message Response { + string Error = 1; + } +} + +// RawState holds the stored state for a resource to be upgraded by the +// provider. It can be in one of two formats, the current json encoded format +// in bytes, or the legacy flatmap format as a map of strings. +message RawState { + bytes json = 1; + map flatmap = 2; +} + +enum StringKind { + PLAIN = 0; + MARKDOWN = 1; +} + +// Schema is the configuration schema for a Resource or Provider. +message Schema { + message Block { + int64 version = 1; + repeated Attribute attributes = 2; + repeated NestedBlock block_types = 3; + string description = 4; + StringKind description_kind = 5; + bool deprecated = 6; + } + + message Attribute { + string name = 1; + bytes type = 2; + Object nested_type = 10; + string description = 3; + bool required = 4; + bool optional = 5; + bool computed = 6; + bool sensitive = 7; + StringKind description_kind = 8; + bool deprecated = 9; + } + + message NestedBlock { + enum NestingMode { + INVALID = 0; + SINGLE = 1; + LIST = 2; + SET = 3; + MAP = 4; + GROUP = 5; + } + + string type_name = 1; + Block block = 2; + NestingMode nesting = 3; + int64 min_items = 4; + int64 max_items = 5; + } + + message Object { + enum NestingMode { + INVALID = 0; + SINGLE = 1; + LIST = 2; + SET = 3; + MAP = 4; + } + + repeated Attribute attributes = 1; + NestingMode nesting = 3; + + // MinItems and MaxItems were never used in the protocol, and have no + // effect on validation. + int64 min_items = 4 [deprecated = true]; + int64 max_items = 5 [deprecated = true]; + } + + // The version of the schema. + // Schemas are versioned, so that providers can upgrade a saved resource + // state when the schema is changed. + int64 version = 1; + + // Block is the top level configuration block for this schema. + Block block = 2; +} + +// ServerCapabilities allows providers to communicate extra information +// regarding supported protocol features. This is used to indicate +// availability of certain forward-compatible changes which may be optional +// in a major protocol version, but cannot be tested for directly. +message ServerCapabilities { + // The plan_destroy capability signals that a provider expects a call + // to PlanResourceChange when a resource is going to be destroyed. + bool plan_destroy = 1; + + // The get_provider_schema_optional capability indicates that this + // provider does not require calling GetProviderSchema to operate + // normally, and the caller can used a cached copy of the provider's + // schema. + bool get_provider_schema_optional = 2; +} + +// DeferredAction represents a reason why a particular action cannot be taken +// until Terraform can provide concrete values instead of unknown value +// placeholders. +message DeferredAction { + oneof reason { + // other_reason is a fallback reason to use if none of the other + // specific reasons seem appropriate. Terraform will show a generic + // message in the UI in this case, acknowledging that the operation + // was deferred but with no specific reason why. Terraform Core will + // also treat any unrecognized reason type defined in later versions + // of this protocol as if they were other_reason. + OtherReason other_reason = 1; + + // provider_config_unknown represents that the action was deferred + // because a necessary part of the corresponding provider configuration + // is not yet known enough to proceed. + ConfigUnknown provider_config_unknown = 2; + + // resource_config_unknown represents that the action was deferred + // because a necessary part of the resource configuration + // is not yet known enough to proceed. + ConfigUnknown resource_config_unknown = 3; + } + + message OtherReason {} + message ConfigUnknown { + // The path to the attribute whose unknown value caused the deferral. + // Provide as precise a path as possible, but it's okay to describe + // a shorter path if e.g. the problem is inside a set element and + // therefore not fully addressable as an AttributePath. + AttributePath attribute = 1; + } +} + +service Provider { + //////// Information about what a provider supports/expects + + // GetMetadata returns upfront information about server capabilities and + // supported resource types without requiring the server to instantiate all + // schema information, which may be memory intensive. This RPC is optional, + // where clients may receive an unimplemented RPC error. Clients should + // ignore the error and call the GetProviderSchema RPC as a fallback. + rpc GetMetadata(GetMetadata.Request) returns (GetMetadata.Response); + + // GetSchema returns schema information for the provider, data resources, + // and managed resources. + rpc GetProviderSchema(GetProviderSchema.Request) returns (GetProviderSchema.Response); + rpc ValidateProviderConfig(ValidateProviderConfig.Request) returns (ValidateProviderConfig.Response); + rpc ValidateResourceConfig(ValidateResourceConfig.Request) returns (ValidateResourceConfig.Response); + rpc ValidateDataResourceConfig(ValidateDataResourceConfig.Request) returns (ValidateDataResourceConfig.Response); + rpc UpgradeResourceState(UpgradeResourceState.Request) returns (UpgradeResourceState.Response); + + //////// One-time initialization, called before other functions below + rpc ConfigureProvider(ConfigureProvider.Request) returns (ConfigureProvider.Response); + + //////// Managed Resource Lifecycle + rpc ReadResource(ReadResource.Request) returns (ReadResource.Response); + rpc PlanResourceChange(PlanResourceChange.Request) returns (PlanResourceChange.Response); + rpc ApplyResourceChange(ApplyResourceChange.Request) returns (ApplyResourceChange.Response); + rpc ImportResourceState(ImportResourceState.Request) returns (ImportResourceState.Response); + + rpc ReadDataSource(ReadDataSource.Request) returns (ReadDataSource.Response); + + //////// Graceful Shutdown + rpc StopProvider(StopProvider.Request) returns (StopProvider.Response); +} + +message GetMetadata { + message Request { + } + + message Response { + ServerCapabilities server_capabilities = 1; + repeated Diagnostic diagnostics = 2; + repeated DataSourceMetadata data_sources = 3; + repeated ResourceMetadata resources = 4; + } + + message DataSourceMetadata { + string type_name = 1; + } + + message ResourceMetadata { + string type_name = 1; + } +} + +message GetProviderSchema { + message Request { + } + message Response { + Schema provider = 1; + map resource_schemas = 2; + map data_source_schemas = 3; + repeated Diagnostic diagnostics = 4; + Schema provider_meta = 5; + ServerCapabilities server_capabilities = 6; + } +} + +message ValidateProviderConfig { + message Request { + DynamicValue config = 1; + } + message Response { + repeated Diagnostic diagnostics = 2; + } +} + +message UpgradeResourceState { + // Request is the message that is sent to the provider during the + // UpgradeResourceState RPC. + // + // This message intentionally does not include configuration data as any + // configuration-based or configuration-conditional changes should occur + // during the PlanResourceChange RPC. Additionally, the configuration is + // not guaranteed to exist (in the case of resource destruction), be wholly + // known, nor match the given prior state, which could lead to unexpected + // provider behaviors for practitioners. + message Request { + string type_name = 1; + + // version is the schema_version number recorded in the state file + int64 version = 2; + + // raw_state is the raw states as stored for the resource. Core does + // not have access to the schema of prior_version, so it's the + // provider's responsibility to interpret this value using the + // appropriate older schema. The raw_state will be the json encoded + // state, or a legacy flat-mapped format. + RawState raw_state = 3; + + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to upgrade the state date to the + // latest schema version. + bool defer_allowed = 4; + } + message Response { + // new_state is a msgpack-encoded data structure that, when interpreted with + // the _current_ schema for this resource type, is functionally equivalent to + // that which was given in prior_state_raw. + DynamicValue upgraded_state = 1; + + // diagnostics describes any errors encountered during migration that could not + // be safely resolved, and warnings about any possibly-risky assumptions made + // in the upgrade process. + repeated Diagnostic diagnostics = 2; + + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will treat the object as completely unknown + // while planning downstream actions. Providers should avoid deferring + // an upgrade if at all possible, by implementing upgrade logic entirely + // within the provider and not accessing any external system. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why upgrading is + // impossible. + repeated DeferredAction deferred = 3; + } +} + +message ValidateResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message ValidateDataResourceConfig { + message Request { + string type_name = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message ConfigureProvider { + message Request { + string terraform_version = 1; + DynamicValue config = 2; + } + message Response { + repeated Diagnostic diagnostics = 1; + } +} + +message ReadResource { + // Request is the message that is sent to the provider during the + // ReadResource RPC. + // + // This message intentionally does not include configuration data as any + // configuration-based or configuration-conditional changes should occur + // during the PlanResourceChange RPC. Additionally, the configuration is + // not guaranteed to be wholly known nor match the given prior state, which + // could lead to unexpected provider behaviors for practitioners. + message Request { + string type_name = 1; + DynamicValue current_state = 2; + bytes private = 3; + DynamicValue provider_meta = 4; + + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to retrieve the current state + // of the object. + bool defer_allowed = 5; + } + message Response { + DynamicValue new_state = 1; + repeated Diagnostic diagnostics = 2; + bytes private = 3; + + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still use the partial "new_state" value + // to plan downstream actions but will then defer them until a + // future run where a similar ReadResource request can return + // a complete result. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why reading is + // impossible. + repeated DeferredAction deferred = 4; + } +} + +message PlanResourceChange { + message Request { + string type_name = 1; + DynamicValue prior_state = 2; + DynamicValue proposed_new_state = 3; + DynamicValue config = 4; + bytes prior_private = 5; + DynamicValue provider_meta = 6; + + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to fully plan the change. + bool defer_allowed = 7; + } + + message Response { + DynamicValue planned_state = 1; + repeated AttributePath requires_replace = 2; + bytes planned_private = 3; + repeated Diagnostic diagnostics = 4; + + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still present the planned action to the + // user for review as a deferred action but will not actually apply + // the change without first asking for a new plan with more information. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why planning is + // impossible. + repeated DeferredAction deferred = 6; + + // This may be set only by the helper/schema "SDK" in the main Terraform + // repository, to request that Terraform Core >=0.12 permit additional + // inconsistencies that can result from the legacy SDK type system + // and its imprecise mapping to the >=0.12 type system. + // The change in behavior implied by this flag makes sense only for the + // specific details of the legacy SDK type system, and are not a general + // mechanism to avoid proper type handling in providers. + // + // ==== DO NOT USE THIS ==== + // ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ==== + // ==== DO NOT USE THIS ==== + bool legacy_type_system = 5; + } +} + +message ApplyResourceChange { + message Request { + string type_name = 1; + DynamicValue prior_state = 2; + DynamicValue planned_state = 3; + DynamicValue config = 4; + bytes planned_private = 5; + DynamicValue provider_meta = 6; + } + message Response { + DynamicValue new_state = 1; + bytes private = 2; + repeated Diagnostic diagnostics = 3; + + // This may be set only by the helper/schema "SDK" in the main Terraform + // repository, to request that Terraform Core >=0.12 permit additional + // inconsistencies that can result from the legacy SDK type system + // and its imprecise mapping to the >=0.12 type system. + // The change in behavior implied by this flag makes sense only for the + // specific details of the legacy SDK type system, and are not a general + // mechanism to avoid proper type handling in providers. + // + // ==== DO NOT USE THIS ==== + // ==== THIS MUST BE LEFT UNSET IN ALL OTHER SDKS ==== + // ==== DO NOT USE THIS ==== + bool legacy_type_system = 4; + } +} + +message ImportResourceState { + message Request { + string type_name = 1; + string id = 2; + + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to import the requested object. + bool defer_allowed = 4; + } + + message ImportedResource { + string type_name = 1; + DynamicValue state = 2; + bytes private = 3; + } + + message Response { + repeated ImportedResource imported_resources = 1; + repeated Diagnostic diagnostics = 2; + + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will treat this object as entirely unknown + // during downstream planning and defer the import until a later + // run when there's hopefully more information available. + // + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why importing is + // impossible. + repeated DeferredAction deferred = 3; + } +} + +message ReadDataSource { + message Request { + string type_name = 1; + DynamicValue config = 2; + DynamicValue provider_meta = 3; + + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to fetch the requested remote object. + bool defer_allowed = 4; + } + message Response { + DynamicValue state = 1; + repeated Diagnostic diagnostics = 2; + + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still use the partial "state" value + // to plan downstream actions but will then defer them until a + // future run where a similar ReadDataSource request can return + // a complete result. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why reading is + // impossible. + repeated DeferredAction deferred = 3; + } +} diff --git a/internal/addrs/deferrable.go b/internal/addrs/deferrable.go new file mode 100644 index 000000000000..680fd2fc69a3 --- /dev/null +++ b/internal/addrs/deferrable.go @@ -0,0 +1,64 @@ +package addrs + +import ( + "strings" +) + +// Deferable represents addresses of types of objects that can have actions +// that might be deferred for execution in a later run. +// +// When an action is defered we still need to describe an approximation of +// the effects of that action so that users can get early feedback about +// whether applying the non-deferred changes will move them closer to their +// desired state. Deferable addresses are how we communicate which object +// each deferred action relates to. +type Deferrable interface { + deferrableSigil() + UniqueKeyer + + // DeferrableString is like String but returns an address form specifically + // tailored for a UI that is describing deferred changes, which clearly + // distinguishes between the different possible deferable address types. + DeferrableString() string +} + +// ConfigResource is deferable because sometimes we must defer even the +// expansion of a resource due to either its own repetition argument or that +// of one of its containing modules being unknown. +func (ConfigResource) deferrableSigil() {} + +func (r ConfigResource) DeferrableString() string { + // Because deferred unexpanded resources will be shown in the same context + // as expanded resource instances, we'll use a special format here to + // make it explicit that we're talking about all instances of a particular + // resource or module, rather than the _unkeyed instance_ of each. + // This follows a similar convention to how we display "move endpoints" + // in the UI, like [MoveEndpointInModule.String]: + // module.foo[*].aws_instance.bar[*], to differentiate from + // module.foo.aws_instance.bar the single instance. + var buf strings.Builder + for _, name := range r.Module { + buf.WriteString("module.") + buf.WriteString(name) + buf.WriteString("[*].") + } + buf.WriteString(r.Resource.String()) + buf.WriteString("[*]") + return buf.String() +} + +var _ Deferrable = ConfigResource{} + +// AbsResourceInstance is deferable for situations where we have already +// succeeded in expanding a resource but one of its instances must be +// defered either for provider-specific reasons or because it is downstream +// of some other deferred action. +func (AbsResourceInstance) deferrableSigil() {} + +var _ Deferrable = AbsResourceInstance{} + +func (r AbsResourceInstance) DeferrableString() string { + // Our "deferrable" string format for AbsResourceInstance is just its + // normal string format, because this is the main case. + return r.String() +} diff --git a/internal/addrs/deferrable_test.go b/internal/addrs/deferrable_test.go new file mode 100644 index 000000000000..679ddc85dcca --- /dev/null +++ b/internal/addrs/deferrable_test.go @@ -0,0 +1,88 @@ +package addrs + +import ( + "fmt" + "testing" +) + +func TestDeferrableString(t *testing.T) { + tests := []struct { + Addr Deferrable + Want string + }{ + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(NoKey).Absolute(RootModuleInstance), + `foo.bar`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(IntKey(2)).Absolute(RootModuleInstance), + `foo.bar[2]`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(StringKey("blub")).Absolute(RootModuleInstance), + `foo.bar["blub"]`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(NoKey).Absolute(RootModuleInstance.Child("boop", NoKey)), + `module.boop.foo.bar`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(NoKey).Absolute(RootModuleInstance.Child("boop", IntKey(6))), + `module.boop[6].foo.bar`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.Instance(NoKey).Absolute(RootModuleInstance.Child("boop", StringKey("a"))), + `module.boop["a"].foo.bar`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.InModule(RootModule), + `foo.bar[*]`, + }, + { + Resource{ + Mode: ManagedResourceMode, + Type: "foo", + Name: "bar", + }.InModule(RootModule.Child("boop")), + `module.boop[*].foo.bar[*]`, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("%#v", test.Addr), func(t *testing.T) { + got := test.Addr.DeferrableString() + + if got != test.Want { + t.Errorf("wrong result\ngot: %s\nwant: %s", got, test.Want) + } + }) + } +} diff --git a/internal/addrs/instance_key.go b/internal/addrs/instance_key.go index bb2ac0149b49..22667eb2313c 100644 --- a/internal/addrs/instance_key.go +++ b/internal/addrs/instance_key.go @@ -134,6 +134,8 @@ func instanceKeyType(k InstanceKey) InstanceKeyType { // of those types. type InstanceKeyType rune +//go:generate go run golang.org/x/tools/cmd/stringer -type=InstanceKeyType instance_key.go + const ( NoKeyType InstanceKeyType = 0 IntKeyType InstanceKeyType = 'I' diff --git a/internal/addrs/instancekeytype_string.go b/internal/addrs/instancekeytype_string.go new file mode 100644 index 000000000000..b67fef078be1 --- /dev/null +++ b/internal/addrs/instancekeytype_string.go @@ -0,0 +1,37 @@ +// Code generated by "stringer -type=InstanceKeyType instance_key.go"; DO NOT EDIT. + +package addrs + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NoKeyType-0] + _ = x[IntKeyType-73] + _ = x[StringKeyType-83] + _ = x[UnknownKeyType-63] +} + +const ( + _InstanceKeyType_name_0 = "NoKeyType" + _InstanceKeyType_name_1 = "UnknownKeyType" + _InstanceKeyType_name_2 = "IntKeyType" + _InstanceKeyType_name_3 = "StringKeyType" +) + +func (i InstanceKeyType) String() string { + switch { + case i == 0: + return _InstanceKeyType_name_0 + case i == 63: + return _InstanceKeyType_name_1 + case i == 73: + return _InstanceKeyType_name_2 + case i == 83: + return _InstanceKeyType_name_3 + default: + return "InstanceKeyType(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/internal/addrs/module_scope.go b/internal/addrs/module_scope.go new file mode 100644 index 000000000000..4a39a486c96a --- /dev/null +++ b/internal/addrs/module_scope.go @@ -0,0 +1,20 @@ +package addrs + +// ModuleEvalScope represents the different kinds of module scope that +// Terraform Core can evaluate expressions within. +// +// Its only two implementations are [ModuleInstance] and +// [PartialExpandedModule], where the latter represents the evaluation context +// for the "partial evaluation" mode which produces placeholder values for +// not-yet-expanded modules. +// +// A nil ModuleEvalScope represents no evaluation scope at all, whereas a +// typed ModuleEvalScope represents either an exact expanded module or a +// partial-expanded module. +type ModuleEvalScope interface { + moduleEvalScopeSigil() +} + +func (ModuleInstance) moduleEvalScopeSigil() {} + +func (PartialExpandedModule) moduleEvalScopeSigil() {} diff --git a/internal/addrs/partial_expanded.go b/internal/addrs/partial_expanded.go index 6bffedac550e..1b8cea469764 100644 --- a/internal/addrs/partial_expanded.go +++ b/internal/addrs/partial_expanded.go @@ -175,6 +175,57 @@ func (pem PartialExpandedModule) Resource(resource Resource) PartialExpandedReso } } +// ParentIsModuleInstance returns true if +// [PartialExpandedModule.ParentModuleInstance] would succeed, or false if +// [PartialExpandedModule.ParentPartialExpandedModule] would succeed. +// +// In other words, it determines whether accessing the parent module would +// cross the boundary between the unexpanded and expanded portions of the +// address, which means that any further traversal upwards should be done +// using [ModuleInstance] values rather than [PartialExpandedModule] +// values. +func (pem PartialExpandedModule) ParentIsModuleInstance() bool { + // NOTE: We don't handle the case where unexpandedSuffix is zero-length + // here because standalone PartialExpandedModule values should always have + // at least one unexpanded part. + // + // This isn't true for the special PartialExpandedModule values hidden in + // the internals of PartialExpandedResource, so don't use this method with + // those. + return len(pem.unexpandedSuffix) == 1 +} + +// ParentModuleInstance returns the fully-expanded module instance that is the +// parent of this module if and only if the last step is the only step in the +// path that is unexpanded. +// +// If the receiever does not meet that criteria, the second return value is +// false. Use ParentPartialExpandedModule instead in that case, to get the +// parent represented as a [PartialExpandedModule]. +func (pem PartialExpandedModule) ParentModuleInstance() (ModuleInstance, bool) { + if len(pem.unexpandedSuffix) != 1 { + return nil, false + } + return pem.expandedPrefix, true +} + +// ParentPartialExpandedModule is like ParentModuleInstance but deals with the +// situation where the parent is also partially-expanded and so needs to still +// be described as a PartialExpandedModule. +// +// If the reciever's parent is already exact then the second return value is +// false. Use ParentModuleInstance instead in that case, to get the parent +// represented as a [ModuleInstance]. +func (pem PartialExpandedModule) ParentPartialExpandedModule() (PartialExpandedModule, bool) { + if len(pem.unexpandedSuffix) < 2 { + return PartialExpandedModule{}, false + } + return PartialExpandedModule{ + expandedPrefix: pem.expandedPrefix, + unexpandedSuffix: pem.unexpandedSuffix[: len(pem.unexpandedSuffix)-1 : len(pem.unexpandedSuffix)-1], + }, true +} + // String returns a string representation of the pattern where the known // prefix uses the normal module instance address syntax and the unknown // suffix steps use a similar syntax but with "[*]" as a placeholder to @@ -295,6 +346,45 @@ func (per PartialExpandedResource) AbsResource() (AbsResource, bool) { }, true } +// FullyExpandedModuleInstance returns the [ModuleInstance] that the receiver +// belongs to if and only if it belongs to a fully-known module path. +// +// The second return value is true only if the first return value is valid. +func (per PartialExpandedResource) FullyExpandedModuleInstance() (ModuleInstance, bool) { + if len(per.module.unexpandedSuffix) != 0 { + return nil, false + } + return per.module.expandedPrefix, true +} + +// PartialExpandedModuleInstance returns the [PartialExpandedModule] that the +// receiver belongs to if and only if the module path is not fully known. +// For a fully-known path use [PartialExpandedResource.FullyExpandedModuleInstance] +// instead, to obtain a [ModuleInstance] +func (per PartialExpandedResource) PartialExpandedModuleInstance() (PartialExpandedModule, bool) { + // We can only reveal our module field's value if it has at least one + // expanded element, because otherwise it will violate the assumptions + // made in the exported API of PartialExpandedModule. + if len(per.module.unexpandedSuffix) == 0 { + return PartialExpandedModule{}, false + } + return per.module, true +} + +// ModuleEvalScope returns the [ModuleEvalScope] that the receiver should +// have its expressions evaluated in. +func (per PartialExpandedResource) ModuleEvalScope() ModuleEvalScope { + if addr, ok := per.FullyExpandedModuleInstance(); ok { + return addr + } else if addr, ok := per.PartialExpandedModuleInstance(); ok { + return addr + } else { + // Should never get here because we should always have exactly one + // of the two address types above. + panic("unexpected ModuleEvalScope type for PartialExpandedResource") + } +} + // ConfigResource returns the unexpanded resource address that this // partially-expanded resource address originates from. func (per PartialExpandedResource) ConfigResource() ConfigResource { diff --git a/internal/backend/remote/backend_state.go b/internal/backend/remote/backend_state.go index 6c90f7f4be11..b397c6f07cdd 100644 --- a/internal/backend/remote/backend_state.go +++ b/internal/backend/remote/backend_state.go @@ -98,7 +98,7 @@ func (r *remoteClient) Put(state []byte) error { return fmt.Errorf("error reading state: %s", err) } - ov, err := jsonstate.MarshalOutputs(stateFile.State.RootModule().OutputValues) + ov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues) if err != nil { return fmt.Errorf("error reading output values: %s", err) } diff --git a/internal/builtin/providers/terraform/data_source_state.go b/internal/builtin/providers/terraform/data_source_state.go index 82b39d1e3440..77e1c77d83fc 100644 --- a/internal/builtin/providers/terraform/data_source_state.go +++ b/internal/builtin/providers/terraform/data_source_state.go @@ -169,11 +169,8 @@ func dataSourceRemoteStateRead(d cty.Value) (cty.Value, tfdiags.Diagnostics) { newState["outputs"] = cty.EmptyObjectVal return cty.ObjectVal(newState), diags } - mod := remoteState.RootModule() - if mod != nil { // should always have a root module in any valid state - for k, os := range mod.OutputValues { - outputs[k] = os.Value - } + for k, os := range remoteState.RootOutputValues { + outputs[k] = os.Value } newState["outputs"] = cty.ObjectVal(outputs) diff --git a/internal/cloud/state.go b/internal/cloud/state.go index 55e37d86346d..54e0def19f86 100644 --- a/internal/cloud/state.go +++ b/internal/cloud/state.go @@ -220,7 +220,7 @@ func (s *State) PersistState(schemas *terraform.Schemas) error { return fmt.Errorf("failed to read state: %w", err) } - ov, err := jsonstate.MarshalOutputs(stateFile.State.RootModule().OutputValues) + ov, err := jsonstate.MarshalOutputs(stateFile.State.RootOutputValues) if err != nil { return fmt.Errorf("failed to translate outputs: %w", err) } @@ -547,7 +547,7 @@ func (s *State) GetRootOutputValues() (map[string]*states.OutputValue, error) { return nil, ErrStateVersionUnauthorizedUpgradeState } - return state.RootModule().OutputValues, nil + return state.RootOutputValues, nil } if output.Sensitive { diff --git a/internal/command/apply.go b/internal/command/apply.go index 4a7ced21203d..e3ea24c86901 100644 --- a/internal/command/apply.go +++ b/internal/command/apply.go @@ -137,7 +137,7 @@ func (c *ApplyCommand) Run(rawArgs []string) int { if rb, isRemoteBackend := be.(BackendWithRemoteTerraformVersion); !isRemoteBackend || rb.IsLocalOperations() { view.ResourceCount(args.State.StateOutPath) if !c.Destroy && op.State != nil { - view.Outputs(op.State.RootModule().OutputValues) + view.Outputs(op.State.RootOutputValues) } } diff --git a/internal/command/command_test.go b/internal/command/command_test.go index 07a6872bab78..eafe5befdd5c 100644 --- a/internal/command/command_test.go +++ b/internal/command/command_test.go @@ -355,7 +355,10 @@ func testStateMgrCurrentLineage(mgr statemgr.Persistent) string { // // (do stuff to the state) // assertStateHasMarker(state, mark) func markStateForMatching(state *states.State, mark string) string { - state.RootModule().SetOutputValue("testing_mark", cty.StringVal(mark), false) + state.SetOutputValue( + addrs.OutputValue{Name: "testing_mark"}.Absolute(addrs.RootModuleInstance), + cty.StringVal(mark), false, + ) return mark } @@ -363,7 +366,7 @@ func markStateForMatching(state *states.State, mark string) string { // mark string previously added to the given state. If no such mark is present, // the result is an empty string. func getStateMatchingMarker(state *states.State) string { - os := state.RootModule().OutputValues["testing_mark"] + os := state.RootOutputValues["testing_mark"] if os == nil { return "" } diff --git a/internal/command/e2etest/primary_test.go b/internal/command/e2etest/primary_test.go index 26252850b0e4..c7b6eaa1ee24 100644 --- a/internal/command/e2etest/primary_test.go +++ b/internal/command/e2etest/primary_test.go @@ -204,13 +204,13 @@ func TestPrimaryChdirOption(t *testing.T) { t.Fatalf("failed to read state file: %s", err) } - gotOutput := state.RootModule().OutputValues["cwd"] + gotOutput := state.RootOutputValues["cwd"] wantOutputValue := cty.StringVal(filepath.ToSlash(tf.Path())) // path.cwd returns the original path, because path.root is how we get the overridden path if gotOutput == nil || !wantOutputValue.RawEquals(gotOutput.Value) { t.Errorf("incorrect value for cwd output\ngot: %#v\nwant Value: %#v", gotOutput, wantOutputValue) } - gotOutput = state.RootModule().OutputValues["root"] + gotOutput = state.RootOutputValues["root"] wantOutputValue = cty.StringVal(filepath.ToSlash(tf.Path("subdir"))) // path.root is a relative path, but the text fixture uses abspath on it. if gotOutput == nil || !wantOutputValue.RawEquals(gotOutput.Value) { t.Errorf("incorrect value for root output\ngot: %#v\nwant Value: %#v", gotOutput, wantOutputValue) diff --git a/internal/command/e2etest/terraform_test.go b/internal/command/e2etest/terraform_test.go index 1ceb307fe4a7..29b99ba5c3b6 100644 --- a/internal/command/e2etest/terraform_test.go +++ b/internal/command/e2etest/terraform_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/e2e" ) @@ -46,7 +45,7 @@ func TestTerraformProviderData(t *testing.T) { } // we'll check the final output to validate the resources - d := state.Module(addrs.RootModuleInstance).OutputValues["d"].Value + d := state.RootOutputValues["d"].Value input := d.GetAttr("input") output := d.GetAttr("output") if input.IsNull() { diff --git a/internal/command/jsonformat/state_test.go b/internal/command/jsonformat/state_test.go index 8ef37fd4c304..aeb3cf8dd2b3 100644 --- a/internal/command/jsonformat/state_test.go +++ b/internal/command/jsonformat/state_test.go @@ -32,32 +32,32 @@ func TestState(t *testing.T) { Schemas *terraform.Schemas Want string }{ - { + 0: { State: &states.State{}, Schemas: &terraform.Schemas{}, Want: "The state file is empty. No resources are represented.\n", }, - { + 1: { State: basicState(t), Schemas: testSchemas(), Want: basicStateOutput, }, - { + 2: { State: nestedState(t), Schemas: testSchemas(), Want: nestedStateOutput, }, - { + 3: { State: deposedState(t), Schemas: testSchemas(), Want: deposedNestedStateOutput, }, - { + 4: { State: onlyDeposedState(t), Schemas: testSchemas(), Want: onlyDeposedOutput, }, - { + 5: { State: stateWithMoreOutputs(t), Schemas: testSchemas(), Want: stateWithMoreOutputsOutput, @@ -252,8 +252,10 @@ func basicState(t *testing.T) *states.State { t.Errorf("root module is nil; want valid object") } - rootModule.SetLocalValue("foo", cty.StringVal("foo value")) - rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar value"), false, + ) rootModule.SetResourceInstanceCurrent( addrs.Resource{ Mode: addrs.ManagedResourceMode, @@ -297,14 +299,30 @@ func stateWithMoreOutputs(t *testing.T) *states.State { t.Errorf("root module is nil; want valid object") } - rootModule.SetOutputValue("string_var", cty.StringVal("string value"), false) - rootModule.SetOutputValue("int_var", cty.NumberIntVal(42), false) - rootModule.SetOutputValue("bool_var", cty.BoolVal(true), false) - rootModule.SetOutputValue("sensitive_var", cty.StringVal("secret!!!"), true) - rootModule.SetOutputValue("map_var", cty.MapVal(map[string]cty.Value{ - "first": cty.StringVal("foo"), - "second": cty.StringVal("bar"), - }), false) + state.SetOutputValue( + addrs.OutputValue{Name: "string_var"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("string value"), false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "int_var"}.Absolute(addrs.RootModuleInstance), + cty.NumberIntVal(42), false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "bool_var"}.Absolute(addrs.RootModuleInstance), + cty.True, false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "sensitive_var"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("secret!!!"), true, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "map_var"}.Absolute(addrs.RootModuleInstance), + cty.MapVal(map[string]cty.Value{ + "first": cty.StringVal("foo"), + "second": cty.StringVal("bar"), + }), + false, + ) rootModule.SetResourceInstanceCurrent( addrs.Resource{ diff --git a/internal/command/jsonstate/state.go b/internal/command/jsonstate/state.go index ae46225a2108..e7b1d07de53d 100644 --- a/internal/command/jsonstate/state.go +++ b/internal/command/jsonstate/state.go @@ -149,7 +149,7 @@ func MarshalForRenderer(sf *statefile.File, schemas *terraform.Schemas) (Module, return Module{}, nil, nil } - outputs, err := MarshalOutputs(sf.State.RootModule().OutputValues) + outputs, err := MarshalOutputs(sf.State.RootOutputValues) if err != nil { return Module{}, nil, err } @@ -193,7 +193,7 @@ func (jsonstate *state) marshalStateValues(s *states.State, schemas *terraform.S var err error // only marshal the root module outputs - sv.Outputs, err = MarshalOutputs(s.RootModule().OutputValues) + sv.Outputs, err = MarshalOutputs(s.RootOutputValues) if err != nil { return err } diff --git a/internal/command/meta_backend_test.go b/internal/command/meta_backend_test.go index 8f647fe36611..ab777fb26328 100644 --- a/internal/command/meta_backend_test.go +++ b/internal/command/meta_backend_test.go @@ -136,7 +136,10 @@ func TestMetaBackend_emptyWithDefaultState(t *testing.T) { // Write some state next := testState() - next.RootModule().SetOutputValue("foo", cty.StringVal("bar"), false) + next.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) s.WriteState(next) if err := s.PersistState(nil); err != nil { t.Fatalf("unexpected error: %s", err) @@ -1862,7 +1865,10 @@ func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) { // // create our local state orig := states.NewState() - orig.Module(addrs.RootModuleInstance).SetOutputValue("foo", cty.StringVal("bar"), false) + orig.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) testStateFileDefault(t, orig) m := testMetaBackend(t, nil) diff --git a/internal/command/refresh.go b/internal/command/refresh.go index 8b54bb9e47a3..c92a019ecaac 100644 --- a/internal/command/refresh.go +++ b/internal/command/refresh.go @@ -104,7 +104,7 @@ func (c *RefreshCommand) Run(rawArgs []string) int { } if op.State != nil { - view.Outputs(op.State.RootModule().OutputValues) + view.Outputs(op.State.RootOutputValues) } return op.Result.ExitStatus() diff --git a/internal/command/show_test.go b/internal/command/show_test.go index b6a999615e61..4c0cdf1ff4fe 100644 --- a/internal/command/show_test.go +++ b/internal/command/show_test.go @@ -494,12 +494,15 @@ func TestShow_plan_json(t *testing.T) { func TestShow_state(t *testing.T) { originalState := testState() - root := originalState.RootModule() - root.SetOutputValue("test", cty.ObjectVal(map[string]cty.Value{ - "attr": cty.NullVal(cty.DynamicPseudoType), - "null": cty.NullVal(cty.String), - "list": cty.ListVal([]cty.Value{cty.NullVal(cty.Number)}), - }), false) + originalState.SetOutputValue( + addrs.OutputValue{Name: "test"}.Absolute(addrs.RootModuleInstance), + cty.ObjectVal(map[string]cty.Value{ + "attr": cty.NullVal(cty.DynamicPseudoType), + "null": cty.NullVal(cty.String), + "list": cty.ListVal([]cty.Value{cty.NullVal(cty.Number)}), + }), + false, + ) statePath := testStateFile(t, originalState) defer os.RemoveAll(filepath.Dir(statePath)) diff --git a/internal/namedvals/state.go b/internal/namedvals/state.go index a96f10c6e3b1..0b4a2ea5aa7c 100644 --- a/internal/namedvals/state.go +++ b/internal/namedvals/state.go @@ -107,6 +107,54 @@ func (s *State) GetOutputValue(addr addrs.AbsOutputValue) cty.Value { return s.outputs.GetExactResult(addr) } +func (s *State) GetOutputValuesForModuleCall(parentAddr addrs.ModuleInstance, callAddr addrs.ModuleCall) addrs.Map[addrs.AbsOutputValue, cty.Value] { + s.mu.Lock() + defer s.mu.Unlock() + + // HACK: The "values" data structure isn't really designed to support + // this operation, since it tries to be general over all different named + // value address types but that makes it unable to generically handle + // the problem of finding the module instance for a particular absolute + // address. We'd need a ModuleInstance equivalent of + // addrs.InPartialExpandedModule to achieve that, but our "Abs" address + // types are all hand-written and predate Go having support for generic + // types. + // + // This operation is just a stop-gap until we make the evaluator work + // in a different way to handle placeholder values, so we'll accept it + // being clunky and slow just as a checkpoint to make everything still + // work similarly to how it used to, and then delete this function again + // later once we can implement what we need using just + // [State.GetOutputValue] by having the caller determine which output + // values it should be asking for using the configuration. + + ret := addrs.MakeMap[addrs.AbsOutputValue, cty.Value]() + all := s.outputs.GetExactResults() + + for _, elem := range all.Elems { + outputMod := elem.Key.Module + if outputMod.IsRoot() { + // We cannot enumerate the root module output values with this + // function, because the root module has no "call". + continue + } + callingMod, call := outputMod.Call() + if call != callAddr { + continue + } + if !callingMod.Equal(parentAddr) { + continue + } + + // If we get here then the output value we're holding belongs to + // one of the instances of the call indicated in this function's + // arguments. + ret.PutElement(elem) + } + + return ret +} + func (s *State) HasOutputValue(addr addrs.AbsOutputValue) bool { s.mu.Lock() defer s.mu.Unlock() diff --git a/internal/namedvals/values.go b/internal/namedvals/values.go index eb559ae68f9e..f24a89c16221 100644 --- a/internal/namedvals/values.go +++ b/internal/namedvals/values.go @@ -90,6 +90,10 @@ func (v *values[LocalType, AbsType]) GetExactResult(addr AbsType) cty.Value { return v.exact.Get(addr) } +func (v *values[LocalType, AbsType]) GetExactResults() addrs.Map[AbsType, cty.Value] { + return v.exact +} + func (v *values[LocalType, AbsType]) SetPlaceholderResult(addr addrs.InPartialExpandedModule[LocalType], val cty.Value) { modAddr := addr.Module.Module() if !v.placeholder.Has(modAddr) { diff --git a/internal/plans/deferring/deferred.go b/internal/plans/deferring/deferred.go new file mode 100644 index 000000000000..e71d7111a283 --- /dev/null +++ b/internal/plans/deferring/deferred.go @@ -0,0 +1,109 @@ +package deferring + +import ( + "sync" + + "github.com/hashicorp/terraform/internal/addrs" +) + +// Deferred is the main type tracking which objects have already been deferred +// and what other objects might have their planning deferred as a result. +type Deferred struct { + // See the description of the resourceDeps argument of [NewDeferred]. + resourceDeps addrs.DirectedGraph[addrs.ConfigResource] + + // deferred is the set of addresses of all resources that either had their + // expansion deferred or whose provider requested deferral during of a + // specific instance during planning. The detail about exactly which + // instances were deferred is tracked in the plan, instead of in this + // data structure. + deferredResources addrs.Set[addrs.ConfigResource] + + // forceAllDeferred is a special case for when Terraform Core is planning + // a configuration that is downstream of some other configuration that + // included deferrals, which means that nothing at all in this configuration + // can be definitively planned yet. + forceAllDeferred bool + + mu sync.Mutex +} + +// NewDeferred allocates and returns a new [Deferred] which can track the +// deferral statuses for objects during Terraform Core evaluation and answer +// questions about whether downstream objects ought to be deferred as a result +// of existing deferrals. +// +// resourceDeps describes the dependency graph of unexpanded resources, +// which we need to decide whether a particular resource ought to be +// deferred as a result of one of its upstreams being deferred. +// This graph must always describe the same effective dependences as the +// main execution graph in Terraform Core, so that questions about +// downstream deferrals will arrive in the correct order for their +// information to be available. +// +// The caller must not modify anything reachable through the given arguments +// after passing them to this function. +func NewDeferred(resourceDeps addrs.DirectedGraph[addrs.ConfigResource]) *Deferred { + return &Deferred{ + resourceDeps: resourceDeps, + deferredResources: addrs.MakeSet[addrs.ConfigResource](), + } +} + +// ForceAllDeferred makes all future queries about whether an object should be +// deferred indicate that it _should_ be deferred. +// +// This should typically be called before beginning the Terraform Core graph +// walk to represent the special situation where we're planning a configuration +// that depends on some other configuration which itself had deferred actions, +// and therefore all of the actions we plan must be deferred. +func (d *Deferred) ForceAllDeferred() { + d.mu.Lock() + d.forceAllDeferred = true + d.mu.Unlock() +} + +// ReportResourceDeferred records that a particular resource has at least one +// deferred instance, or that its entire expansion was deferred. +// +// Terraform Core must call this for any resource that it generates deferred +// actions for, even if that deferral was forced by one of the "Should" +// functions on this same object, because our analyses typically consider only +// direct dependencies on the assumption that Terraform Core is going to visit +// everything in order anyway. +func (d *Deferred) ReportResourceDeferred(addr addrs.ConfigResource) { + // NOTE: We're currently only tracking deferral for entire ConfigResource + // addresses, which means that we don't track which module instances each + // deferral belongs to and so this analysis will be very conservative when + // considering deferrals inside multi-instance modules. + // + // We might improve the accuracy of this later, but we'll wait to see if + // that's justified based on experience with real-world usage. Even this + // imprecise analysis is presumably better than failing outright whenever + // unknown values appear in an unfortunate place. + + d.mu.Lock() + d.deferredResources.Add(addr) + d.mu.Unlock() +} + +func (d *Deferred) ShouldDeferResourceInstanceAction(addr addrs.AbsResourceInstance) bool { + d.mu.Lock() + defer d.mu.Unlock() + + if d.forceAllDeferred { + return true + } + + // We use DirectDependenciesOf because we expect Terraform Core to visit + // all of the resources in dependency order and to have already called + // ReportResourceDeferred for any direct upstreams that were deferred for + // any reason. + deps := d.resourceDeps.DirectDependenciesOf(addr.ConfigResource()) + for _, depAddr := range deps { + if d.deferredResources.Has(depAddr) { + return true + } + } + return false +} diff --git a/internal/plans/deferring/doc.go b/internal/plans/deferring/doc.go new file mode 100644 index 000000000000..4416c687ee3a --- /dev/null +++ b/internal/plans/deferring/doc.go @@ -0,0 +1,4 @@ +// Package deferring has data structures that aim to encapsulate the details +// of how the full planning of certain actions might be deferred until a future +// plan where there's more information available. +package deferring diff --git a/internal/plans/deferring/reason.go b/internal/plans/deferring/reason.go new file mode 100644 index 000000000000..c0d52a07caff --- /dev/null +++ b/internal/plans/deferring/reason.go @@ -0,0 +1,54 @@ +package deferring + +import ( + "github.com/zclconf/go-cty/cty" +) + +// Reason is an enumeration of possible reasons for deferring. +type Reason rune + +//go:generate go run golang.org/x/tools/cmd/stringer -type=Reason + +const ( + // BecauseUpstream means that an action was deferred because it depends + // on the result of some other action that was deferred. + // + // In this case the proposed action should typically be complete in itself + // but must be deferred anyway to preserve the correct order of operations + // in relation to some other deferred action. + BecauseUpstream = '↰' + + // BecauseExpansionUnknown means that an action was deferred because + // Terraform can't yet calculate the full set of instances of the object + // whose action is being described. + BecauseExpansionUnknown = '#' + + // BecauseProviderConfigUnknown means that a resource instance action was + // deferred because the configuration for the provider instance that would + // be performing the action is not yet sufficiently known to produce a + // complete plan. + BecauseProviderConfigUnknown = 'P' + + // BecauseResourceInstanceConfigUnknown means that a resource instance + // action was deferred because the configuration for that resource instance + // is not yet sufficiently known to produce a complete plan. + BecauseResourceInstanceConfigUnknown = 'R' +) + +// Explanation combines a deferral reason with other reason-specific +// information. +type Explanation struct { + // Reason describes both the deferral reason and how to interpret the + // other fields of this type. + Reason Reason + + // ArgPath describes an attribute path to an argument in an object that + // specifically caused the deferral. + // + // - For [BecauseProviderConfigUnknown] this is a path into the provider + // configuration block that the relevant resource is associated with. + // - For [BecauseResourceInstanceConfigUnknown] this is a path into the + // configuration of the relevant resource instance. + // - For all other reasons this is always nil. + ArgPath cty.Path +} diff --git a/internal/plugin6/convert/deferred.go b/internal/plugin6/convert/deferred.go new file mode 100644 index 000000000000..f4f2ee5f3904 --- /dev/null +++ b/internal/plugin6/convert/deferred.go @@ -0,0 +1,29 @@ +package convert + +import ( + "github.com/hashicorp/terraform/internal/providers" + "github.com/hashicorp/terraform/internal/tfplugin6" +) + +func DeferredReasonFromProto(protoReason *tfplugin6.DeferredAction) providers.DeferredReason { + if protoReason == nil { + // Should never happen, but we'll treat it as an "other" reason + // for robustness against oddly-behaving providers. + return providers.NewDeferredReasonOther() + } + + switch protoReason := protoReason.Reason.(type) { + case *tfplugin6.DeferredAction_ProviderConfigUnknown: + return providers.NewDeferredReasonUnknownProviderConfig( + AttributePathToPath(protoReason.ProviderConfigUnknown.Attribute), + ) + case *tfplugin6.DeferredAction_ResourceConfigUnknown: + return providers.NewDeferredReasonUnknownResourceConfig( + AttributePathToPath(protoReason.ResourceConfigUnknown.Attribute), + ) + default: + // Fallback for all unrecognized reasons, in case later protocol + // versions define additional ones. + return providers.NewDeferredReasonOther() + } +} diff --git a/internal/plugin6/grpc_provider.go b/internal/plugin6/grpc_provider.go index 70e65cd7f9ca..912114733c48 100644 --- a/internal/plugin6/grpc_provider.go +++ b/internal/plugin6/grpc_provider.go @@ -285,6 +285,7 @@ func (p *GRPCProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequ Json: r.RawStateJSON, Flatmap: r.RawStateFlatmap, }, + DeferAllowed: true, } protoResp, err := p.client.UpgradeResourceState(p.ctx, protoReq) @@ -307,6 +308,13 @@ func (p *GRPCProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequ } resp.UpgradedState = state + if len(protoResp.Deferred) != 0 { + resp.Deferred = make([]providers.DeferredReason, len(protoResp.Deferred)) + for i, raw := range protoResp.Deferred { + resp.Deferred[i] = convert.DeferredReasonFromProto(raw) + } + } + return resp } @@ -381,6 +389,7 @@ func (p *GRPCProvider) ReadResource(r providers.ReadResourceRequest) (resp provi TypeName: r.TypeName, CurrentState: &proto6.DynamicValue{Msgpack: mp}, Private: r.Private, + DeferAllowed: true, } if metaSchema.Block != nil { @@ -407,6 +416,13 @@ func (p *GRPCProvider) ReadResource(r providers.ReadResourceRequest) (resp provi resp.NewState = state resp.Private = protoResp.Private + if len(protoResp.Deferred) != 0 { + resp.Deferred = make([]providers.DeferredReason, len(protoResp.Deferred)) + for i, raw := range protoResp.Deferred { + resp.Deferred[i] = convert.DeferredReasonFromProto(raw) + } + } + return resp } @@ -460,6 +476,7 @@ func (p *GRPCProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) Config: &proto6.DynamicValue{Msgpack: configMP}, ProposedNewState: &proto6.DynamicValue{Msgpack: propMP}, PriorPrivate: r.PriorPrivate, + DeferAllowed: true, } if metaSchema.Block != nil { @@ -489,6 +506,13 @@ func (p *GRPCProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) resp.RequiresReplace = append(resp.RequiresReplace, convert.AttributePathToPath(p)) } + if len(protoResp.Deferred) != 0 { + resp.Deferred = make([]providers.DeferredReason, len(protoResp.Deferred)) + for i, raw := range protoResp.Deferred { + resp.Deferred[i] = convert.DeferredReasonFromProto(raw) + } + } + resp.PlannedPrivate = protoResp.PlannedPrivate resp.LegacyTypeSystem = protoResp.LegacyTypeSystem @@ -577,8 +601,9 @@ func (p *GRPCProvider) ImportResourceState(r providers.ImportResourceStateReques } protoReq := &proto6.ImportResourceState_Request{ - TypeName: r.TypeName, - Id: r.ID, + TypeName: r.TypeName, + Id: r.ID, + DeferAllowed: true, } protoResp, err := p.client.ImportResourceState(p.ctx, protoReq) @@ -588,6 +613,13 @@ func (p *GRPCProvider) ImportResourceState(r providers.ImportResourceStateReques } resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) + if len(protoResp.Deferred) != 0 { + resp.Deferred = make([]providers.DeferredReason, len(protoResp.Deferred)) + for i, raw := range protoResp.Deferred { + resp.Deferred[i] = convert.DeferredReasonFromProto(raw) + } + } + for _, imported := range protoResp.ImportedResources { resource := providers.ImportedResource{ TypeName: imported.TypeName, @@ -639,6 +671,7 @@ func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp p Config: &proto6.DynamicValue{ Msgpack: config, }, + DeferAllowed: true, } if metaSchema.Block != nil { @@ -664,6 +697,13 @@ func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp p } resp.State = state + if len(protoResp.Deferred) != 0 { + resp.Deferred = make([]providers.DeferredReason, len(protoResp.Deferred)) + for i, raw := range protoResp.Deferred { + resp.Deferred[i] = convert.DeferredReasonFromProto(raw) + } + } + return resp } diff --git a/internal/providers/deferred.go b/internal/providers/deferred.go new file mode 100644 index 000000000000..cc67814911dd --- /dev/null +++ b/internal/providers/deferred.go @@ -0,0 +1,68 @@ +package providers + +import ( + "github.com/zclconf/go-cty/cty" +) + +// DeferredReason describes one reason why a particular action cannot be +// completed fully in the current run, and must therefore be deferred to +// a later run where hopefully more informationis available. +// +// This is a sealed interface type whose full set of implementations lives +// inside this package. Future versions of this package may include additional +// implementations, so callers should use [DeferredReasonOther] as a placeholder +// if they encounter a [DeferredReason] type that they don't recognize. +type DeferredReason interface { + deferredReasonSigil() +} + +func NewDeferredReasonOther() DeferredReason { + return DeferredReasonOther{} +} + +func NewDeferredReasonUnknownProviderConfig(attributePath cty.Path) DeferredReason { + return DeferredReasonUnknownProviderConfig{ + AttributePath: attributePath, + } +} + +func NewDeferredReasonUnknownResourceConfig(attributePath cty.Path) DeferredReason { + return DeferredReasonUnknownResourceConfig{ + AttributePath: attributePath, + } +} + +// DeferredReasonOther is the [DeferredReason] implementation to use when +// none of the others are applicable, and also a good placeholder to use if +// a caller encounters a reason type it doesn't recognize. +type DeferredReasonOther struct{} + +func (DeferredReasonOther) deferredReasonSigil() {} + +// DeferredReasonUnknownProviderConfig is the [DeferredReason] implementation +// to represent that an unknown attribute value in the configuration of the +// provider responsible for the action prevents full planning or execution +// of the action. +type DeferredReasonUnknownProviderConfig struct { + // AttributePath is a path to the closest possible attribute to the one + // whose unknown value caused the problem, which Terraform might then use + // to highlight the particular attribute somehow in the UI. + // This path is resolved within the provider configuration, not within + // the configuration of a resource belonging to the provider. + AttributePath cty.Path +} + +func (DeferredReasonUnknownProviderConfig) deferredReasonSigil() {} + +// DeferredReasonUnknownProviderConfig is the [DeferredReason] implementation +// to represent that an unknown attribute value in the configuration of the +// resource an action relates to prevents full planning or execution of the +// action. +type DeferredReasonUnknownResourceConfig struct { + // AttributePath is a path to the closest possible attribute to the one + // whose unknown value caused the problem, which Terraform might then use + // to highlight the particular attribute somehow in the UI. + AttributePath cty.Path +} + +func (DeferredReasonUnknownResourceConfig) deferredReasonSigil() {} diff --git a/internal/providers/provider.go b/internal/providers/provider.go index bfaf2daa4026..ea5adb2ca4f2 100644 --- a/internal/providers/provider.go +++ b/internal/providers/provider.go @@ -189,6 +189,13 @@ type UpgradeResourceStateResponse struct { // Diagnostics contains any warnings or errors from the method call. Diagnostics tfdiags.Diagnostics + + // Deferred is a list of reasons why this action must be deferred to + // a later run when there's hopefully more information available. If this + // list has one or more items then Terraform will place this change and + // anything that depends on it into the "deferred changes" bucket, and + // therefore exclude it from the set of proposed changes for this run. + Deferred []DeferredReason } type ConfigureProviderRequest struct { @@ -234,6 +241,13 @@ type ReadResourceResponse struct { // Private is an opaque blob that will be stored in state along with the // resource. It is intended only for interpretation by the provider itself. Private []byte + + // Deferred is a list of reasons why this action must be deferred to + // a later run when there's hopefully more information available. If this + // list has one or more items then Terraform will place this change and + // anything that depends on it into the "deferred changes" bucket, and + // therefore exclude it from the set of proposed changes for this run. + Deferred []DeferredReason } type PlanResourceChangeRequest struct { @@ -283,6 +297,13 @@ type PlanResourceChangeResponse struct { // Diagnostics contains any warnings or errors from the method call. Diagnostics tfdiags.Diagnostics + // Deferred is a list of reasons why this action must be deferred to + // a later run when there's hopefully more information available. If this + // list has one or more items then Terraform will place this change and + // anything that depends on it into the "deferred changes" bucket, and + // therefore exclude it from the set of proposed changes for this run. + Deferred []DeferredReason + // LegacyTypeSystem is set only if the provider is using the legacy SDK // whose type system cannot be precisely mapped into the Terraform type // system. We use this to bypass certain consistency checks that would @@ -357,6 +378,13 @@ type ImportResourceStateResponse struct { // Diagnostics contains any warnings or errors from the method call. Diagnostics tfdiags.Diagnostics + + // Deferred is a list of reasons why this action must be deferred to + // a later run when there's hopefully more information available. If this + // list has one or more items then Terraform will place this change and + // anything that depends on it into the "deferred changes" bucket, and + // therefore exclude it from the set of proposed changes for this run. + Deferred []DeferredReason } // ImportedResource represents an object being imported into Terraform with the @@ -416,4 +444,11 @@ type ReadDataSourceResponse struct { // Diagnostics contains any warnings or errors from the method call. Diagnostics tfdiags.Diagnostics + + // Deferred is a list of reasons why this action must be deferred to + // a later run when there's hopefully more information available. If this + // list has one or more items then Terraform will place any change + // that depends on this result into the "deferred changes" bucket, and + // therefore exclude it from the set of proposed changes for this run. + Deferred []DeferredReason } diff --git a/internal/stacks/stackruntime/internal/stackeval/component_instance.go b/internal/stacks/stackruntime/internal/stackeval/component_instance.go index 1643e58f58db..9eb2b8b2a5a1 100644 --- a/internal/stacks/stackruntime/internal/stackeval/component_instance.go +++ b/internal/stacks/stackruntime/internal/stackeval/component_instance.go @@ -908,7 +908,7 @@ func (c *ComponentInstance) ResultValue(ctx context.Context, phase EvalPhase) ct // For apply and inspect phases we use the root module output values // from the state to construct our value. - outputVals := state.RootModule().OutputValues + outputVals := state.RootOutputValues attrs := make(map[string]cty.Value, len(outputVals)) for _, ov := range outputVals { name := ov.Addr.OutputValue.Name diff --git a/internal/states/module.go b/internal/states/module.go index edf30c7833e7..16b3c7564c21 100644 --- a/internal/states/module.go +++ b/internal/states/module.go @@ -4,8 +4,6 @@ package states import ( - "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/terraform/internal/addrs" ) @@ -16,23 +14,13 @@ type Module struct { // Resources contains the state for each resource. The keys in this map are // an implementation detail and must not be used by outside callers. Resources map[string]*Resource - - // OutputValues contains the state for each output value. The keys in this - // map are output value names. - OutputValues map[string]*OutputValue - - // LocalValues contains the value for each named output value. The keys - // in this map are local value names. - LocalValues map[string]cty.Value } // NewModule constructs an empty module state for the given module address. func NewModule(addr addrs.ModuleInstance) *Module { return &Module{ - Addr: addr, - Resources: map[string]*Resource{}, - OutputValues: map[string]*OutputValue{}, - LocalValues: map[string]cty.Value{}, + Addr: addr, + Resources: map[string]*Resource{}, } } @@ -253,43 +241,6 @@ func (ms *Module) maybeRestoreResourceInstanceDeposed(addr addrs.ResourceInstanc return true } -// SetOutputValue writes an output value into the state, overwriting any -// existing value of the same name. -func (ms *Module) SetOutputValue(name string, value cty.Value, sensitive bool) *OutputValue { - os := &OutputValue{ - Addr: addrs.AbsOutputValue{ - Module: ms.Addr, - OutputValue: addrs.OutputValue{ - Name: name, - }, - }, - Value: value, - Sensitive: sensitive, - } - ms.OutputValues[name] = os - return os -} - -// RemoveOutputValue removes the output value of the given name from the state, -// if it exists. This method is a no-op if there is no value of the given -// name. -func (ms *Module) RemoveOutputValue(name string) { - delete(ms.OutputValues, name) -} - -// SetLocalValue writes a local value into the state, overwriting any -// existing value of the same name. -func (ms *Module) SetLocalValue(name string, value cty.Value) { - ms.LocalValues[name] = value -} - -// RemoveLocalValue removes the local value of the given name from the state, -// if it exists. This method is a no-op if there is no value of the given -// name. -func (ms *Module) RemoveLocalValue(name string) { - delete(ms.LocalValues, name) -} - // PruneResourceHusks is a specialized method that will remove any Resource // objects that do not contain any instances, even if they have an EachMode. // @@ -318,7 +269,5 @@ func (ms *Module) empty() bool { // This must be updated to cover any new collections added to Module // in future. - return (len(ms.Resources) == 0 && - len(ms.OutputValues) == 0 && - len(ms.LocalValues) == 0) + return len(ms.Resources) == 0 } diff --git a/internal/states/remote/state.go b/internal/states/remote/state.go index ebcbc59e745d..ca08ab789ff2 100644 --- a/internal/states/remote/state.go +++ b/internal/states/remote/state.go @@ -70,7 +70,7 @@ func (s *State) GetRootOutputValues() (map[string]*states.OutputValue, error) { state = states.NewState() } - return state.RootModule().OutputValues, nil + return state.RootOutputValues, nil } // StateForMigration is part of our implementation of statemgr.Migrator. diff --git a/internal/states/remote/state_test.go b/internal/states/remote/state_test.go index 826d5f5a80ef..ce34ff7badab 100644 --- a/internal/states/remote/state_test.go +++ b/internal/states/remote/state_test.go @@ -233,7 +233,10 @@ func TestStatePersist(t *testing.T) { name: "add output to state", mutationFunc: func(mgr *State) (*states.State, func()) { s := mgr.State() - s.RootModule().SetOutputValue("foo", cty.StringVal("bar"), false) + s.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) return s, func() {} }, expectedRequests: []mockClientRequest{ @@ -261,7 +264,10 @@ func TestStatePersist(t *testing.T) { name: "mutate state bar -> baz", mutationFunc: func(mgr *State) (*states.State, func()) { s := mgr.State() - s.RootModule().SetOutputValue("foo", cty.StringVal("baz"), false) + s.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("baz"), false, + ) return s, func() {} }, expectedRequests: []mockClientRequest{ diff --git a/internal/states/state.go b/internal/states/state.go index 20e25341c964..e3e8f2d961ca 100644 --- a/internal/states/state.go +++ b/internal/states/state.go @@ -7,10 +7,9 @@ import ( "fmt" "sort" - "github.com/zclconf/go-cty/cty" - "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/getproviders" + "github.com/zclconf/go-cty/cty" ) // State is the top-level type of a Terraform state. @@ -29,6 +28,14 @@ type State struct { // an implementation detail and must not be used by outside callers. Modules map[string]*Module + // OutputValues contains the state for each output value defined in the + // root module. + // + // Output values in other modules don't persist anywhere between runs, + // so Terraform Core tracks those only internally and does not expose + // them in any artifacts that survive between runs. + RootOutputValues map[string]*OutputValue + // CheckResults contains a snapshot of the statuses of checks at the // end of the most recent update to the state. Callers might compare // checks between runs to see if e.g. a previously-failing check has @@ -48,7 +55,8 @@ func NewState() *State { modules := map[string]*Module{} modules[addrs.RootModuleInstance.String()] = NewModule(addrs.RootModuleInstance) return &State{ - Modules: modules, + Modules: modules, + RootOutputValues: make(map[string]*OutputValue), } } @@ -68,11 +76,11 @@ func (s *State) Empty() bool { if s == nil { return true } + if len(s.RootOutputValues) != 0 { + return false + } for _, ms := range s.Modules { - if len(ms.Resources) != 0 { - return false - } - if len(ms.OutputValues) != 0 { + if !ms.empty() { return false } } @@ -99,35 +107,6 @@ func (s *State) ModuleInstances(addr addrs.Module) []*Module { return ms } -// ModuleOutputs returns all outputs for the given module call under the -// parentAddr instance. -func (s *State) ModuleOutputs(parentAddr addrs.ModuleInstance, module addrs.ModuleCall) []*OutputValue { - var os []*OutputValue - for _, m := range s.Modules { - // can't get outputs from the root module - if m.Addr.IsRoot() { - continue - } - - parent, call := m.Addr.Call() - // make sure this is a descendent in the correct path - if !parentAddr.Equal(parent) { - continue - } - - // and check if this is the correct child - if call.Name != module.Name { - continue - } - - for _, o := range m.OutputValues { - os = append(os, o) - } - } - - return os -} - // RemoveModule removes the module with the given address from the state, // unless it is the root module. The root module cannot be deleted, and so // this method will panic if that is attempted. @@ -308,22 +287,39 @@ func (s *State) ResourceInstanceObjectSrc(addr addrs.AbsResourceInstanceObject) // OutputValue returns the state for the output value with the given address, // or nil if no such output value is tracked in the state. +// +// Only root module output values are tracked in the state, so this always +// returns nil for output values in any other module. func (s *State) OutputValue(addr addrs.AbsOutputValue) *OutputValue { - ms := s.Module(addr.Module) - if ms == nil { + if !addr.Module.IsRoot() { return nil } - return ms.OutputValues[addr.OutputValue.Name] + return s.RootOutputValues[addr.OutputValue.Name] } -// LocalValue returns the value of the named local value with the given address, -// or cty.NilVal if no such value is tracked in the state. -func (s *State) LocalValue(addr addrs.AbsLocalValue) cty.Value { - ms := s.Module(addr.Module) - if ms == nil { - return cty.NilVal +// SetOutputValue updates the value stored for the given output value if and +// only if it's a root module output value. +// +// All other output values will just be silently ignored, because we don't +// store those here anymore. (They live in a namedvals.State object hidden +// in the internals of Terraform Core.) +func (s *State) SetOutputValue(addr addrs.AbsOutputValue, value cty.Value, sensitive bool) { + if !addr.Module.IsRoot() { + return + } + s.RootOutputValues[addr.OutputValue.Name] = &OutputValue{ + Addr: addr, + Value: value, + Sensitive: sensitive, + } +} + +// RemoveOutputValue removes the record of a previously-stored output value. +func (s *State) RemoveOutputValue(addr addrs.AbsOutputValue) { + if !addr.Module.IsRoot() { + return } - return ms.LocalValues[addr.LocalValue.Name] + delete(s.RootOutputValues, addr.OutputValue.Name) } // ProviderAddrs returns a list of all of the provider configuration addresses @@ -566,13 +562,6 @@ func (s *State) MoveModuleInstance(src, dst addrs.ModuleInstance) { r.Addr.Module = dst } } - - // Update any OutputValues's addresses. - if srcMod.OutputValues != nil { - for _, ov := range srcMod.OutputValues { - ov.Addr.Module = dst - } - } } // MaybeMoveModuleInstance moves the given src ModuleInstance's current state to diff --git a/internal/states/state_deepcopy.go b/internal/states/state_deepcopy.go index 834a9e13da12..5bd88f77772a 100644 --- a/internal/states/state_deepcopy.go +++ b/internal/states/state_deepcopy.go @@ -31,9 +31,14 @@ func (s *State) DeepCopy() *State { for k, m := range s.Modules { modules[k] = m.DeepCopy() } + outputValues := make(map[string]*OutputValue, len(s.RootOutputValues)) + for k, v := range s.RootOutputValues { + outputValues[k] = v.DeepCopy() + } return &State{ - Modules: modules, - CheckResults: s.CheckResults.DeepCopy(), + Modules: modules, + RootOutputValues: outputValues, + CheckResults: s.CheckResults.DeepCopy(), } } @@ -54,21 +59,10 @@ func (ms *Module) DeepCopy() *Module { for k, r := range ms.Resources { resources[k] = r.DeepCopy() } - outputValues := make(map[string]*OutputValue, len(ms.OutputValues)) - for k, v := range ms.OutputValues { - outputValues[k] = v.DeepCopy() - } - localValues := make(map[string]cty.Value, len(ms.LocalValues)) - for k, v := range ms.LocalValues { - // cty.Value is immutable, so we don't need to copy these. - localValues[k] = v - } return &Module{ - Addr: ms.Addr, // technically mutable, but immutable by convention - Resources: resources, - OutputValues: outputValues, - LocalValues: localValues, + Addr: ms.Addr, // technically mutable, but immutable by convention + Resources: resources, } } diff --git a/internal/states/state_string.go b/internal/states/state_string.go index 2e34834a5518..6e6796ea2d9a 100644 --- a/internal/states/state_string.go +++ b/internal/states/state_string.go @@ -38,7 +38,7 @@ func (s *State) String() string { var buf bytes.Buffer for _, name := range modules { m := s.Modules[name] - mStr := m.testString() + mStr := m.testString(s) // If we're the root module, we just write the output directly. if m.Addr.IsRoot() { @@ -76,7 +76,7 @@ func (s *State) String() string { // testString is used to produce part of the output of State.String. It should // never be used directly. -func (ms *Module) testString() string { +func (ms *Module) testString(state *State) string { var buf bytes.Buffer if len(ms.Resources) == 0 { @@ -204,17 +204,25 @@ func (ms *Module) testString() string { } } - if len(ms.OutputValues) > 0 { + // This is a bit weird because we used to store output values for all + // modules in the state, but now we use it only for the root output + // values since they are the only ones that persist between runs. + // + // To keep this long-suffering legacy string representation compatible + // (since so many of our older tests depend on it) we have this structured + // in as close as possible to the same way it was when OutputValues was + // a field of ms, instead of RootOutputValues in State. + if ms.Addr.IsRoot() && len(state.RootOutputValues) != 0 { buf.WriteString("\nOutputs:\n\n") - ks := make([]string, 0, len(ms.OutputValues)) - for k := range ms.OutputValues { + ks := make([]string, 0, len(state.RootOutputValues)) + for k := range state.RootOutputValues { ks = append(ks, k) } sort.Strings(ks) for _, k := range ks { - v := ms.OutputValues[k] + v := state.RootOutputValues[k] lv := hcl2shim.ConfigValueFromHCL2(v.Value) switch vTyped := lv.(type) { case string: diff --git a/internal/states/state_test.go b/internal/states/state_test.go index 1f79ff61e080..a13e7d45b241 100644 --- a/internal/states/state_test.go +++ b/internal/states/state_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/go-test/deep" + "github.com/google/go-cmp/cmp" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" @@ -27,9 +28,14 @@ func TestState(t *testing.T) { t.Errorf("root module is nil; want valid object") } - rootModule.SetLocalValue("foo", cty.StringVal("foo value")) - rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false) - rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true) + state.SetOutputValue( + addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar value"), false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "secret"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("secret value"), true, + ) rootModule.SetResourceInstanceCurrent( addrs.Resource{ Mode: addrs.ManagedResourceMode, @@ -47,40 +53,43 @@ func TestState(t *testing.T) { }, ) + // State silently ignores attempts to write to non-root outputs, because + // historically we did track those here but these days we track them in + // namedvals.State instead, and we're being gracious to existing callers + // that might not know yet that they need to treat root module output + // values in a special way. childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) - childModule.SetOutputValue("pizza", cty.StringVal("hawaiian"), false) + state.SetOutputValue(addrs.OutputValue{Name: "pizza"}.Absolute(childModule.Addr), cty.StringVal("hawaiian"), false) multiModA := state.EnsureModule(addrs.RootModuleInstance.Child("multi", addrs.StringKey("a"))) - multiModA.SetOutputValue("pizza", cty.StringVal("cheese"), false) + state.SetOutputValue(addrs.OutputValue{Name: "pizza"}.Absolute(multiModA.Addr), cty.StringVal("cheese"), false) multiModB := state.EnsureModule(addrs.RootModuleInstance.Child("multi", addrs.StringKey("b"))) - multiModB.SetOutputValue("pizza", cty.StringVal("sausage"), false) + state.SetOutputValue(addrs.OutputValue{Name: "pizza"}.Absolute(multiModB.Addr), cty.StringVal("sausage"), false) want := &State{ - Modules: map[string]*Module{ - "": { - Addr: addrs.RootModuleInstance, - LocalValues: map[string]cty.Value{ - "foo": cty.StringVal("foo value"), - }, - OutputValues: map[string]*OutputValue{ - "bar": { - Addr: addrs.AbsOutputValue{ - OutputValue: addrs.OutputValue{ - Name: "bar", - }, - }, - Value: cty.StringVal("bar value"), - Sensitive: false, + RootOutputValues: map[string]*OutputValue{ + "bar": { + Addr: addrs.AbsOutputValue{ + OutputValue: addrs.OutputValue{ + Name: "bar", }, - "secret": { - Addr: addrs.AbsOutputValue{ - OutputValue: addrs.OutputValue{ - Name: "secret", - }, - }, - Value: cty.StringVal("secret value"), - Sensitive: true, + }, + Value: cty.StringVal("bar value"), + Sensitive: false, + }, + "secret": { + Addr: addrs.AbsOutputValue{ + OutputValue: addrs.OutputValue{ + Name: "secret", }, }, + Value: cty.StringVal("secret value"), + Sensitive: true, + }, + }, + + Modules: map[string]*Module{ + "": { + Addr: addrs.RootModuleInstance, Resources: map[string]*Resource{ "test_thing.baz": { Addr: addrs.Resource{ @@ -107,54 +116,15 @@ func TestState(t *testing.T) { }, }, "module.child": { - Addr: addrs.RootModuleInstance.Child("child", addrs.NoKey), - LocalValues: map[string]cty.Value{}, - OutputValues: map[string]*OutputValue{ - "pizza": { - Addr: addrs.AbsOutputValue{ - Module: addrs.RootModuleInstance.Child("child", addrs.NoKey), - OutputValue: addrs.OutputValue{ - Name: "pizza", - }, - }, - Value: cty.StringVal("hawaiian"), - Sensitive: false, - }, - }, + Addr: addrs.RootModuleInstance.Child("child", addrs.NoKey), Resources: map[string]*Resource{}, }, `module.multi["a"]`: { - Addr: addrs.RootModuleInstance.Child("multi", addrs.StringKey("a")), - LocalValues: map[string]cty.Value{}, - OutputValues: map[string]*OutputValue{ - "pizza": { - Addr: addrs.AbsOutputValue{ - Module: addrs.RootModuleInstance.Child("multi", addrs.StringKey("a")), - OutputValue: addrs.OutputValue{ - Name: "pizza", - }, - }, - Value: cty.StringVal("cheese"), - Sensitive: false, - }, - }, + Addr: addrs.RootModuleInstance.Child("multi", addrs.StringKey("a")), Resources: map[string]*Resource{}, }, `module.multi["b"]`: { - Addr: addrs.RootModuleInstance.Child("multi", addrs.StringKey("b")), - LocalValues: map[string]cty.Value{}, - OutputValues: map[string]*OutputValue{ - "pizza": { - Addr: addrs.AbsOutputValue{ - Module: addrs.RootModuleInstance.Child("multi", addrs.StringKey("b")), - OutputValue: addrs.OutputValue{ - Name: "pizza", - }, - }, - Value: cty.StringVal("sausage"), - Sensitive: false, - }, - }, + Addr: addrs.RootModuleInstance.Child("multi", addrs.StringKey("b")), Resources: map[string]*Resource{}, }, }, @@ -173,27 +143,8 @@ func TestState(t *testing.T) { }() } - for _, problem := range deep.Equal(state, want) { - t.Error(problem) - } - - expectedOutputs := map[string]string{ - `module.multi["a"].output.pizza`: "cheese", - `module.multi["b"].output.pizza`: "sausage", - } - - for _, o := range state.ModuleOutputs(addrs.RootModuleInstance, addrs.ModuleCall{Name: "multi"}) { - addr := o.Addr.String() - expected := expectedOutputs[addr] - delete(expectedOutputs, addr) - - if expected != o.Value.AsString() { - t.Fatalf("expected %q:%q, got %q", addr, expected, o.Value.AsString()) - } - } - - for addr, o := range expectedOutputs { - t.Fatalf("missing output %q:%q", addr, o) + if diff := cmp.Diff(want.String(), state.String()); diff != "" { + t.Errorf("wrong result\n%s", diff) } } @@ -231,9 +182,14 @@ func TestStateDeepCopy(t *testing.T) { t.Errorf("root module is nil; want valid object") } - rootModule.SetLocalValue("foo", cty.StringVal("foo value")) - rootModule.SetOutputValue("bar", cty.StringVal("bar value"), false) - rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true) + state.SetOutputValue( + addrs.OutputValue{Name: "bar"}.Absolute(rootModule.Addr), + cty.StringVal("bar value"), false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "secret"}.Absolute(rootModule.Addr), + cty.StringVal("secret value"), true, + ) rootModule.SetResourceInstanceCurrent( addrs.Resource{ Mode: addrs.ManagedResourceMode, @@ -288,8 +244,7 @@ func TestStateDeepCopy(t *testing.T) { }, ) - childModule := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) - childModule.SetOutputValue("pizza", cty.StringVal("hawaiian"), false) + state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) stateCopy := state.DeepCopy() if !state.Equal(stateCopy) { diff --git a/internal/states/statefile/version4.go b/internal/states/statefile/version4.go index 52939e8cb896..f3b21c6028b1 100644 --- a/internal/states/statefile/version4.go +++ b/internal/states/statefile/version4.go @@ -260,7 +260,6 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) { // need to reload them now. (For descendent modules we just re-calculate // them based on the latest configuration on each run.) { - rootModule := state.RootModule() for name, fos := range sV4.RootOutputs { os := &states.OutputValue{ Addr: addrs.AbsOutputValue{ @@ -292,7 +291,7 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) { } os.Value = val - rootModule.OutputValues[name] = os + state.RootOutputValues[name] = os } } @@ -338,7 +337,7 @@ func writeStateV4(file *File, w io.Writer) tfdiags.Diagnostics { Resources: []resourceStateV4{}, } - for name, os := range file.State.RootModule().OutputValues { + for name, os := range file.State.RootOutputValues { src, err := ctyjson.Marshal(os.Value, os.Value.Type()) if err != nil { diags = diags.Append(tfdiags.Sourceless( diff --git a/internal/states/statemgr/filesystem.go b/internal/states/statemgr/filesystem.go index a69a48cff4c2..42ea8b46319e 100644 --- a/internal/states/statemgr/filesystem.go +++ b/internal/states/statemgr/filesystem.go @@ -248,7 +248,7 @@ func (s *Filesystem) GetRootOutputValues() (map[string]*states.OutputValue, erro state = states.NewState() } - return state.RootModule().OutputValues, nil + return state.RootOutputValues, nil } func (s *Filesystem) refreshState() error { diff --git a/internal/states/statemgr/statemgr_fake.go b/internal/states/statemgr/statemgr_fake.go index db12945b5316..11eb8ebbf1ed 100644 --- a/internal/states/statemgr/statemgr_fake.go +++ b/internal/states/statemgr/statemgr_fake.go @@ -70,7 +70,7 @@ func (m *fakeFull) PersistState(schemas *terraform.Schemas) error { } func (m *fakeFull) GetRootOutputValues() (map[string]*states.OutputValue, error) { - return m.State().RootModule().OutputValues, nil + return m.State().RootOutputValues, nil } func (m *fakeFull) Lock(info *LockInfo) (string, error) { diff --git a/internal/states/statemgr/testing.go b/internal/states/statemgr/testing.go index d002a95b35bf..1174cb293022 100644 --- a/internal/states/statemgr/testing.go +++ b/internal/states/statemgr/testing.go @@ -48,7 +48,10 @@ func TestFull(t *testing.T, s Full) { current := s.State() // Write a new state and verify that we have it - current.RootModule().SetOutputValue("bar", cty.StringVal("baz"), false) + current.SetOutputValue( + addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("baz"), false, + ) if err := s.WriteState(current); err != nil { t.Fatalf("err: %s", err) @@ -101,9 +104,11 @@ func TestFull(t *testing.T, s Full) { // Change the serial current = current.DeepCopy() - current.EnsureModule(addrs.RootModuleInstance).SetOutputValue( - "serialCheck", cty.StringVal("true"), false, + current.SetOutputValue( + addrs.OutputValue{Name: "serialCheck"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("true"), false, ) + if err := s.WriteState(current); err != nil { t.Fatalf("err: %s", err) } @@ -159,8 +164,14 @@ func TestFullInitialState() *states.State { } childMod.SetResourceProvider(rAddr, providerAddr) - state.RootModule().SetOutputValue("sensitive_output", cty.StringVal("it's a secret"), true) - state.RootModule().SetOutputValue("nonsensitive_output", cty.StringVal("hello, world!"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "sensitive_output"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("it's a secret"), true, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "nonsensitive_output"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("hello, world!"), false, + ) return state } diff --git a/internal/states/sync.go b/internal/states/sync.go index b82af1c10f25..ec8bf45dbe6f 100644 --- a/internal/states/sync.go +++ b/internal/states/sync.go @@ -52,18 +52,6 @@ func (s *SyncState) Module(addr addrs.ModuleInstance) *Module { return ret } -// ModuleOutputs returns the set of OutputValues that matches the given path. -func (s *SyncState) ModuleOutputs(parentAddr addrs.ModuleInstance, module addrs.ModuleCall) []*OutputValue { - s.lock.RLock() - defer s.lock.RUnlock() - var os []*OutputValue - - for _, o := range s.state.ModuleOutputs(parentAddr, module) { - os = append(os, o.DeepCopy()) - } - return os -} - // RemoveModule removes the entire state for the given module, taking with // it any resources associated with the module. This should generally be // called only for modules whose resources have all been destroyed, but @@ -90,71 +78,33 @@ func (s *SyncState) OutputValue(addr addrs.AbsOutputValue) *OutputValue { // SetOutputValue writes a given output value into the state, overwriting // any existing value of the same name. // -// If the module containing the output is not yet tracked in state then it -// be added as a side-effect. +// The state only tracks output values for the root module, so attempts to +// write output values for any other module will be quietly ignored. func (s *SyncState) SetOutputValue(addr addrs.AbsOutputValue, value cty.Value, sensitive bool) { + if !addr.Module.IsRoot() { + return + } + s.lock.Lock() defer s.lock.Unlock() - ms := s.state.EnsureModule(addr.Module) - ms.SetOutputValue(addr.OutputValue.Name, value, sensitive) + s.state.SetOutputValue(addr, value, sensitive) } // RemoveOutputValue removes the stored value for the output value with the // given address. // -// If this results in its containing module being empty, the module will be -// pruned from the state as a side-effect. +// The state only tracks output values for the root module, so attempts to +// remove output values for any other module will be quietly ignored. func (s *SyncState) RemoveOutputValue(addr addrs.AbsOutputValue) { - s.lock.Lock() - defer s.lock.Unlock() - - ms := s.state.Module(addr.Module) - if ms == nil { + if !addr.Module.IsRoot() { return } - ms.RemoveOutputValue(addr.OutputValue.Name) - s.maybePruneModule(addr.Module) -} -// LocalValue returns the current value associated with the given local value -// address. -func (s *SyncState) LocalValue(addr addrs.AbsLocalValue) cty.Value { - s.lock.RLock() - // cty.Value is immutable, so we don't need any extra copying here. - ret := s.state.LocalValue(addr) - s.lock.RUnlock() - return ret -} - -// SetLocalValue writes a given output value into the state, overwriting -// any existing value of the same name. -// -// If the module containing the local value is not yet tracked in state then it -// will be added as a side-effect. -func (s *SyncState) SetLocalValue(addr addrs.AbsLocalValue, value cty.Value) { - s.lock.Lock() - defer s.lock.Unlock() - - ms := s.state.EnsureModule(addr.Module) - ms.SetLocalValue(addr.LocalValue.Name, value) -} - -// RemoveLocalValue removes the stored value for the local value with the -// given address. -// -// If this results in its containing module being empty, the module will be -// pruned from the state as a side-effect. -func (s *SyncState) RemoveLocalValue(addr addrs.AbsLocalValue) { s.lock.Lock() defer s.lock.Unlock() - ms := s.state.Module(addr.Module) - if ms == nil { - return - } - ms.RemoveLocalValue(addr.LocalValue.Name) - s.maybePruneModule(addr.Module) + s.state.RemoveOutputValue(addr) } // Resource returns a snapshot of the state of the resource with the given diff --git a/internal/terraform/context_apply2_test.go b/internal/terraform/context_apply2_test.go index a7f1929e9055..72590c4173dc 100644 --- a/internal/terraform/context_apply2_test.go +++ b/internal/terraform/context_apply2_test.go @@ -621,7 +621,7 @@ func TestContext2Apply_nullableVariables(t *testing.T) { t.Fatalf("apply: %s", diags.Err()) } - outputs := state.Module(addrs.RootModuleInstance).OutputValues + outputs := state.RootOutputValues // we check for null outputs be seeing that they don't exists if _, ok := outputs["nullable_null_default"]; ok { t.Error("nullable_null_default: expected no output value") @@ -1686,7 +1686,10 @@ output "from_resource" { }, mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), ) - mod.SetOutputValue("from_resource", cty.StringVal("wrong val"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "from_resource"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("wrong val"), false, + ) ctx := testContext2(t, &ContextOpts{ Providers: map[addrs.Provider]providers.Factory{ @@ -2269,16 +2272,27 @@ locals { t.Errorf("expected no errors, but got %s", diags) } - state, diags := ctx.Apply(plan, m, nil) - if diags.HasErrors() { - t.Errorf("expected no errors, but got %s", diags) + g, _, diags := ctx.applyGraph(plan, m, &ApplyOpts{}, true) + // The local value should've been pruned from the graph because nothing + // refers to it. + gotGraph := g.String() + wantGraph := `provider["registry.terraform.io/hashicorp/test"] +provider["registry.terraform.io/hashicorp/test"] (close) + test_object.a +root + provider["registry.terraform.io/hashicorp/test"] (close) +test_object.a + test_object.a (expand) +test_object.a (expand) + provider["registry.terraform.io/hashicorp/test"] +` + if diff := cmp.Diff(wantGraph, gotGraph); diff != "" { + t.Errorf("wrong apply graph\n%s", diff) } - // We didn't specify any external references, so the unreferenced local - // value should have been tidied up and never made it into the state. - module := state.RootModule() - if len(module.LocalValues) > 0 { - t.Errorf("expected no local values in the state but found %d", len(module.LocalValues)) + _, diags = ctx.Apply(plan, m, nil) + if diags.HasErrors() { + t.Errorf("expected no errors, but got %s", diags) } } @@ -2312,17 +2326,36 @@ locals { t.Errorf("expected no errors, but got %s", diags) } - state, diags := ctx.Apply(plan, m, nil) + g, _, diags := ctx.applyGraph(plan, m, &ApplyOpts{}, true) if diags.HasErrors() { t.Errorf("expected no errors, but got %s", diags) } - // We did specify the local value in the external references, so it should - // have been preserved even though it is not referenced by anything directly - // in the config. - module := state.RootModule() - if module.LocalValues["local_value"].AsString() != "foo" { - t.Errorf("expected local value to be \"foo\" but was \"%s\"", module.LocalValues["local_value"].AsString()) + // The local value should remain in the graph because the external + // reference uses it. + gotGraph := g.String() + wantGraph := ` + local.local_value (expand) +local.local_value (expand) + test_object.a +provider["registry.terraform.io/hashicorp/test"] +provider["registry.terraform.io/hashicorp/test"] (close) + test_object.a +root + + provider["registry.terraform.io/hashicorp/test"] (close) +test_object.a + test_object.a (expand) +test_object.a (expand) + provider["registry.terraform.io/hashicorp/test"] +` + if diff := cmp.Diff(wantGraph, gotGraph); diff != "" { + t.Errorf("wrong graph\n%s", diff) + } + + _, diags = ctx.Apply(plan, m, nil) + if diags.HasErrors() { + t.Errorf("expected no errors, but got %s", diags) } } diff --git a/internal/terraform/context_apply_test.go b/internal/terraform/context_apply_test.go index 6bbc13372f48..81d61cebd774 100644 --- a/internal/terraform/context_apply_test.go +++ b/internal/terraform/context_apply_test.go @@ -717,10 +717,7 @@ module.test: null_resource.noop: ID = foo provider = provider["registry.terraform.io/hashicorp/null"] - - Outputs: - - amis_out = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 }`) +`) if actual != expected { t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual) } @@ -3296,10 +3293,6 @@ module.A: provider = provider["registry.terraform.io/hashicorp/aws"] foo = bar type = aws_instance - - Outputs: - - value = foo module.B: aws_instance.bar: ID = foo @@ -3605,7 +3598,7 @@ func TestContext2Apply_multiVar(t *testing.T) { t.Fatalf("diags: %s", diags.Err()) } - actual := state.RootModule().OutputValues["output"] + actual := state.RootOutputValues["output"] expected := cty.StringVal("bar0,bar1,bar2") if actual == nil || actual.Value != expected { t.Fatalf("wrong value\ngot: %#v\nwant: %#v", actual.Value, expected) @@ -3639,7 +3632,7 @@ func TestContext2Apply_multiVar(t *testing.T) { t.Logf("End state: %s", state.String()) - actual := state.RootModule().OutputValues["output"] + actual := state.RootOutputValues["output"] if actual == nil { t.Fatal("missing output") } @@ -3846,7 +3839,7 @@ func TestContext2Apply_multiVarComprehensive(t *testing.T) { }, } got := map[string]interface{}{} - for k, s := range state.RootModule().OutputValues { + for k, s := range state.RootOutputValues { got[k] = hcl2shim.ConfigValueFromHCL2(s.Value) } if !reflect.DeepEqual(got, want) { @@ -3882,7 +3875,7 @@ func TestContext2Apply_multiVarOrder(t *testing.T) { t.Logf("State: %s", state.String()) - actual := state.RootModule().OutputValues["should-be-11"] + actual := state.RootOutputValues["should-be-11"] expected := cty.StringVal("index-11") if actual == nil || actual.Value != expected { t.Fatalf("wrong value\ngot: %#v\nwant: %#v", actual.Value, expected) @@ -3913,7 +3906,7 @@ func TestContext2Apply_multiVarOrderInterp(t *testing.T) { t.Logf("State: %s", state.String()) - actual := state.RootModule().OutputValues["should-be-11"] + actual := state.RootOutputValues["should-be-11"] expected := cty.StringVal("baz-index-11") if actual == nil || actual.Value != expected { t.Fatalf("wrong value\ngot: %#v\nwant: %#v", actual.Value, expected) @@ -4070,9 +4063,14 @@ func TestContext2Apply_outputOrphan(t *testing.T) { p.PlanResourceChangeFn = testDiffFn state := states.NewState() - root := state.EnsureModule(addrs.RootModuleInstance) - root.SetOutputValue("foo", cty.StringVal("bar"), false) - root.SetOutputValue("bar", cty.StringVal("baz"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) + state.SetOutputValue( + addrs.OutputValue{Name: "bar"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("baz"), false, + ) ctx := testContext2(t, &ContextOpts{ Providers: map[addrs.Provider]providers.Factory{ @@ -7158,7 +7156,10 @@ func TestContext2Apply_targetedDestroy(t *testing.T) { }, mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), ) - root.SetOutputValue("out", cty.StringVal("bar"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "out"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) child.SetResourceInstanceCurrent( @@ -7217,8 +7218,8 @@ func TestContext2Apply_targetedDestroy(t *testing.T) { // TODO: Future refactoring may enable us to remove the output from state in // this case, and that would be Just Fine - this test can be modified to // expect 0 outputs. - if len(mod.OutputValues) != 1 { - t.Fatalf("expected 1 outputs, got: %#v", mod.OutputValues) + if len(state.RootOutputValues) != 1 { + t.Fatalf("expected 1 outputs, got: %#v", state.RootOutputValues) } // the module instance should remain @@ -7521,6 +7522,7 @@ func TestContext2Apply_targetedModuleDep(t *testing.T) { t.Fatalf("diags: %s", diags.Err()) } + // The output from module.child is copied into aws_instance.foo.foo checkStateString(t, state, ` aws_instance.foo: ID = foo @@ -7536,11 +7538,7 @@ module.child: ID = foo provider = provider["registry.terraform.io/hashicorp/aws"] type = aws_instance - - Outputs: - - output = foo - `) +`) } // GH-10911 untargeted outputs should not be in the graph, and therefore @@ -7588,10 +7586,6 @@ module.child2: ID = foo provider = provider["registry.terraform.io/hashicorp/aws"] type = aws_instance - - Outputs: - - instance_id = foo `) } @@ -8667,7 +8661,7 @@ func TestContext2Apply_terraformWorkspace(t *testing.T) { t.Fatalf("diags: %s", diags.Err()) } - actual := state.RootModule().OutputValues["output"] + actual := state.RootOutputValues["output"] expected := cty.StringVal("foo") if actual == nil || actual.Value != expected { t.Fatalf("wrong value\ngot: %#v\nwant: %#v", actual.Value, expected) @@ -8786,7 +8780,10 @@ func TestContext2Apply_destroyWithLocals(t *testing.T) { }, mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), ) - root.SetOutputValue("name", cty.StringVal("test-bar"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "name"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("test-bar"), false, + ) ctx := testContext2(t, &ContextOpts{ Providers: map[addrs.Provider]providers.Factory{ @@ -9094,7 +9091,10 @@ func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) { }, mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), ) - root.SetOutputValue("out", cty.ListVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("foo")}), false) + state.SetOutputValue( + addrs.OutputValue{Name: "out"}.Absolute(addrs.RootModuleInstance), + cty.ListVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("foo")}), false, + ) ctx := testContext2(t, &ContextOpts{ Providers: providers, @@ -10833,6 +10833,14 @@ module "mod2" { source = "./mod" in = module.mod1["a"].out } + +output "mod1" { + value = module.mod1 +} + +output "mod2" { + value = module.mod2 +} `, "mod/main.tf": ` resource "aws_instance" "foo" { @@ -10870,16 +10878,17 @@ output "out" { } expected := ` +Outputs: + +mod1 = {a:map[out:foo] } +mod2 = {out:foo } + module.mod1["a"]: aws_instance.foo: ID = foo provider = provider["registry.terraform.io/hashicorp/aws"] foo = default type = aws_instance - - Outputs: - - out = foo module.mod2: aws_instance.foo: ID = foo @@ -11317,7 +11326,7 @@ locals { } // check the output, as those can't cause an error planning the value - out := state.RootModule().OutputValues["out"].Value.AsString() + out := state.RootOutputValues["out"].Value.AsString() if out != "a0" { t.Fatalf(`expected output "a0", got: %q`, out) } @@ -11372,7 +11381,7 @@ locals { } // check the output, as those can't cause an error planning the value - out = state.RootModule().OutputValues["out"].Value.AsString() + out = state.RootOutputValues["out"].Value.AsString() if out != "" { t.Fatalf(`expected output "", got: %q`, out) } @@ -12212,7 +12221,7 @@ output "out" { t.Fatal(diags.ErrWithWarnings()) } - got := state.RootModule().OutputValues["out"].Value + got := state.RootOutputValues["out"].Value want := cty.ObjectVal(map[string]cty.Value{ "required": cty.StringVal("boop"), @@ -12271,7 +12280,7 @@ output "out" { t.Fatal(diags.ErrWithWarnings()) } - got := state.RootModule().OutputValues["out"].Value + got := state.RootOutputValues["out"].Value want := cty.ObjectVal(map[string]cty.Value{ "required": cty.StringVal("boop"), @@ -12321,7 +12330,7 @@ output "out" { t.Fatal(diags.ErrWithWarnings()) } - got := state.RootModule().OutputValues["out"].Value + got := state.RootOutputValues["out"].Value // The null default value should be bound, after type converting to the // full object type want := cty.TupleVal([]cty.Value{cty.NullVal(cty.Object(map[string]cty.Type{ @@ -12384,7 +12393,7 @@ output "out" { t.Fatal(diags.ErrWithWarnings()) } - got := state.RootModule().OutputValues["out"].Value + got := state.RootOutputValues["out"].Value want := cty.ListVal([]cty.Value{ cty.ObjectVal(map[string]cty.Value{ "a": cty.SetVal([]cty.Value{cty.StringVal("foo")}), diff --git a/internal/terraform/context_plan2_test.go b/internal/terraform/context_plan2_test.go index 6177883c29c1..98bb4336a372 100644 --- a/internal/terraform/context_plan2_test.go +++ b/internal/terraform/context_plan2_test.go @@ -4234,6 +4234,10 @@ resource "test_object" "a" { locals { local_value = test_object.a.test_string } + +output "from_local_value" { + value = local.local_value +} `, }) @@ -4253,20 +4257,20 @@ locals { module := state.RootModule() // So, the original state shouldn't have been updated at all. - if len(module.LocalValues) > 0 { - t.Errorf("expected no local values in the state but found %d", len(module.LocalValues)) + if len(state.RootOutputValues) > 0 { + t.Errorf("expected no root output values in the state but found %d", len(state.RootOutputValues)) } if len(module.Resources) > 0 { - t.Errorf("expected no resources in the state but found %d", len(module.LocalValues)) + t.Errorf("expected no resources in the state but found %d", len(module.Resources)) } // But, this makes it hard for the testing framework to valid things about // the returned plan. So, the plan contains the planned state: module = plan.PlannedState.RootModule() - if module.LocalValues["local_value"].AsString() != "foo" { - t.Errorf("expected local value to be \"foo\" but was \"%s\"", module.LocalValues["local_value"].AsString()) + if got, want := plan.PlannedState.RootOutputValues["from_local_value"].Value.AsString(), "foo"; got != want { + t.Errorf("expected local value to be %q but was %q", want, got) } if module.ResourceInstance(addr.Resource).Current.Status != states.ObjectPlanned { diff --git a/internal/terraform/context_plan_test.go b/internal/terraform/context_plan_test.go index 52456e3f4100..16d1d37b10f9 100644 --- a/internal/terraform/context_plan_test.go +++ b/internal/terraform/context_plan_test.go @@ -2248,25 +2248,6 @@ func TestContext2Plan_countComputed(t *testing.T) { } } -func TestContext2Plan_countComputedModule(t *testing.T) { - m := testModule(t, "plan-count-computed-module") - p := testProvider("aws") - p.PlanResourceChangeFn = testDiffFn - ctx := testContext2(t, &ContextOpts{ - Providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), - }, - }) - - _, err := ctx.Plan(m, states.NewState(), DefaultPlanOpts) - - expectedErr := `The "count" value depends on resource attributes` - if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) { - t.Fatalf("expected err would contain %q\nerr: %s\n", - expectedErr, err) - } -} - func TestContext2Plan_countModuleStatic(t *testing.T) { m := testModule(t, "plan-count-module-static") p := testProvider("aws") @@ -3089,48 +3070,6 @@ func TestContext2Plan_forEach(t *testing.T) { } } -func TestContext2Plan_forEachUnknownValue(t *testing.T) { - // This module has a variable defined, but it's value is unknown. We - // expect this to produce an error, but not to panic. - m := testModule(t, "plan-for-each-unknown-value") - p := testProvider("aws") - ctx := testContext2(t, &ContextOpts{ - Providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), - }, - }) - - _, diags := ctx.Plan(m, states.NewState(), &PlanOpts{ - Mode: plans.NormalMode, - SetVariables: InputValues{ - "foo": { - Value: cty.UnknownVal(cty.String), - SourceType: ValueFromCLIArg, - }, - }, - }) - if !diags.HasErrors() { - // Should get this error: - // Invalid for_each argument: The "for_each" value depends on resource attributes that cannot be determined until apply... - t.Fatal("succeeded; want errors") - } - - gotErrStr := diags.Err().Error() - wantErrStr := "Invalid for_each argument" - if !strings.Contains(gotErrStr, wantErrStr) { - t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErrStr, wantErrStr) - } - - // We should have a diagnostic that is marked as being caused by unknown - // values. - for _, diag := range diags { - if tfdiags.DiagnosticCausedByUnknown(diag) { - return // don't fall through to the error below - } - } - t.Fatalf("no diagnostic is marked as being caused by unknown\n%s", diags.Err().Error()) -} - func TestContext2Plan_destroy(t *testing.T) { m := testModule(t, "plan-destroy") p := testProvider("aws") @@ -6914,8 +6853,10 @@ output "planned" { ctx := testContext2(t, &ContextOpts{}) state := states.BuildState(func(s *states.SyncState) { - r := s.Module(addrs.RootModuleInstance) - r.SetOutputValue("planned", cty.NullVal(cty.DynamicPseudoType), false) + s.SetOutputValue( + addrs.OutputValue{Name: "planned"}.Absolute(addrs.RootModuleInstance), + cty.NullVal(cty.DynamicPseudoType), false, + ) }) plan, diags := ctx.Plan(m, state, DefaultPlanOpts) if diags.HasErrors() { diff --git a/internal/terraform/context_refresh_test.go b/internal/terraform/context_refresh_test.go index 8e4970160676..7eeec9bda404 100644 --- a/internal/terraform/context_refresh_test.go +++ b/internal/terraform/context_refresh_test.go @@ -721,7 +721,10 @@ func TestContext2Refresh_output(t *testing.T) { state := states.NewState() root := state.EnsureModule(addrs.RootModuleInstance) testSetResourceInstanceCurrent(root, "aws_instance.web", `{"id":"foo","foo":"bar"}`, `provider["registry.terraform.io/hashicorp/aws"]`) - root.SetOutputValue("foo", cty.StringVal("foo"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("foo"), false, + ) ctx := testContext2(t, &ContextOpts{ Providers: map[addrs.Provider]providers.Factory{ diff --git a/internal/terraform/context_walk.go b/internal/terraform/context_walk.go index 30ed5547a500..d78fb7bc1c6d 100644 --- a/internal/terraform/context_walk.go +++ b/internal/terraform/context_walk.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/moduletest/mocking" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/refactoring" @@ -163,6 +164,7 @@ func (c *Context) graphWalker(operation walkOperation, opts *graphWalkOpts) *Con Overrides: opts.Overrides, PrevRunState: prevRunState, Changes: changes.SyncWrapper(), + NamedValues: namedvals.NewState(), Checks: checkState, InstanceExpander: instances.NewExpander(), ExternalProviderConfigs: opts.ExternalProviderConfigs, diff --git a/internal/terraform/eval_context.go b/internal/terraform/eval_context.go index e16d034aef0e..b1fe06a83dd2 100644 --- a/internal/terraform/eval_context.go +++ b/internal/terraform/eval_context.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/moduletest/mocking" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/provisioners" @@ -133,35 +134,10 @@ type EvalContext interface { // addresses in this context. EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope - // SetRootModuleArgument defines the value for one variable of the root - // module. The caller must ensure that given value is a suitable - // "final value" for the variable, which means that it's already converted - // and validated to match any configured constraints and validation rules. - // - // Calling this function multiple times with the same variable address - // will silently overwrite the value provided by a previous call. - SetRootModuleArgument(addrs.InputVariable, cty.Value) - - // SetModuleCallArgument defines the value for one input variable of a - // particular child module call. The caller must ensure that the given - // value is a suitable "final value" for the variable, which means that - // it's already converted and validated to match any configured - // constraints and validation rules. - // - // Calling this function multiple times with the same variable address - // will silently overwrite the value provided by a previous call. - SetModuleCallArgument(addrs.ModuleCallInstance, addrs.InputVariable, cty.Value) - - // GetVariableValue returns the value provided for the input variable with - // the given address, or cty.DynamicVal if the variable hasn't been assigned - // a value yet. - // - // Most callers should deal with variable values only indirectly via - // EvaluationScope and the other expression evaluation functions, but - // this is provided because variables tend to be evaluated outside of - // the context of the module they belong to and so we sometimes need to - // override the normal expression evaluation behavior. - GetVariableValue(addr addrs.AbsInputVariableInstance) cty.Value + // NamedValues returns the object that tracks the gradual evaluation of + // all input variables, local values, and output values during a graph + // walk. + NamedValues() *namedvals.State // Changes returns the writer object that can be used to write new proposed // changes into the global changes set. @@ -211,4 +187,9 @@ type EvalContext interface { // WithPath returns a copy of the context with the internal path set to the // path argument. WithPath(path addrs.ModuleInstance) EvalContext + + // WithPartialExpandedPath is like WithPath but works with a + // partially-expanded path, allowing for speculative evaluation inside + // as-yet-unexpanded modules. + WithPartialExpandedPath(path addrs.PartialExpandedModule) EvalContext } diff --git a/internal/terraform/eval_context_builtin.go b/internal/terraform/eval_context_builtin.go index ccd30f9929c5..f66ad87f5d64 100644 --- a/internal/terraform/eval_context_builtin.go +++ b/internal/terraform/eval_context_builtin.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/moduletest/mocking" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/provisioners" @@ -44,18 +45,23 @@ type BuiltinEvalContext struct { // panic if this is not set. pathSet bool + // PartialPathValue is an alternative to PathValue for situations where + // Terraform is speculating about any possible instances of a module whose + // expansion isn't known. partialPathSet is analogous to pathSet. + // This pair is mutually-exclusive with PathValue/pathSet. The Path + // method will still panic if a partial path is set instead of an exact one, + // but evaluation methods will work and will use a speculative evaluation + // context. + PartialPathValue addrs.PartialExpandedModule + partialPathSet bool + // Evaluator is used for evaluating expressions within the scope of this // eval context. Evaluator *Evaluator - // VariableValues contains the variable values across all modules. This - // structure is shared across the entire containing context, and so it - // may be accessed only when holding VariableValuesLock. - // The keys of the first level of VariableValues are the string - // representations of addrs.ModuleInstance values. The second-level keys - // are variable names within each module instance. - VariableValues map[string]map[string]cty.Value - VariableValuesLock *sync.Mutex + // NamedValuesValue is where we keep the values of already-evaluated input + // variables, local values, and output values. + NamedValuesValue *namedvals.State // Plugins is a library of plugin components (providers and provisioners) // available for use during a graph walk. @@ -92,6 +98,17 @@ func (ctx *BuiltinEvalContext) WithPath(path addrs.ModuleInstance) EvalContext { newCtx := *ctx newCtx.pathSet = true newCtx.PathValue = path + newCtx.partialPathSet = false + newCtx.PartialPathValue = addrs.PartialExpandedModule{} + return &newCtx +} + +func (ctx *BuiltinEvalContext) WithPartialExpandedPath(path addrs.PartialExpandedModule) EvalContext { + newCtx := *ctx + newCtx.pathSet = false + newCtx.PathValue = nil + newCtx.partialPathSet = true + newCtx.PartialPathValue = path return &newCtx } @@ -424,16 +441,21 @@ func (ctx *BuiltinEvalContext) EvaluateReplaceTriggeredBy(expr hcl.Expression, r return ref, replace, diags } -func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope { - if !ctx.pathSet { - panic("context path not set") - } +func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData instances.RepetitionData) *lang.Scope { data := &evaluationStateData{ Evaluator: ctx.Evaluator, - ModulePath: ctx.PathValue, InstanceKeyData: keyData, Operation: ctx.Evaluator.Operation, } + switch { + case ctx.pathSet: + data.ModulePath = ctx.PathValue + case ctx.partialPathSet: + data.PartialExpandedModulePath = ctx.PartialPathValue + data.PartialEval = true + default: + panic("context path not set") + } scope := ctx.Evaluator.Scope(data, self, source) // ctx.PathValue is the path of the module that contains whatever @@ -450,56 +472,17 @@ func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, source } func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance { - if !ctx.pathSet { - panic("context path not set") + if ctx.partialPathSet { + panic(fmt.Sprintf("no module instance path during partial eval of %s", ctx.PartialPathValue)) } - return ctx.PathValue -} - -func (ctx *BuiltinEvalContext) SetRootModuleArgument(addr addrs.InputVariable, v cty.Value) { - ctx.VariableValuesLock.Lock() - defer ctx.VariableValuesLock.Unlock() - - log.Printf("[TRACE] BuiltinEvalContext: Storing final value for variable %s", addr.Absolute(addrs.RootModuleInstance)) - key := addrs.RootModuleInstance.String() - args := ctx.VariableValues[key] - if args == nil { - args = make(map[string]cty.Value) - ctx.VariableValues[key] = args - } - args[addr.Name] = v -} - -func (ctx *BuiltinEvalContext) SetModuleCallArgument(callAddr addrs.ModuleCallInstance, varAddr addrs.InputVariable, v cty.Value) { - ctx.VariableValuesLock.Lock() - defer ctx.VariableValuesLock.Unlock() - if !ctx.pathSet { panic("context path not set") } - - childPath := callAddr.ModuleInstance(ctx.PathValue) - log.Printf("[TRACE] BuiltinEvalContext: Storing final value for variable %s", varAddr.Absolute(childPath)) - key := childPath.String() - args := ctx.VariableValues[key] - if args == nil { - args = make(map[string]cty.Value) - ctx.VariableValues[key] = args - } - args[varAddr.Name] = v + return ctx.PathValue } -func (ctx *BuiltinEvalContext) GetVariableValue(addr addrs.AbsInputVariableInstance) cty.Value { - ctx.VariableValuesLock.Lock() - defer ctx.VariableValuesLock.Unlock() - - modKey := addr.Module.String() - modVars := ctx.VariableValues[modKey] - val, ok := modVars[addr.Variable.Name] - if !ok { - return cty.DynamicVal - } - return val +func (ctx *BuiltinEvalContext) NamedValues() *namedvals.State { + return ctx.NamedValuesValue } func (ctx *BuiltinEvalContext) Changes() *plans.ChangesSync { diff --git a/internal/terraform/eval_context_mock.go b/internal/terraform/eval_context_mock.go index 18d174c4aa81..3813e172c923 100644 --- a/internal/terraform/eval_context_mock.go +++ b/internal/terraform/eval_context_mock.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/moduletest/mocking" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/provisioners" @@ -118,21 +119,11 @@ type MockEvalContext struct { PathCalled bool PathPath addrs.ModuleInstance - SetRootModuleArgumentCalled bool - SetRootModuleArgumentAddr addrs.InputVariable - SetRootModuleArgumentValue cty.Value - SetRootModuleArgumentFunc func(addr addrs.InputVariable, v cty.Value) + WithPartialExpandedPathCalled bool + WithPartialExpandedPathPath addrs.PartialExpandedModule - SetModuleCallArgumentCalled bool - SetModuleCallArgumentModuleCall addrs.ModuleCallInstance - SetModuleCallArgumentVariable addrs.InputVariable - SetModuleCallArgumentValue cty.Value - SetModuleCallArgumentFunc func(callAddr addrs.ModuleCallInstance, varAddr addrs.InputVariable, v cty.Value) - - GetVariableValueCalled bool - GetVariableValueAddr addrs.AbsInputVariableInstance - GetVariableValueValue cty.Value - GetVariableValueFunc func(addr addrs.AbsInputVariableInstance) cty.Value // supersedes GetVariableValueValue + NamedValuesCalled bool + NamedValuesState *namedvals.State ChangesCalled bool ChangesChanges *plans.ChangesSync @@ -346,32 +337,17 @@ func (c *MockEvalContext) Path() addrs.ModuleInstance { return c.PathPath } -func (c *MockEvalContext) SetRootModuleArgument(addr addrs.InputVariable, v cty.Value) { - c.SetRootModuleArgumentCalled = true - c.SetRootModuleArgumentAddr = addr - c.SetRootModuleArgumentValue = v - if c.SetRootModuleArgumentFunc != nil { - c.SetRootModuleArgumentFunc(addr, v) - } -} - -func (c *MockEvalContext) SetModuleCallArgument(callAddr addrs.ModuleCallInstance, varAddr addrs.InputVariable, v cty.Value) { - c.SetModuleCallArgumentCalled = true - c.SetModuleCallArgumentModuleCall = callAddr - c.SetModuleCallArgumentVariable = varAddr - c.SetModuleCallArgumentValue = v - if c.SetModuleCallArgumentFunc != nil { - c.SetModuleCallArgumentFunc(callAddr, varAddr, v) - } +func (c *MockEvalContext) WithPartialExpandedPath(path addrs.PartialExpandedModule) EvalContext { + c.WithPartialExpandedPathCalled = true + c.WithPartialExpandedPathPath = path + newC := *c + newC.WithPartialExpandedPathPath = path + return &newC } -func (c *MockEvalContext) GetVariableValue(addr addrs.AbsInputVariableInstance) cty.Value { - c.GetVariableValueCalled = true - c.GetVariableValueAddr = addr - if c.GetVariableValueFunc != nil { - return c.GetVariableValueFunc(addr) - } - return c.GetVariableValueValue +func (c *MockEvalContext) NamedValues() *namedvals.State { + c.NamedValuesCalled = true + return c.NamedValuesState } func (c *MockEvalContext) Changes() *plans.ChangesSync { diff --git a/internal/terraform/eval_count.go b/internal/terraform/eval_count.go index 9e2144d9e0f6..be16328ba100 100644 --- a/internal/terraform/eval_count.go +++ b/internal/terraform/eval_count.go @@ -20,35 +20,18 @@ import ( // evaluateCountExpression differs from evaluateCountExpressionValue by // returning an error if the count value is not known, and converting the // cty.Value to an integer. -func evaluateCountExpression(expr hcl.Expression, ctx EvalContext) (int, tfdiags.Diagnostics) { +func evaluateCountExpression(expr hcl.Expression, ctx EvalContext) (v int, known bool, diags tfdiags.Diagnostics) { countVal, diags := evaluateCountExpressionValue(expr, ctx) - if !countVal.IsKnown() { - // Currently this is a rather bad outcome from a UX standpoint, since we have - // no real mechanism to deal with this situation and all we can do is produce - // an error message. - // FIXME: In future, implement a built-in mechanism for deferring changes that - // can't yet be predicted, and use it to guide the user through several - // plan/apply steps until the desired configuration is eventually reached. - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Invalid count argument", - Detail: `The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.`, - Subject: expr.Range().Ptr(), - // TODO: Also populate Expression and EvalContext in here, but - // we can't easily do that right now because the hcl.EvalContext - // (which is not the same as the ctx we have in scope here) is - // hidden away inside evaluateCountExpressionValue. - Extra: diagnosticCausedByUnknown(true), - }) + if !countVal.IsKnown() { + return -1, false, diags } - - if countVal.IsNull() || !countVal.IsKnown() { - return -1, diags + if countVal.IsNull() { + return -1, true, diags } count, _ := countVal.AsBigFloat().Int64() - return int(count), diags + return int(count), true, diags } // evaluateCountExpressionValue is like evaluateCountExpression diff --git a/internal/terraform/eval_count_test.go b/internal/terraform/eval_count_test.go index 74bcfbdf721d..8c97ebf33691 100644 --- a/internal/terraform/eval_count_test.go +++ b/internal/terraform/eval_count_test.go @@ -18,21 +18,29 @@ func TestEvaluateCountExpression(t *testing.T) { tests := map[string]struct { Expr hcl.Expression Count int + Known bool }{ "zero": { hcltest.MockExprLiteral(cty.NumberIntVal(0)), 0, + true, }, "expression with marked value": { hcltest.MockExprLiteral(cty.NumberIntVal(8).Mark(marks.Sensitive)), 8, + true, + }, + "unknown value": { + hcltest.MockExprLiteral(cty.UnknownVal(cty.Number)), + -1, + false, }, } for name, test := range tests { t.Run(name, func(t *testing.T) { ctx := &MockEvalContext{} ctx.installSimpleEval() - countVal, diags := evaluateCountExpression(test.Expr, ctx) + countVal, known, diags := evaluateCountExpression(test.Expr, ctx) if len(diags) != 0 { t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) @@ -44,6 +52,9 @@ func TestEvaluateCountExpression(t *testing.T) { spew.Sdump(countVal), spew.Sdump(test.Count), ) } + if known != test.Known { + t.Errorf("wrong 'knownness'\ngot: %#v\nwant: %#v", known, test.Known) + } }) } } diff --git a/internal/terraform/eval_for_each.go b/internal/terraform/eval_for_each.go index 3782234e9b0e..0e31179ee95b 100644 --- a/internal/terraform/eval_for_each.go +++ b/internal/terraform/eval_for_each.go @@ -19,7 +19,7 @@ import ( // evaluateForEachExpression differs from evaluateForEachExpressionValue by // returning an error if the count value is not known, and converting the // cty.Value to a map[string]cty.Value for compatibility with other calls. -func evaluateForEachExpression(expr hcl.Expression, ctx EvalContext) (forEach map[string]cty.Value, diags tfdiags.Diagnostics) { +func evaluateForEachExpression(expr hcl.Expression, ctx EvalContext) (forEach map[string]cty.Value, known bool, diags tfdiags.Diagnostics) { return newForEachEvaluator(expr, ctx).ResourceValue() } @@ -54,38 +54,36 @@ type forEachEvaluator struct { // ResourceForEachValue returns a known for_each map[string]cty.Value // appropriate for use within resource expansion. -func (ev *forEachEvaluator) ResourceValue() (map[string]cty.Value, tfdiags.Diagnostics) { +func (ev *forEachEvaluator) ResourceValue() (map[string]cty.Value, bool, tfdiags.Diagnostics) { res := map[string]cty.Value{} // no expression always results in an empty map if ev.expr == nil { - return res, nil + return res, true, nil } forEachVal, diags := ev.Value() if diags.HasErrors() { - return res, diags + return res, true, diags } - // ensure our value is known for use in resource expansion - diags = diags.Append(ev.ensureKnownForResource(forEachVal)) - if diags.HasErrors() { - return res, diags + if !ev.isKnownForResource(forEachVal) { + return nil, false, diags } // validate the for_each value for use in resource expansion diags = diags.Append(ev.validateResource(forEachVal)) if diags.HasErrors() { - return res, diags + return res, true, diags } if forEachVal.IsNull() || !forEachVal.IsKnown() || markSafeLengthInt(forEachVal) == 0 { // we check length, because an empty set returns a nil map which will panic below - return res, diags + return res, true, diags } res = forEachVal.AsValueMap() - return res, diags + return res, true, diags } // ImportValue returns the for_each map for use within an import block, @@ -176,47 +174,19 @@ func (ev *forEachEvaluator) ensureKnownForImport(forEachVal cty.Value) tfdiags.D return diags } -// ensureKnownForResource checks that the value is known within the rules of +// isKnownForResource checks that the value is known within the rules of // resource and module expansion. -func (ev *forEachEvaluator) ensureKnownForResource(forEachVal cty.Value) tfdiags.Diagnostics { - var diags tfdiags.Diagnostics +func (ev *forEachEvaluator) isKnownForResource(forEachVal cty.Value) bool { ty := forEachVal.Type() - const errInvalidUnknownDetailMap = "The \"for_each\" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.\n\nAlternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge." - const errInvalidUnknownDetailSet = "The \"for_each\" set includes values derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource.\n\nWhen working with unknown values in for_each, it's better to use a map value where the keys are defined statically in your configuration and where only the values contain apply-time results.\n\nAlternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge." - - if !forEachVal.IsKnown() { - var detailMsg string - switch { - case ty.IsSetType(): - detailMsg = errInvalidUnknownDetailSet - default: - detailMsg = errInvalidUnknownDetailMap - } - - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Invalid for_each argument", - Detail: detailMsg, - Subject: ev.expr.Range().Ptr(), - Expression: ev.expr, - EvalContext: ev.hclCtx, - Extra: diagnosticCausedByUnknown(true), - }) - return diags - } - if ty.IsSetType() && !forEachVal.IsWhollyKnown() { - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Invalid for_each argument", - Detail: errInvalidUnknownDetailSet, - Subject: ev.expr.Range().Ptr(), - Expression: ev.expr, - EvalContext: ev.hclCtx, - Extra: diagnosticCausedByUnknown(true), - }) + switch { + case !forEachVal.IsKnown(): + return false + case ty.IsSetType() && !forEachVal.IsWhollyKnown(): + return false + default: + return true } - return diags } // ValidateResourceValue is used from validation walks to verify the validity diff --git a/internal/terraform/eval_for_each_test.go b/internal/terraform/eval_for_each_test.go index 3f7717d09015..1c58c0b2e015 100644 --- a/internal/terraform/eval_for_each_test.go +++ b/internal/terraform/eval_for_each_test.go @@ -20,10 +20,12 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { tests := map[string]struct { Expr hcl.Expression ForEachMap map[string]cty.Value + Known bool }{ "empty set": { hcltest.MockExprLiteral(cty.SetValEmpty(cty.String)), map[string]cty.Value{}, + true, }, "multi-value string set": { hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.StringVal("a"), cty.StringVal("b")})), @@ -31,10 +33,12 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { "a": cty.StringVal("a"), "b": cty.StringVal("b"), }, + true, }, "empty map": { hcltest.MockExprLiteral(cty.MapValEmpty(cty.Bool)), map[string]cty.Value{}, + true, }, "map": { hcltest.MockExprLiteral(cty.MapVal(map[string]cty.Value{ @@ -45,6 +49,7 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { "a": cty.BoolVal(true), "b": cty.BoolVal(false), }, + true, }, "map containing unknown values": { hcltest.MockExprLiteral(cty.MapVal(map[string]cty.Value{ @@ -55,6 +60,7 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { "a": cty.UnknownVal(cty.Bool), "b": cty.UnknownVal(cty.Bool), }, + true, }, "map containing sensitive values, but strings are literal": { hcltest.MockExprLiteral(cty.MapVal(map[string]cty.Value{ @@ -65,6 +71,27 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { "a": cty.BoolVal(true).Mark(marks.Sensitive), "b": cty.BoolVal(false), }, + true, + }, + "unknown string set": { + hcltest.MockExprLiteral(cty.UnknownVal(cty.Set(cty.String))), + nil, + false, + }, + "unknown map": { + hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.Bool))), + nil, + false, + }, + "set containing unknown value": { + hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.UnknownVal(cty.String)})), + nil, + false, + }, + "set containing dynamic unknown value": { + hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.UnknownVal(cty.DynamicPseudoType)})), + nil, + false, }, } @@ -72,7 +99,7 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { t.Run(name, func(t *testing.T) { ctx := &MockEvalContext{} ctx.installSimpleEval() - forEachMap, diags := evaluateForEachExpression(test.Expr, ctx) + forEachMap, known, diags := evaluateForEachExpression(test.Expr, ctx) if len(diags) != 0 { t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) @@ -84,7 +111,9 @@ func TestEvaluateForEachExpression_valid(t *testing.T) { spew.Sdump(forEachMap), spew.Sdump(test.ForEachMap), ) } - + if known != test.Known { + t.Errorf("wrong 'knownness'\ngot: %#v\nwant: %#v", known, test.Known) + } }) } } @@ -119,18 +148,6 @@ func TestEvaluateForEachExpression_errors(t *testing.T) { "must be a map, or set of strings, and you have provided a value of type tuple", false, false, }, - "unknown string set": { - hcltest.MockExprLiteral(cty.UnknownVal(cty.Set(cty.String))), - "Invalid for_each argument", - "set includes values derived from resource attributes that cannot be determined until apply", - true, false, - }, - "unknown map": { - hcltest.MockExprLiteral(cty.UnknownVal(cty.Map(cty.Bool))), - "Invalid for_each argument", - "map includes keys derived from resource attributes that cannot be determined until apply", - true, false, - }, "marked map": { hcltest.MockExprLiteral(cty.MapVal(map[string]cty.Value{ "a": cty.BoolVal(true), @@ -152,18 +169,6 @@ func TestEvaluateForEachExpression_errors(t *testing.T) { "must not contain null values", false, false, }, - "set containing unknown value": { - hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.UnknownVal(cty.String)})), - "Invalid for_each argument", - "set includes values derived from resource attributes that cannot be determined until apply", - true, false, - }, - "set containing dynamic unknown value": { - hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.UnknownVal(cty.DynamicPseudoType)})), - "Invalid for_each argument", - "set includes values derived from resource attributes that cannot be determined until apply", - true, false, - }, "set containing marked values": { hcltest.MockExprLiteral(cty.SetVal([]cty.Value{cty.StringVal("beep").Mark(marks.Sensitive), cty.StringVal("boop")})), "Invalid for_each argument", @@ -176,7 +181,7 @@ func TestEvaluateForEachExpression_errors(t *testing.T) { t.Run(name, func(t *testing.T) { ctx := &MockEvalContext{} ctx.installSimpleEval() - _, diags := evaluateForEachExpression(test.Expr, ctx) + _, _, diags := evaluateForEachExpression(test.Expr, ctx) if len(diags) != 1 { t.Fatalf("got %d diagnostics; want 1", len(diags)) diff --git a/internal/terraform/eval_variable.go b/internal/terraform/eval_variable.go index 625792583911..4e58cfdcd78d 100644 --- a/internal/terraform/eval_variable.go +++ b/internal/terraform/eval_variable.go @@ -223,7 +223,7 @@ func evalVariableValidations(addr addrs.AbsInputVariableInstance, config *config // bypass our usual evaluation machinery here and just produce a minimal // evaluation context containing just the required value, and thus avoid // the problem that ctx's evaluation functions refer to the wrong module. - val := ctx.GetVariableValue(addr) + val := ctx.NamedValues().GetInputVariableValue(addr) if val == cty.NilVal { diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, diff --git a/internal/terraform/eval_variable_test.go b/internal/terraform/eval_variable_test.go index a081119de609..e9edae147c93 100644 --- a/internal/terraform/eval_variable_test.go +++ b/internal/terraform/eval_variable_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform/internal/checks" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/lang/marks" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/tfdiags" ) @@ -1173,12 +1174,8 @@ func TestEvalVariableValidations_jsonErrorMessageEdgeCase(t *testing.T) { // We need a minimal scope to allow basic functions to be passed to // the HCL scope ctx.EvaluationScopeScope = &lang.Scope{} - ctx.GetVariableValueFunc = func(addr addrs.AbsInputVariableInstance) cty.Value { - if got, want := addr.String(), varAddr.String(); got != want { - t.Errorf("incorrect argument to GetVariableValue: got %s, want %s", got, want) - } - return test.given - } + ctx.NamedValuesState = namedvals.NewState() + ctx.NamedValuesState.SetInputVariableValue(varAddr, test.given) ctx.ChecksState = checks.NewState(cfg) ctx.ChecksState.ReportCheckableObjects(varAddr.ConfigCheckable(), addrs.MakeSet[addrs.Checkable](varAddr)) @@ -1326,15 +1323,11 @@ variable "bar" { // We need a minimal scope to allow basic functions to be passed to // the HCL scope ctx.EvaluationScopeScope = &lang.Scope{} - ctx.GetVariableValueFunc = func(addr addrs.AbsInputVariableInstance) cty.Value { - if got, want := addr.String(), varAddr.String(); got != want { - t.Errorf("incorrect argument to GetVariableValue: got %s, want %s", got, want) - } - if varCfg.Sensitive { - return test.given.Mark(marks.Sensitive) - } else { - return test.given - } + ctx.NamedValuesState = namedvals.NewState() + if varCfg.Sensitive { + ctx.NamedValuesState.SetInputVariableValue(varAddr, test.given.Mark(marks.Sensitive)) + } else { + ctx.NamedValuesState.SetInputVariableValue(varAddr, test.given) } ctx.ChecksState = checks.NewState(cfg) ctx.ChecksState.ReportCheckableObjects(varAddr.ConfigCheckable(), addrs.MakeSet[addrs.Checkable](varAddr)) diff --git a/internal/terraform/evaluate.go b/internal/terraform/evaluate.go index 8cf9fe771e7a..68c265fc1216 100644 --- a/internal/terraform/evaluate.go +++ b/internal/terraform/evaluate.go @@ -8,7 +8,6 @@ import ( "log" "os" "path/filepath" - "sync" "time" "github.com/hashicorp/hcl/v2" @@ -21,6 +20,7 @@ import ( "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/lang/marks" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/tfdiags" @@ -39,15 +39,16 @@ type Evaluator struct { // Config is the root node in the configuration tree. Config *configs.Config - // VariableValues is a map from variable names to their associated values, - // within the module indicated by ModulePath. VariableValues is modified - // concurrently, and so it must be accessed only while holding - // VariableValuesLock. - // - // The first map level is string representations of addr.ModuleInstance - // values, while the second level is variable names. - VariableValues map[string]map[string]cty.Value - VariableValuesLock *sync.Mutex + // NamedValues is where we keep the values of already-evaluated input + // variables, local values, and output values. + NamedValues *namedvals.State + + // Instances tracks the "expansion" (from one configuration object into + // multiple instances of that object) of modules and resources. Other + // parts of Terraform Core update this object during the graph walk, + // and the evaluator uses it to return correctly-shaped data structures + // representing those expandable objects. + Instances *instances.Expander // Plugins is the library of available plugin components (providers and // provisioners) that we have available to help us evaluate expressions @@ -100,7 +101,16 @@ type evaluationStateData struct { // ModulePath is the path through the dynamic module tree to the module // that references will be resolved relative to. - ModulePath addrs.ModuleInstance + // + // PartialExpandedModulePath is the same but for situations when we're + // doing partial evaluation inside hypothetical instances of a + // not-yet-fully-expanded module. + // + // These two are mutually exclusive, and PartialEval is true when we're + // using PartialExpandedModulePath instead of ModulePath. + ModulePath addrs.ModuleInstance + PartialExpandedModulePath addrs.PartialExpandedModule + PartialEval bool // InstanceKeyData describes the values, if any, that are accessible due // to repetition of a containing object using "count" or "for_each" @@ -114,6 +124,27 @@ type evaluationStateData struct { Operation walkOperation } +func (d *evaluationStateData) staticModulePath() addrs.Module { + if d.PartialEval { + return d.PartialExpandedModulePath.Module() + } else { + return d.ModulePath.Module() + } +} + +func (d *evaluationStateData) modulePathDisplayAddr() string { + var ret string + if d.PartialEval { + ret = d.PartialExpandedModulePath.String() + } else { + ret = d.ModulePath.String() + } + if ret == "" { + return "root module" + } + return ret +} + // InstanceKeyEvalData is the old name for instances.RepetitionData, aliased // here for compatibility. In new code, use instances.RepetitionData instead. type InstanceKeyEvalData = instances.RepetitionData @@ -224,11 +255,11 @@ func (d *evaluationStateData) GetInputVariable(addr addrs.InputVariable, rng tfd // First we'll make sure the requested value is declared in configuration, // so we can produce a nice message if not. - moduleConfig := d.Evaluator.Config.DescendentForInstance(d.ModulePath) + moduleConfig := d.Evaluator.Config.Descendent(d.staticModulePath()) if moduleConfig == nil { // should never happen, since we can't be evaluating in a module // that wasn't mentioned in configuration. - panic(fmt.Sprintf("input variable read from %s, which has no configuration", d.ModulePath)) + panic(fmt.Sprintf("input variable read from %s, which has no configuration", d.modulePathDisplayAddr())) } config := moduleConfig.Module.Variables[addr.Name] @@ -252,8 +283,6 @@ func (d *evaluationStateData) GetInputVariable(addr addrs.InputVariable, rng tfd }) return cty.DynamicVal, diags } - d.Evaluator.VariableValuesLock.Lock() - defer d.Evaluator.VariableValuesLock.Unlock() // During the validate walk, input variables are always unknown so // that we are validating the configuration for all possible input values @@ -276,35 +305,11 @@ func (d *evaluationStateData) GetInputVariable(addr addrs.InputVariable, rng tfd return cty.UnknownVal(config.Type), diags } - moduleAddrStr := d.ModulePath.String() - vals := d.Evaluator.VariableValues[moduleAddrStr] - if vals == nil { - return cty.UnknownVal(config.Type), diags - } - - // d.Evaluator.VariableValues should always contain valid "final values" - // for variables, which is to say that they have already had type - // conversions, validations, and default value handling applied to them. - // Those are the responsibility of the graph notes representing the - // variable declarations. Therefore here we just trust that we already - // have a correct value. - - val, isSet := vals[addr.Name] - if !isSet { - // We should not be able to get here without having a valid value - // for every variable, so this always indicates a bug in either - // the graph builder (not including all the needed nodes) or in - // the graph nodes representing variables. - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: `Reference to unresolved input variable`, - Detail: fmt.Sprintf( - `The final value for %s is missing in Terraform's evaluation context. This is a bug in Terraform; please report it!`, - addr.Absolute(d.ModulePath), - ), - Subject: rng.ToHCL().Ptr(), - }) - val = cty.UnknownVal(config.Type) + var val cty.Value + if d.PartialEval { + val = d.Evaluator.NamedValues.GetInputVariablePlaceholder(addrs.ObjectInPartialExpandedModule(d.PartialExpandedModulePath, addr)) + } else { + val = d.Evaluator.NamedValues.GetInputVariableValue(d.ModulePath.InputVariable(addr.Name)) } // Mark if sensitive @@ -320,11 +325,11 @@ func (d *evaluationStateData) GetLocalValue(addr addrs.LocalValue, rng tfdiags.S // First we'll make sure the requested value is declared in configuration, // so we can produce a nice message if not. - moduleConfig := d.Evaluator.Config.DescendentForInstance(d.ModulePath) + moduleConfig := d.Evaluator.Config.Descendent(d.staticModulePath()) if moduleConfig == nil { // should never happen, since we can't be evaluating in a module // that wasn't mentioned in configuration. - panic(fmt.Sprintf("local value read from %s, which has no configuration", d.ModulePath)) + panic(fmt.Sprintf("local value read from %s, which has no configuration", d.modulePathDisplayAddr())) } config := moduleConfig.Module.Locals[addr.Name] @@ -347,10 +352,11 @@ func (d *evaluationStateData) GetLocalValue(addr addrs.LocalValue, rng tfdiags.S return cty.DynamicVal, diags } - val := d.Evaluator.State.LocalValue(addr.Absolute(d.ModulePath)) - if val == cty.NilVal { - // Not evaluated yet? - val = cty.DynamicVal + var val cty.Value + if d.PartialEval { + val = d.Evaluator.NamedValues.GetLocalValuePlaceholder(addrs.ObjectInPartialExpandedModule(d.PartialExpandedModulePath, addr)) + } else { + val = d.Evaluator.NamedValues.GetLocalValue(addr.Absolute(d.ModulePath)) } return val, diags @@ -361,9 +367,9 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc // Output results live in the module that declares them, which is one of // the child module instances of our current module path. - moduleAddr := d.ModulePath.Module().Child(addr.Name) + moduleAddr := d.staticModulePath().Child(addr.Name) - parentCfg := d.Evaluator.Config.DescendentForInstance(d.ModulePath) + parentCfg := d.Evaluator.Config.Descendent(d.staticModulePath()) callConfig, ok := parentCfg.Module.ModuleCalls[addr.Name] if !ok { diags = diags.Append(&hcl.Diagnostic{ @@ -386,195 +392,153 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc } outputConfigs := moduleConfig.Module.Outputs - // Collect all the relevant outputs that current exist in the state. - // We know the instance path up to this point, and the child module name, - // so we only need to store these by instance key. - stateMap := map[addrs.InstanceKey]map[string]cty.Value{} - for _, output := range d.Evaluator.State.ModuleOutputs(d.ModulePath, addr) { - val := output.Value - if output.Sensitive { - val = val.Mark(marks.Sensitive) + // The module won't be expanded during validation, so we need to return an + // unknown value. This will ensure the types looks correct, since we built + // the objects based on the configuration. + // FIXME: If we arrange for all module calls to have unknown expansion + // during the validate walk then we could avoid this special case by + // entering the d.PartialEval branch below instead, but we've retained + // this special case for now to limit the size of the change that + // introduced the partial evaluation mode. + if d.Operation == walkValidate { + attrTypes := make(map[string]cty.Type, len(outputConfigs)) + for name := range outputConfigs { + attrTypes[name] = cty.DynamicPseudoType } - _, callInstance := output.Addr.Module.CallInstance() - instance, ok := stateMap[callInstance.Key] - if !ok { - instance = map[string]cty.Value{} - stateMap[callInstance.Key] = instance + // While we know the type here and it would be nice to validate whether + // indexes are valid or not, because tuples and objects have fixed + // numbers of elements we can't simply return an unknown value of the + // same type since we have not expanded any instances during + // validation. + // + // In order to validate the expression a little precisely, we'll create + // an unknown map or list here to get more type information. This + // is technically a little incorrect because in all other cases we + // return object types instead of maps and tuple types instead of lists, + // but the validation results don't carry forward into planning so + // this small untruth won't typically hurt anything and gives a little + // more information to the type checker during validation. + ty := cty.Object(attrTypes) + switch { + case callConfig.Count != nil: + return cty.UnknownVal(cty.List(ty)), diags + case callConfig.ForEach != nil: + return cty.UnknownVal(cty.Map(ty)), diags + default: + return cty.UnknownVal(ty), diags } - - instance[output.Addr.OutputValue.Name] = val } - // Get all changes that reside for this module call within our path. - // The change contains the full addr, so we can key these with strings. - changesMap := map[addrs.InstanceKey]map[string]*plans.OutputChangeSrc{} - for _, change := range d.Evaluator.Changes.GetOutputChanges(d.ModulePath, addr) { - _, callInstance := change.Addr.Module.CallInstance() - instance, ok := changesMap[callInstance.Key] - if !ok { - instance = map[string]*plans.OutputChangeSrc{} - changesMap[callInstance.Key] = instance + if d.PartialEval { + // If we are under an unexpanded module then we cannot predict our + // instance keys unless this is a singleton module call, in which + // has it has only one "no-key" instance. + if callConfig.Count != nil || callConfig.ForEach != nil { + // A multi-instance module call appears as an object type or + // tuple type, which means we can't say anything at all about + // the type until we know exactly what the instance keys will be. + // TODO: If we ever support explicitly-type-constrained output + // values like in https://github.com/hashicorp/terraform/pull/31728 + // then we could return unknown values of list of object and map of + // object types here in any case where all of the output values + // are exactly specified, which would then enable better type + // checking of uses in the calling module. + return cty.DynamicVal, diags } - instance[change.Addr.OutputValue.Name] = change - } - - // Build up all the module objects, creating a map of values for each - // module instance. - moduleInstances := map[addrs.InstanceKey]map[string]cty.Value{} - - // create a dummy object type for validation below - unknownMap := map[string]cty.Type{} - - // the structure is based on the configuration, so iterate through all the - // defined outputs, and add any instance state or changes we find. - for _, cfg := range outputConfigs { - // record the output names for validation - unknownMap[cfg.Name] = cty.DynamicPseudoType - - // get all instance output for this path from the state - for key, states := range stateMap { - outputState, ok := states[cfg.Name] - if !ok { - continue - } - - instance, ok := moduleInstances[key] - if !ok { - instance = map[string]cty.Value{} - moduleInstances[key] = instance - } - - instance[cfg.Name] = outputState + // If we get here then this _is_ a singleton and our result will be + // an object type built from the placeholder values that represent + // the results for _all_ instances of this module call. + attrs := make(map[string]cty.Value, len(outputConfigs)) + for name := range outputConfigs { + outputAddr := addrs.OutputValue{Name: name} + placeholderAddr := addrs.ObjectInPartialExpandedModule(d.PartialExpandedModulePath.Child(addr), outputAddr) + attrs[name] = d.Evaluator.NamedValues.GetOutputValuePlaceholder(placeholderAddr) } - - // any pending changes override the state state values - for key, changes := range changesMap { - changeSrc, ok := changes[cfg.Name] - if !ok { - continue - } - - instance, ok := moduleInstances[key] - if !ok { - instance = map[string]cty.Value{} - moduleInstances[key] = instance - } - - change, err := changeSrc.Decode() - if err != nil { - // This should happen only if someone has tampered with a plan - // file, so we won't bother with a pretty error for it. - diags = diags.Append(fmt.Errorf("planned change for %s could not be decoded: %s", addr, err)) - instance[cfg.Name] = cty.DynamicVal - continue - } - - instance[cfg.Name] = change.After - - if change.Sensitive { - instance[cfg.Name] = change.After.Mark(marks.Sensitive) - } + return cty.ObjectVal(attrs), diags + } else { + keyType, knownKeys, unknownKeys := d.Evaluator.Instances.GetModuleCallInstanceKeys(addr.Absolute(d.ModulePath)) + if keyType == addrs.UnknownKeyType || unknownKeys { + // If we don't know our full set of instance keys then we can't say + // anything at all about the expected final result. + return cty.DynamicVal, diags } - } - - var ret cty.Value - // compile the outputs into the correct value type for the each mode - switch { - case callConfig.Count != nil: - // figure out what the last index we have is - length := -1 - for key := range moduleInstances { - intKey, ok := key.(addrs.IntKey) - if !ok { - // old key from state which is being dropped - continue + switch keyType { + case addrs.NoKeyType: + // The following two conditions should always hold for for a module + // call which has addrs.NoKeyType as its key type. + if len(knownKeys) != 1 { + panic(fmt.Sprintf("instance expander produced %d instance keys for a singleton module call", len(knownKeys))) } - if int(intKey) >= length { - length = int(intKey) + 1 + if knownKeys[0] != addrs.NoKey { + panic(fmt.Sprintf("instance expander produced instance key %#v for a singleton module call", knownKeys[0])) } - } - if length > 0 { - vals := make([]cty.Value, length) - for key, instance := range moduleInstances { - intKey, ok := key.(addrs.IntKey) - if !ok { - // old key from state which is being dropped - continue - } - - vals[int(intKey)] = cty.ObjectVal(instance) + // Now we've proven that we do indeed have only one instance key + // and it's NoKey, we can safely disregard knownKeys when building + // the result. + // The output values actually live in the child module instance, + // so we need to extend our module instance address to include that. + moduleAddr := d.ModulePath.Child(addr.Name, addrs.NoKey) + attrs := d.moduleCallInstanceOutputValues(moduleAddr, outputConfigs) + return cty.ObjectVal(attrs), diags + + case addrs.IntKeyType: + // For IntKeyType the expander should return the keys in index order, + // and we'll assume that while constructing this tuple. + insts := make([]cty.Value, len(knownKeys)) + for i, instKey := range knownKeys { + // The output values actually live in the child module instance, + // so we need to extend our module instance address to include that. + moduleAddr := d.ModulePath.Child(addr.Name, instKey) + attrs := d.moduleCallInstanceOutputValues(moduleAddr, outputConfigs) + insts[i] = cty.ObjectVal(attrs) } - - // Insert unknown values where there are any missing instances - for i, v := range vals { - if v.IsNull() { - vals[i] = cty.DynamicVal - continue - } + return cty.TupleVal(insts), diags + + case addrs.StringKeyType: + insts := make(map[string]cty.Value, len(knownKeys)) + for _, instKey := range knownKeys { + // The output values actually live in the child module instance, + // so we need to extend our module instance address to include that. + moduleAddr := d.ModulePath.Child(addr.Name, instKey) + attrs := d.moduleCallInstanceOutputValues(moduleAddr, outputConfigs) + insts[string(instKey.(addrs.StringKey))] = cty.ObjectVal(attrs) } - ret = cty.TupleVal(vals) - } else { - ret = cty.EmptyTupleVal - } + return cty.ObjectVal(insts), diags - case callConfig.ForEach != nil: - vals := make(map[string]cty.Value) - for key, instance := range moduleInstances { - strKey, ok := key.(addrs.StringKey) - if !ok { - continue - } - - vals[string(strKey)] = cty.ObjectVal(instance) + default: + // The above cases should be exhaustive for all key types except + // for UnknownKeyType, which we handled in the if statement above. + panic(fmt.Sprintf("unsupported instance key type %s", keyType)) } + } +} - if len(vals) > 0 { - ret = cty.ObjectVal(vals) +func (d *evaluationStateData) moduleCallInstanceOutputValues(moduleAddr addrs.ModuleInstance, outputConfigs map[string]*configs.Output) map[string]cty.Value { + attrs := make(map[string]cty.Value, len(outputConfigs)) + for name, cfg := range outputConfigs { + outputAddr := addrs.OutputValue{Name: name}.Absolute(moduleAddr) + // In situations where Terraform can prove that a particular expression + // refers only to a single output value of a module instance the + // graph allows evaluating the object representing a module before + // all of the output values have been evaluated, so we must generate + // placeholders for any that aren't ready yet. This oddity is just + // so we can reuse the GetModule method as a "get individual output" + // method rather than having to implement essentially the same logic + // in two different ways. + if !d.Evaluator.NamedValues.HasOutputValue(outputAddr) { + attrs[name] = cty.DynamicVal } else { - ret = cty.EmptyObjectVal - } - - default: - val, ok := moduleInstances[addrs.NoKey] - if !ok { - // create the object if there wasn't one known - val = map[string]cty.Value{} - for k := range outputConfigs { - val[k] = cty.DynamicVal - } + attrs[name] = d.Evaluator.NamedValues.GetOutputValue(outputAddr) } - - ret = cty.ObjectVal(val) - } - - // The module won't be expanded during validation, so we need to return an - // unknown value. This will ensure the types looks correct, since we built - // the objects based on the configuration. - if d.Operation == walkValidate { - // While we know the type here and it would be nice to validate whether - // indexes are valid or not, because tuples and objects have fixed - // numbers of elements we can't simply return an unknown value of the - // same type since we have not expanded any instances during - // validation. - // - // In order to validate the expression a little precisely, we'll create - // an unknown map or list here to get more type information. - ty := cty.Object(unknownMap) - switch { - case callConfig.Count != nil: - ret = cty.UnknownVal(cty.List(ty)) - case callConfig.ForEach != nil: - ret = cty.UnknownVal(cty.Map(ty)) - default: - ret = cty.UnknownVal(ty) + if cfg.Sensitive { + attrs[name] = attrs[name].Mark(marks.Sensitive) } } - - return ret, diags + return attrs } func (d *evaluationStateData) GetPathAttr(addr addrs.PathAttr, rng tfdiags.SourceRange) (cty.Value, tfdiags.Diagnostics) { @@ -618,11 +582,11 @@ func (d *evaluationStateData) GetPathAttr(addr addrs.PathAttr, rng tfdiags.Sourc return cty.StringVal(filepath.ToSlash(wd)), diags case "module": - moduleConfig := d.Evaluator.Config.DescendentForInstance(d.ModulePath) + moduleConfig := d.Evaluator.Config.Descendent(d.staticModulePath()) if moduleConfig == nil { // should never happen, since we can't be evaluating in a module // that wasn't mentioned in configuration. - panic(fmt.Sprintf("module.path read from module %s, which has no configuration", d.ModulePath)) + panic(fmt.Sprintf("module.path read from module %s, which has no configuration", d.modulePathDisplayAddr())) } sourceDir := moduleConfig.Module.SourceDir return cty.StringVal(filepath.ToSlash(sourceDir)), diags @@ -650,12 +614,11 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc var diags tfdiags.Diagnostics // First we'll consult the configuration to see if an resource of this // name is declared at all. - moduleAddr := d.ModulePath - moduleConfig := d.Evaluator.Config.DescendentForInstance(moduleAddr) + moduleConfig := d.Evaluator.Config.Descendent(d.staticModulePath()) if moduleConfig == nil { // should never happen, since we can't be evaluating in a module // that wasn't mentioned in configuration. - panic(fmt.Sprintf("resource value read from %s, which has no configuration", moduleAddr)) + panic(fmt.Sprintf("resource value read from %s, which has no configuration", d.modulePathDisplayAddr())) } config := moduleConfig.Module.ResourceByAddr(addr) @@ -663,7 +626,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, Summary: `Reference to undeclared resource`, - Detail: fmt.Sprintf(`A resource %q %q has not been declared in %s`, addr.Type, addr.Name, moduleDisplayAddr(moduleAddr)), + Detail: fmt.Sprintf(`A resource %q %q has not been declared in %s`, addr.Type, addr.Name, d.modulePathDisplayAddr()), Subject: rng.ToHCL().Ptr(), }) return cty.DynamicVal, diags @@ -708,7 +671,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc // (since a planned destroy cannot yet remove root outputs), we // need to return a dynamic value here to allow evaluation to // continue. - log.Printf("[ERROR] unknown instance %q referenced during %s", addr.Absolute(d.ModulePath), d.Operation) + log.Printf("[ERROR] unknown instance %s in %s referenced during %s", addr, d.modulePathDisplayAddr(), d.Operation) return cty.DynamicVal, diags } diff --git a/internal/terraform/evaluate_test.go b/internal/terraform/evaluate_test.go index 9c9dd2c84ed3..6a3e90bc36b2 100644 --- a/internal/terraform/evaluate_test.go +++ b/internal/terraform/evaluate_test.go @@ -4,7 +4,6 @@ package terraform import ( - "sync" "testing" "github.com/davecgh/go-spew/spew" @@ -13,7 +12,9 @@ import ( "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/configschema" + "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/lang/marks" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/states" @@ -25,6 +26,8 @@ func TestEvaluatorGetTerraformAttr(t *testing.T) { Meta: &ContextMeta{ Env: "foo", }, + NamedValues: namedvals.NewState(), + Instances: instances.NewExpander(), } data := &evaluationStateData{ Evaluator: evaluator, @@ -55,6 +58,8 @@ func TestEvaluatorGetPathAttr(t *testing.T) { SourceDir: "bar/baz", }, }, + NamedValues: namedvals.NewState(), + Instances: instances.NewExpander(), } data := &evaluationStateData{ Evaluator: evaluator, @@ -155,6 +160,14 @@ func TestEvaluatorGetOutputValue(t *testing.T) { // This particularly tests that a sensitive attribute in config // results in a value that has a "sensitive" cty Mark func TestEvaluatorGetInputVariable(t *testing.T) { + namedValues := namedvals.NewState() + namedValues.SetInputVariableValue( + addrs.RootModuleInstance.InputVariable("some_var"), cty.StringVal("bar"), + ) + namedValues.SetInputVariableValue( + addrs.RootModuleInstance.InputVariable("some_other_var"), cty.StringVal("boop").Mark(marks.Sensitive), + ) + evaluator := &Evaluator{ Meta: &ContextMeta{ Env: "foo", @@ -180,13 +193,8 @@ func TestEvaluatorGetInputVariable(t *testing.T) { }, }, }, - VariableValues: map[string]map[string]cty.Value{ - "": { - "some_var": cty.StringVal("bar"), - "some_other_var": cty.StringVal("boop").Mark(marks.Sensitive), - }, - }, - VariableValuesLock: &sync.Mutex{}, + NamedValues: namedValues, + Instances: instances.NewExpander(), } data := &evaluationStateData{ @@ -264,7 +272,9 @@ func TestEvaluatorGetResource(t *testing.T) { }, }, }, - State: stateSync, + State: stateSync, + NamedValues: namedvals.NewState(), + Instances: instances.NewExpander(), Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]providers.ProviderSchema{ addrs.NewDefaultProvider("test"): { ResourceTypes: map[string]providers.Schema{ @@ -501,8 +511,10 @@ func TestEvaluatorGetResource_changes(t *testing.T) { }, }, }, - State: stateSync, - Plugins: schemaOnlyProvidersForTesting(schemas.Providers), + State: stateSync, + NamedValues: namedvals.NewState(), + Instances: instances.NewExpander(), + Plugins: schemaOnlyProvidersForTesting(schemas.Providers), } data := &evaluationStateData{ @@ -531,15 +543,11 @@ func TestEvaluatorGetResource_changes(t *testing.T) { } func TestEvaluatorGetModule(t *testing.T) { - // Create a new evaluator with an existing state - stateSync := states.BuildState(func(ss *states.SyncState) { - ss.SetOutputValue( - addrs.OutputValue{Name: "out"}.Absolute(addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "mod"}}), - cty.StringVal("bar"), - true, - ) - }).SyncWrapper() - evaluator := evaluatorForModule(stateSync, plans.NewChanges().SyncWrapper()) + evaluator := evaluatorForModule(states.NewState().SyncWrapper(), plans.NewChanges().SyncWrapper()) + evaluator.NamedValues.SetOutputValue( + addrs.OutputValue{Name: "out"}.Absolute(addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "mod"}}), + cty.StringVal("bar").Mark(marks.Sensitive), + ) data := &evaluationStateData{ Evaluator: evaluator, } @@ -553,57 +561,14 @@ func TestEvaluatorGetModule(t *testing.T) { t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) } if !got.RawEquals(want) { - t.Errorf("wrong result %#v; want %#v", got, want) - } - - // Changes should override the state value - changesSync := plans.NewChanges().SyncWrapper() - change := &plans.OutputChange{ - Addr: addrs.OutputValue{Name: "out"}.Absolute(addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "mod"}}), - Sensitive: true, - Change: plans.Change{ - After: cty.StringVal("baz"), - }, - } - cs, _ := change.Encode() - changesSync.AppendOutputChange(cs) - evaluator = evaluatorForModule(stateSync, changesSync) - data = &evaluationStateData{ - Evaluator: evaluator, - } - scope = evaluator.Scope(data, nil, nil) - want = cty.ObjectVal(map[string]cty.Value{"out": cty.StringVal("baz").Mark(marks.Sensitive)}) - got, diags = scope.Data.GetModule(addrs.ModuleCall{ - Name: "mod", - }, tfdiags.SourceRange{}) - - if len(diags) != 0 { - t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) - } - if !got.RawEquals(want) { - t.Errorf("wrong result %#v; want %#v", got, want) - } - - // Test changes with empty state - evaluator = evaluatorForModule(states.NewState().SyncWrapper(), changesSync) - data = &evaluationStateData{ - Evaluator: evaluator, - } - scope = evaluator.Scope(data, nil, nil) - want = cty.ObjectVal(map[string]cty.Value{"out": cty.StringVal("baz").Mark(marks.Sensitive)}) - got, diags = scope.Data.GetModule(addrs.ModuleCall{ - Name: "mod", - }, tfdiags.SourceRange{}) - - if len(diags) != 0 { - t.Errorf("unexpected diagnostics %s", spew.Sdump(diags)) - } - if !got.RawEquals(want) { - t.Errorf("wrong result %#v; want %#v", got, want) + t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, want) } } func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesSync) *Evaluator { + insts := instances.NewExpander() + insts.SetModuleSingle(addrs.RootModuleInstance, addrs.ModuleCall{Name: "mod"}) + return &Evaluator{ Meta: &ContextMeta{ Env: "foo", @@ -630,8 +595,10 @@ func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesS }, }, }, - State: stateSync, - Changes: changesSync, + State: stateSync, + Changes: changesSync, + NamedValues: namedvals.NewState(), + Instances: insts, } } diff --git a/internal/terraform/graph.go b/internal/terraform/graph.go index 4991c9a3b580..f29fa4d44543 100644 --- a/internal/terraform/graph.go +++ b/internal/terraform/graph.go @@ -71,9 +71,30 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics { // is normally the context of our graph but can be overridden // with a GraphNodeModuleInstance impl. vertexCtx := ctx - if pn, ok := v.(GraphNodeModuleInstance); ok { + switch pn := v.(type) { + case GraphNodeModuleInstance: vertexCtx = walker.EnterPath(pn.Path()) defer walker.ExitPath(pn.Path()) + case GraphNodePartialExpandedModule: + vertexCtx = walker.EnterPartialExpandedPath(pn.PartialExpandedModule()) + defer walker.ExitPartialExpandedPath(pn.PartialExpandedModule()) + case GraphNodeModuleEvalScope: + // This is a dynamic variant that combines the two cases above and + // the possibility to have no scope at all, for situations where + // the same node type needs to handle two or more kinds of + // evaluation. + switch evalScope := pn.ModuleEvalScope().(type) { + case addrs.ModuleInstance: + vertexCtx = walker.EnterPath(evalScope) + defer walker.ExitPath(evalScope) + case addrs.PartialExpandedModule: + vertexCtx = walker.EnterPartialExpandedPath(evalScope) + defer walker.ExitPartialExpandedPath(evalScope) + case nil: + // Fine but we don't have anything to do in this case. + default: + panic(fmt.Sprintf("unsupported addrs.ModuleEvalScope implementation %T", evalScope)) + } } if g.checkAndApplyOverrides(ctx.Overrides(), v) { diff --git a/internal/terraform/graph_interface_subgraph.go b/internal/terraform/graph_interface_subgraph.go index 2e013aeca0fa..a194c99ad130 100644 --- a/internal/terraform/graph_interface_subgraph.go +++ b/internal/terraform/graph_interface_subgraph.go @@ -18,3 +18,26 @@ type GraphNodeModuleInstance interface { type GraphNodeModulePath interface { ModulePath() addrs.Module } + +// GraphNodePartialExpandedModule is implemented by nodes that represent +// potentially multiple instances of a particular configuration object that +// we haven't fully resolved yet because the expansion of one or more of +// the calling modules was deferred. +type GraphNodePartialExpandedModule interface { + PartialExpandedModule() addrs.PartialExpandedModule +} + +// GraphNodeModuleEvalScope is a dynamic variant of both [GraphNodeModuleInstance] +// and [GraphNodePartialExpandedModule] combined, which a node can implement +// to dynamically choose between: +// +// - nil, representing no module evaluation scope at all +// - an [addrs.ModuleInstance], representing an exact module instance with similar effect to implementing [GraphNodeModuleInstance] +// - an [addrs.PartialExpandedModule], representing a partial-expanded module instance with similar effect to implementing [GraphNodePartialExpandedModule] +// +// When calling a node's [GraphNodeExecutable] implementation, the graph +// walker will pass an [EvalContext] with the appropriate module evaluation +// scope (if any) pre-assigned. +type GraphNodeModuleEvalScope interface { + ModuleEvalScope() addrs.ModuleEvalScope +} diff --git a/internal/terraform/graph_walk.go b/internal/terraform/graph_walk.go index 54f5c674d24e..768e052baad1 100644 --- a/internal/terraform/graph_walk.go +++ b/internal/terraform/graph_walk.go @@ -14,6 +14,8 @@ type GraphWalker interface { EvalContext() EvalContext EnterPath(addrs.ModuleInstance) EvalContext ExitPath(addrs.ModuleInstance) + EnterPartialExpandedPath(addrs.PartialExpandedModule) EvalContext + ExitPartialExpandedPath(addrs.PartialExpandedModule) Execute(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics } @@ -22,7 +24,16 @@ type GraphWalker interface { // implementing all the required functions. type NullGraphWalker struct{} -func (NullGraphWalker) EvalContext() EvalContext { return new(MockEvalContext) } -func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) } -func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {} +var _ GraphWalker = NullGraphWalker{} + +func (NullGraphWalker) EvalContext() EvalContext { return new(MockEvalContext) } + +func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) } +func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {} + +func (NullGraphWalker) EnterPartialExpandedPath(addrs.PartialExpandedModule) EvalContext { + return new(MockEvalContext) +} +func (NullGraphWalker) ExitPartialExpandedPath(addrs.PartialExpandedModule) {} + func (NullGraphWalker) Execute(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics { return nil } diff --git a/internal/terraform/graph_walk_context.go b/internal/terraform/graph_walk_context.go index 2171a26b8fc3..56137afc058f 100644 --- a/internal/terraform/graph_walk_context.go +++ b/internal/terraform/graph_walk_context.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/instances" "github.com/hashicorp/terraform/internal/moduletest/mocking" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/provisioners" @@ -36,6 +37,7 @@ type ContextGraphWalker struct { PrevRunState *states.SyncState // Used for safe concurrent access to state Changes *plans.ChangesSync // Used for safe concurrent writes to changes Checks *checks.State // Used for safe concurrent writes of checkable objects and their check results + NamedValues *namedvals.State // Tracks evaluation of input variables, local values, and output values InstanceExpander *instances.Expander // Tracks our gradual expansion of module and resource instances Imports []configs.Import MoveResults refactoring.MoveResults // Read-only record of earlier processing of move statements @@ -64,6 +66,8 @@ type ContextGraphWalker struct { provisionerLock sync.Mutex } +var _ GraphWalker = (*ContextGraphWalker)(nil) + func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext { w.contextLock.Lock() defer w.contextLock.Unlock() @@ -79,6 +83,17 @@ func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext { return ctx } +func (w *ContextGraphWalker) EnterPartialExpandedPath(path addrs.PartialExpandedModule) EvalContext { + w.contextLock.Lock() + defer w.contextLock.Unlock() + + // TODO: Consider caching these in a similar way as we do in EnterPath, + // if the allocations here prove bothersome. + + ctx := w.EvalContext().WithPartialExpandedPath(path) + return ctx +} + func (w *ContextGraphWalker) EvalContext() EvalContext { w.once.Do(w.init) @@ -86,15 +101,15 @@ func (w *ContextGraphWalker) EvalContext() EvalContext { // so that we can safely run multiple evaluations at once across // different modules. evaluator := &Evaluator{ - Meta: w.Context.meta, - Config: w.Config, - Operation: w.Operation, - State: w.State, - Changes: w.Changes, - Plugins: w.Context.plugins, - VariableValues: w.variableValues, - VariableValuesLock: &w.variableValuesLock, - PlanTimestamp: w.PlanTimestamp, + Meta: w.Context.meta, + Config: w.Config, + Operation: w.Operation, + State: w.State, + Changes: w.Changes, + NamedValues: w.NamedValues, + Instances: w.InstanceExpander, + Plugins: w.Context.plugins, + PlanTimestamp: w.PlanTimestamp, } ctx := &BuiltinEvalContext{ @@ -112,12 +127,11 @@ func (w *ContextGraphWalker) EvalContext() EvalContext { ProvisionerLock: &w.provisionerLock, ChangesValue: w.Changes, ChecksValue: w.Checks, + NamedValuesValue: w.NamedValues, StateValue: w.State, RefreshStateValue: w.RefreshState, PrevRunStateValue: w.PrevRunState, Evaluator: evaluator, - VariableValues: w.variableValues, - VariableValuesLock: &w.variableValuesLock, OverrideValues: w.Overrides, } diff --git a/internal/terraform/node_external_reference.go b/internal/terraform/node_external_reference.go index 59ac112a11a8..8050d15e3fa3 100644 --- a/internal/terraform/node_external_reference.go +++ b/internal/terraform/node_external_reference.go @@ -3,7 +3,13 @@ package terraform -import "github.com/hashicorp/terraform/internal/addrs" +import ( + "fmt" + "sort" + "strings" + + "github.com/hashicorp/terraform/internal/addrs" +) // nodeExternalReference allows external callers (such as the testing framework) // to provide the list of references they are making into the graph. This @@ -32,3 +38,13 @@ func (n *nodeExternalReference) ModulePath() addrs.Module { func (n *nodeExternalReference) References() []*addrs.Reference { return n.ExternalReferences } + +// Name implements dag.NamedVertex +func (n *nodeExternalReference) Name() string { + names := make([]string, len(n.ExternalReferences)) + for i, ref := range n.ExternalReferences { + names[i] = ref.DisplayString() + } + sort.Strings(names) + return fmt.Sprintf("", strings.Join(names, ", ")) +} diff --git a/internal/terraform/node_local.go b/internal/terraform/node_local.go index 7d955e514f53..a8237210d28e 100644 --- a/internal/terraform/node_local.go +++ b/internal/terraform/node_local.go @@ -77,6 +77,14 @@ func (n *nodeExpandLocal) DynamicExpand(ctx EvalContext) (*Graph, tfdiags.Diagno log.Printf("[TRACE] Expanding local: adding %s as %T", o.Addr.String(), o) g.Add(o) } + for _, module := range expander.UnknownModuleInstances(n.Module) { + o := &nodeLocalUnexpandedPlaceholder{ + Addr: addrs.ObjectInPartialExpandedModule(module, n.Addr), + Config: n.Config, + } + log.Printf("[TRACE] Expanding local: adding %s as %T", o.Addr.String(), o) + g.Add(o) + } addRootNodeToGraph(&g) return &g, nil } @@ -161,13 +169,7 @@ func (n *NodeLocal) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Di return diags } - state := ctx.State() - if state == nil { - diags = diags.Append(fmt.Errorf("cannot write local value to nil state")) - return diags - } - - state.SetLocalValue(addr.Absolute(ctx.Path()), val) + ctx.NamedValues().SetLocalValue(addr.Absolute(ctx.Path()), val) return diags } @@ -182,3 +184,75 @@ func (n *NodeLocal) DotNode(name string, opts *dag.DotOpts) *dag.DotNode { }, } } + +type nodeLocalUnexpandedPlaceholder struct { + Addr addrs.InPartialExpandedModule[addrs.LocalValue] + Config *configs.Local +} + +var ( + _ GraphNodePartialExpandedModule = (*nodeLocalUnexpandedPlaceholder)(nil) + _ GraphNodeReferenceable = (*nodeLocalUnexpandedPlaceholder)(nil) + _ GraphNodeReferencer = (*nodeLocalUnexpandedPlaceholder)(nil) + _ GraphNodeExecutable = (*nodeLocalUnexpandedPlaceholder)(nil) + _ graphNodeTemporaryValue = (*nodeLocalUnexpandedPlaceholder)(nil) +) + +// PartialExpandedModule implements GraphNodePartialExpandedModule +func (n *nodeLocalUnexpandedPlaceholder) PartialExpandedModule() addrs.PartialExpandedModule { + return n.Addr.Module +} + +func (n *nodeLocalUnexpandedPlaceholder) Name() string { + return n.Addr.String() +} + +// graphNodeTemporaryValue +func (n *nodeLocalUnexpandedPlaceholder) temporaryValue() bool { + return true +} + +// GraphNodeReferenceable +func (n *nodeLocalUnexpandedPlaceholder) ReferenceableAddrs() []addrs.Referenceable { + return []addrs.Referenceable{n.Addr.Local} +} + +// GraphNodeReferencer +func (n *nodeLocalUnexpandedPlaceholder) References() []*addrs.Reference { + refs, _ := lang.ReferencesInExpr(addrs.ParseRef, n.Config.Expr) + return refs +} + +// Execute implements GraphNodeExecutable +func (n *nodeLocalUnexpandedPlaceholder) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + expr := n.Config.Expr + + // We ignore diags here because any problems we might find will be found + // again in EvaluateExpr below. + refs, _ := lang.ReferencesInExpr(addrs.ParseRef, expr) + for _, ref := range refs { + if ref.Subject == n.Addr.Local { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Self-referencing local value", + Detail: fmt.Sprintf("Local value %s cannot use its own result as part of its expression.", n.Addr), + Subject: ref.SourceRange.ToHCL().Ptr(), + Context: expr.Range().Ptr(), + }) + } + } + if diags.HasErrors() { + return diags + } + + val, moreDiags := ctx.EvaluateExpr(expr, cty.DynamicPseudoType, nil) + diags = diags.Append(moreDiags) + if moreDiags.HasErrors() { + return diags + } + + ctx.NamedValues().SetLocalValuePlaceholder(n.Addr, val) + + return diags +} diff --git a/internal/terraform/node_local_test.go b/internal/terraform/node_local_test.go index 6e11d74f7d6d..ba28c118e99d 100644 --- a/internal/terraform/node_local_test.go +++ b/internal/terraform/node_local_test.go @@ -4,17 +4,15 @@ package terraform import ( - "reflect" "testing" - "github.com/davecgh/go-spew/spew" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" - "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/hcl2shim" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/states" ) @@ -48,14 +46,16 @@ func TestNodeLocalExecute(t *testing.T) { t.Fatal(diags.Error()) } + localAddr := addrs.LocalValue{Name: "foo"}.Absolute(addrs.RootModuleInstance) n := &NodeLocal{ - Addr: addrs.LocalValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + Addr: localAddr, Config: &configs.Local{ Expr: expr, }, } ctx := &MockEvalContext{ - StateState: states.NewState().SyncWrapper(), + StateState: states.NewState().SyncWrapper(), + NamedValuesState: namedvals.NewState(), EvaluateExprResult: hcl2shim.HCL2ValueFromConfigValue(test.Want), } @@ -69,18 +69,19 @@ func TestNodeLocalExecute(t *testing.T) { } } - ms := ctx.StateState.Module(addrs.RootModuleInstance) - gotLocals := ms.LocalValues - wantLocals := map[string]cty.Value{} - if test.Want != nil { - wantLocals["foo"] = hcl2shim.HCL2ValueFromConfigValue(test.Want) - } - - if !reflect.DeepEqual(gotLocals, wantLocals) { - t.Errorf( - "wrong locals after Eval\ngot: %swant: %s", - spew.Sdump(gotLocals), spew.Sdump(wantLocals), - ) + if test.Err { + if ctx.NamedValues().HasLocalValue(localAddr) { + t.Errorf("have value for %s, but wanted none", localAddr) + } + } else { + if !ctx.NamedValues().HasLocalValue(localAddr) { + t.Fatalf("no value for %s", localAddr) + } + got := ctx.NamedValues().GetLocalValue(localAddr) + want := hcl2shim.HCL2ValueFromConfigValue(test.Want) + if !want.RawEquals(got) { + t.Errorf("wrong value for %s\ngot: %#v\nwant: %#v", localAddr, got, want) + } } }) } diff --git a/internal/terraform/node_module_expand.go b/internal/terraform/node_module_expand.go index 9fc0495c9554..f8044b8c7644 100644 --- a/internal/terraform/node_module_expand.go +++ b/internal/terraform/node_module_expand.go @@ -111,24 +111,38 @@ func (n *nodeExpandModule) Execute(ctx EvalContext, op walkOperation) (diags tfd // to our module, and register module instances with each of them. for _, module := range expander.ExpandModule(n.Addr.Parent()) { ctx = ctx.WithPath(module) + callAddr := module.ChildCall(call.Name) switch { case n.ModuleCall.Count != nil: - count, ctDiags := evaluateCountExpression(n.ModuleCall.Count, ctx) + count, known, ctDiags := evaluateCountExpression(n.ModuleCall.Count, ctx) diags = diags.Append(ctDiags) if diags.HasErrors() { return diags } - expander.SetModuleCount(module, call, count) + if known { + log.Printf("[TRACE] nodeExpandModule: %s has count = %d", callAddr, count) + expander.SetModuleCount(module, call, count) + } else { + log.Printf("[TRACE] nodeExpandModule: %s has unknown count", callAddr) + expander.SetModuleCountUnknown(module, call) + } case n.ModuleCall.ForEach != nil: - forEach, feDiags := evaluateForEachExpression(n.ModuleCall.ForEach, ctx) + forEach, known, feDiags := evaluateForEachExpression(n.ModuleCall.ForEach, ctx) diags = diags.Append(feDiags) if diags.HasErrors() { return diags } - expander.SetModuleForEach(module, call, forEach) + if known { + log.Printf("[TRACE] nodeExpandModule: %s has for_each with instance count %d", callAddr, len(forEach)) + expander.SetModuleForEach(module, call, forEach) + } else { + log.Printf("[TRACE] nodeExpandModule: %s has for_each with unknown instance keys", callAddr) + expander.SetModuleForEachUnknown(module, call) + } default: + log.Printf("[TRACE] nodeExpandModule: %s is a single-instance module", callAddr) expander.SetModuleSingle(module, call) } } @@ -240,16 +254,19 @@ func (n *nodeValidateModule) Execute(ctx EvalContext, op walkOperation) (diags t _, call := n.Addr.Call() expander := ctx.InstanceExpander() - // Modules all evaluate to single instances during validation, only to - // create a proper context within which to evaluate. All parent modules - // will be a single instance, but still get our address in the expected - // manner anyway to ensure they've been registered correctly. + // We don't actually ever expand during validation, since we're testing + // whether modules are valid for _any_ input, rather than for some specific + // input. + // + // Therefore we evaluate the count or for_each expression purely to check + // whether its valid, but then always mark the expansion unknown so that + // downstreams will work with placeholder values that cover only what + // all instances of the module have in common. Specific instance validation + // will happen as part of planning. for _, module := range expander.ExpandModule(n.Addr.Parent()) { ctx = ctx.WithPath(module) // Validate our for_each and count expressions at a basic level - // We skip validation on known, because there will be unknown values before - // a full expansion, presuming these errors will be caught in later steps switch { case n.ModuleCall.Count != nil: _, countDiags := evaluateCountExpressionValue(n.ModuleCall.Count, ctx) diff --git a/internal/terraform/node_module_variable.go b/internal/terraform/node_module_variable.go index 7237fb84b322..e15c106af51e 100644 --- a/internal/terraform/node_module_variable.go +++ b/internal/terraform/node_module_variable.go @@ -80,6 +80,14 @@ func (n *nodeExpandModuleVariable) DynamicExpand(ctx EvalContext) (*Graph, tfdia } g.Add(o) } + for _, unexpModule := range expander.UnknownModuleInstances(n.Module) { + o := &nodePartialExpandedModuleVariable{ + Addr: addrs.ObjectInPartialExpandedModule(unexpModule, n.Addr), + Config: n.Config, + Expr: n.Expr, + } + g.Add(o) + } addRootNodeToGraph(&g) if checkableAddrs != nil { @@ -136,8 +144,8 @@ func (n *nodeExpandModuleVariable) ReferenceableAddrs() []addrs.Referenceable { return []addrs.Referenceable{n.Addr} } -// nodeModuleVariable represents a module variable input during -// the apply step. +// nodeModuleVariable represents a module input variable in an already-expanded +// module instance. type nodeModuleVariable struct { Addr addrs.AbsInputVariableInstance Config *configs.Variable // Config is the var in the config @@ -201,8 +209,7 @@ func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) (diags t // Set values for arguments of a child module call, for later retrieval // during expression evaluation. - _, call := n.Addr.Module.CallInstance() - ctx.SetModuleCallArgument(call, n.Addr.Variable, val) + ctx.NamedValues().SetInputVariableValue(n.Addr, val) // Skip evalVariableValidations during destroy operations. We still want // to evaluate the variable in case it is used to initialise providers @@ -248,6 +255,9 @@ func (n *nodeModuleVariable) evalModuleVariable(ctx EvalContext, validateOnly bo case validateOnly: // the instance expander does not track unknown expansion values, so we // have to assume all RepetitionData is unknown. + // TODO: This is essentially what nodePartialExpandedModuleVariable + // does too, so we should consider making the validate walk use + // that node type instead so we have fewer codepaths. moduleInstanceRepetitionData = instances.RepetitionData{ CountIndex: cty.UnknownVal(cty.Number), EachKey: cty.UnknownVal(cty.String), @@ -288,3 +298,116 @@ func (n *nodeModuleVariable) evalModuleVariable(ctx EvalContext, validateOnly bo return finalVal, diags.ErrWithWarnings() } + +// nodePartialExpandedModuleVariable represents a placeholder for zero or more +// module input variable instances that live under a module path which can't +// be fully expanded yet. +type nodePartialExpandedModuleVariable struct { + Addr addrs.InPartialExpandedModule[addrs.InputVariable] + Config *configs.Variable // Config is the var in the config + Expr hcl.Expression // Expr is the value expression given in the call +} + +// Ensure that we are implementing all of the interfaces we think we are +// implementing. +var ( + _ GraphNodePartialExpandedModule = (*nodePartialExpandedModuleVariable)(nil) + _ GraphNodeExecutable = (*nodePartialExpandedModuleVariable)(nil) + _ graphNodeTemporaryValue = (*nodePartialExpandedModuleVariable)(nil) +) + +func (n *nodePartialExpandedModuleVariable) Name() string { + return n.Addr.String() +} + +func (n *nodePartialExpandedModuleVariable) temporaryValue() bool { + return true +} + +// Execute implements GraphNodeExecutable +func (n *nodePartialExpandedModuleVariable) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { + // For an input variable in a partial-expanded module our job is to + // produce a placeholder value that ought to be true for any possible + // instance of the containing module once its expansion _is_ known. + // Downstreams will use this to further derive approximate results, so + // it's important that we don't over-promise and err on the side of + // using unknown value placeholders for anything that might vary between + // instances of the module. + + var diags tfdiags.Diagnostics + var givenVal cty.Value + var errSourceRange tfdiags.SourceRange + + ctx = n.evalContextForParentModuleInstance(ctx) + if expr := n.Expr; expr != nil { + + // TODO: We should ideally be able to tailor this based on whether the + // module configuration is using count, for_each, or neither, but we don't + // currently have access to that information here so we'll settle for just + // allowing everything as unknown for now. + moduleInstanceRepetitionData := instances.RepetitionData{ + CountIndex: cty.UnknownVal(cty.Number), + EachKey: cty.UnknownVal(cty.String), + EachValue: cty.DynamicVal, + } + + scope := ctx.EvaluationScope(nil, nil, moduleInstanceRepetitionData) + val, moreDiags := scope.EvalExpr(expr, cty.DynamicPseudoType) + diags = diags.Append(moreDiags) + if moreDiags.HasErrors() { + return diags + } + givenVal = val + errSourceRange = tfdiags.SourceRangeFromHCL(expr.Range()) + } else { + // We'll use cty.NilVal to represent the variable not being set at all. + givenVal = cty.NilVal + errSourceRange = tfdiags.SourceRangeFromHCL(n.Config.DeclRange) // we use the declaration range as a fallback for an undefined variable + } + + // We construct a synthetic InputValue here to pretend as if this were + // a root module variable set from outside, just as a convenience so we + // can reuse the InputValue type for this. + rawVal := &InputValue{ + Value: givenVal, + SourceType: ValueFromConfig, + SourceRange: errSourceRange, + } + + // prepareFinalInputVariableValue expects to be working with a fully-expanded + // input variable, so for now we'll construct a synthetic address for it to + // use. We should probably find a better way to do this at some point + // because this will produce mildly-inaccurate error messages. + fakeInstanceAddr := n.Addr.Module.Module().UnkeyedInstanceShim().InputVariable(n.Addr.Local.Name) + finalVal, moreDiags := prepareFinalInputVariableValue(fakeInstanceAddr, rawVal, n.Config) + diags = diags.Append(moreDiags) + + // This placeholder represents a the value for all possible instances of + // this variable that might exist after we know the full expansion of the + // containing module, so will be used as the value of this variable for + // any evaluation we do to predict the results of these hypothetical module + // instances. + ctx.NamedValues().SetInputVariablePlaceholder(n.Addr, finalVal) + + return diags +} + +// evalContextForParentModuleInstance returns a "pathed" [EvalContext] that has +// either an exact module path or a partial-expanded one depending on whether +// the parent module instance of this variable is expanded or not. +func (n *nodePartialExpandedModuleVariable) evalContextForParentModuleInstance(unpathedCtx EvalContext) EvalContext { + if parent, ok := n.Addr.Module.ParentModuleInstance(); ok { + return unpathedCtx.WithPath(parent) + } else if parent, ok := n.Addr.Module.ParentPartialExpandedModule(); ok { + return unpathedCtx.WithPartialExpandedPath(parent) + } else { + // Should never happen: parent should always be either a ModuleInstance + // or another PartialExpandedModule. + panic(fmt.Sprintf("parent of %s is neither fully-expanded nor partially-expanded module", n.Addr.Module)) + } +} + +// PartialExpandedModule implements GraphNodePartialExpandedModule +func (n *nodePartialExpandedModuleVariable) PartialExpandedModule() addrs.PartialExpandedModule { + return n.Addr.Module +} diff --git a/internal/terraform/node_output.go b/internal/terraform/node_output.go index 249365a65f3c..e37e8cac199f 100644 --- a/internal/terraform/node_output.go +++ b/internal/terraform/node_output.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform/internal/dag" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/lang/marks" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/tfdiags" @@ -119,7 +120,14 @@ func (n *nodeExpandOutput) DynamicExpand(ctx EvalContext) (*Graph, tfdiags.Diagn } } - log.Printf("[TRACE] Expanding output: adding %s as %T", absAddr.String(), node) + log.Printf("[TRACE] nodeExpandOutput: adding %s as %T", absAddr.String(), node) + g.Add(node) + } + for _, module := range expander.UnknownModuleInstances(n.Module) { + node := &nodeOutputUnexpandedPlaceholder{ + Addr: addrs.ObjectInPartialExpandedModule(module, n.Addr), + Config: n.Config, + } g.Add(node) } addRootNodeToGraph(&g) @@ -268,9 +276,10 @@ func referenceableAddrsForOutput(addr addrs.AbsOutputValue) []addrs.Referenceabl // relative to the calling module, not the module where the output // was declared. _, outp := addr.ModuleCallOutput() - _, call := addr.Module.CallInstance() + _, callInst := addr.Module.CallInstance() + _, call := addr.Module.Call() - return []addrs.Referenceable{outp, call} + return []addrs.Referenceable{outp, callInst, call} } // GraphNodeReferenceable @@ -390,7 +399,7 @@ If you do intend to export this data, annotate the output value as sensitive by // if we're continuing, make sure the output is included, and // marked as unknown. If the evaluator was able to find a type // for the value in spite of the error then we'll use it. - n.setValue(state, changes, cty.UnknownVal(val.Type())) + n.setValue(ctx.NamedValues(), state, changes, cty.UnknownVal(val.Type())) // Keep existing warnings, while converting errors to warnings. // This is not meant to be the normal path, so there no need to @@ -410,13 +419,13 @@ If you do intend to export this data, annotate the output value as sensitive by } return diags } - n.setValue(state, changes, val) + n.setValue(ctx.NamedValues(), state, changes, val) // If we were able to evaluate a new value, we can update that in the // refreshed state as well. if state = ctx.RefreshState(); state != nil && val.IsWhollyKnown() { // we only need to update the state, do not pass in the changes again - n.setValue(state, nil, val) + n.setValue(nil, state, nil, val) } return diags @@ -472,7 +481,10 @@ func (n *NodeDestroyableOutput) Execute(ctx EvalContext, op walkOperation) tfdia before := cty.NullVal(cty.DynamicPseudoType) mod := state.Module(n.Addr.Module) if n.Addr.Module.IsRoot() && mod != nil { - if o, ok := mod.OutputValues[n.Addr.OutputValue.Name]; ok { + s := state.Lock() + rootOutputs := s.RootOutputValues + state.Unlock() + if o, ok := rootOutputs[n.Addr.OutputValue.Name]; ok { sensitiveBefore = o.Sensitive before = o.Value } else { @@ -521,7 +533,7 @@ func (n *NodeDestroyableOutput) DotNode(name string, opts *dag.DotOpts) *dag.Dot } } -func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.ChangesSync, val cty.Value) { +func (n *NodeApplyableOutput) setValue(namedVals *namedvals.State, state *states.SyncState, changes *plans.ChangesSync, val cty.Value) { if changes != nil && n.Planning { // if this is a root module, try to get a before value from the state for // the diff @@ -533,7 +545,10 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C mod := state.Module(n.Addr.Module) if n.Addr.Module.IsRoot() && mod != nil { - for name, o := range mod.OutputValues { + s := state.Lock() + rootOutputs := s.RootOutputValues + state.Unlock() + for name, o := range rootOutputs { if name == n.Addr.OutputValue.Name { before = o.Value sensitiveBefore = o.Sensitive @@ -587,7 +602,7 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C // Should never happen, since we just constructed this right above panic(fmt.Sprintf("planned change for %s could not be encoded: %s", n.Addr, err)) } - log.Printf("[TRACE] setValue: Saving %s change for %s in changeset", change.Action, n.Addr) + log.Printf("[TRACE] NodeApplyableOutput.setValue: Saving %s change for %s in changeset", change.Action, n.Addr) changes.AppendOutputChange(cs) // add the new planned change } @@ -601,13 +616,22 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C // evaluated. Null root outputs are removed entirely, which is always fine // because they can't be referenced by anything else in the configuration. if n.Addr.Module.IsRoot() && val.IsNull() { - log.Printf("[TRACE] setValue: Removing %s from state (it is now null)", n.Addr) + log.Printf("[TRACE] NodeApplyableOutput.setValue: Removing %s from state (it is now null)", n.Addr) state.RemoveOutputValue(n.Addr) return } - log.Printf("[TRACE] setValue: Saving value for %s in state", n.Addr) + // caller leaves namedVals nil if they've already called this function + // with a different state, since we only have one namedVals regardless + // of how many states are involved in an operation. + if namedVals != nil { + namedVals.SetOutputValue(n.Addr, val) + } + // The state itself doesn't represent unknown values, so we null them + // out here and then we'll save the real unknown value in the planned + // changeset, if we have one on this graph walk. + log.Printf("[TRACE] NodeApplyableOutput.setValue: Saving value for %s in state", n.Addr) // non-root outputs need to keep sensitive marks for evaluation, but are // not serialized. if n.Addr.Module.IsRoot() { @@ -617,3 +641,72 @@ func (n *NodeApplyableOutput) setValue(state *states.SyncState, changes *plans.C state.SetOutputValue(n.Addr, val, n.Config.Sensitive) } + +type nodeOutputUnexpandedPlaceholder struct { + Addr addrs.InPartialExpandedModule[addrs.OutputValue] + Config *configs.Output +} + +var ( + _ GraphNodePartialExpandedModule = (*nodeOutputUnexpandedPlaceholder)(nil) + _ GraphNodeReferenceable = (*nodeOutputUnexpandedPlaceholder)(nil) + _ GraphNodeReferencer = (*nodeOutputUnexpandedPlaceholder)(nil) + _ GraphNodeReferenceOutside = (*nodeOutputUnexpandedPlaceholder)(nil) + _ GraphNodeExecutable = (*nodeOutputUnexpandedPlaceholder)(nil) + _ graphNodeTemporaryValue = (*nodeOutputUnexpandedPlaceholder)(nil) +) + +func (n *nodeOutputUnexpandedPlaceholder) temporaryValue() bool { + return !n.Addr.Module.Module().IsRoot() +} + +func (n *nodeOutputUnexpandedPlaceholder) Name() string { + return n.Addr.String() +} + +// GraphNodePartialExpandedModule +func (n *nodeOutputUnexpandedPlaceholder) PartialExpandedModule() addrs.PartialExpandedModule { + return n.Addr.Module +} + +// GraphNodeReferenceOutside implementation +func (n *nodeOutputUnexpandedPlaceholder) ReferenceOutside() (selfPath, referencePath addrs.Module) { + // Output values have their expressions resolved in the context of the + // module where they are defined. + referencePath = n.Addr.Module.Module() + + // ...but they are referenced in the context of their calling module. + selfPath = referencePath.Parent() + + return // uses named return values +} + +// GraphNodeReferenceable +func (n *nodeOutputUnexpandedPlaceholder) ReferenceableAddrs() []addrs.Referenceable { + // For an output inside an unexpanded module we don't actually have any + // specific module call instance addresses to return; the best we can + // do is the entire call that we're declared within, which should then + // soak up any access to any instance of it, and therefore any output + // value within any instance of it. + moduleAddr := n.Addr.Module.Module() + callName := moduleAddr[len(moduleAddr)-1] + call := addrs.ModuleCall{Name: callName} + return []addrs.Referenceable{call} +} + +func (n *nodeOutputUnexpandedPlaceholder) References() []*addrs.Reference { + return referencesForOutput(n.Config) +} + +// Execute implements GraphNodeExecutable +func (n *nodeOutputUnexpandedPlaceholder) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { + val, diags := ctx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil) + if diags.HasErrors() { + val = cty.DynamicVal + } + diags = diags.Append(validateDependsOn(ctx, n.Config.DependsOn)) + + ctx.NamedValues().SetOutputValuePlaceholder(n.Addr, val) + + return diags +} diff --git a/internal/terraform/node_output_test.go b/internal/terraform/node_output_test.go index 97af2986eac6..1e007ff703e0 100644 --- a/internal/terraform/node_output_test.go +++ b/internal/terraform/node_output_test.go @@ -153,7 +153,10 @@ func TestNodeDestroyableOutputExecute(t *testing.T) { outputAddr := addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance) state := states.NewState() - state.Module(addrs.RootModuleInstance).SetOutputValue("foo", cty.StringVal("bar"), false) + state.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("bar"), false, + ) state.OutputValue(outputAddr) ctx := &MockEvalContext{ diff --git a/internal/terraform/node_resource_abstract.go b/internal/terraform/node_resource_abstract.go index cbf4f1d16e40..b21f9aa7467a 100644 --- a/internal/terraform/node_resource_abstract.go +++ b/internal/terraform/node_resource_abstract.go @@ -142,15 +142,20 @@ func (n *NodeAbstractResource) ReferenceableAddrs() []addrs.Referenceable { // GraphNodeReferencer func (n *NodeAbstractResource) References() []*addrs.Reference { + return referencesForResource(n.Addr, n.Config, n.Schema, n.ProvisionerSchemas) +} + +func referencesForResource(addr addrs.ConfigResource, config *configs.Resource, schema *configschema.Block, provisionerSchemas map[string]*configschema.Block) []*addrs.Reference { var result []*addrs.Reference // If we have a config then we prefer to use that. - if c := n.Config; c != nil { - result = append(result, n.DependsOn()...) + if c := config; c != nil { + result = append(result, resourceDependsOn(addr, config)...) - if n.Schema == nil { + if schema == nil { // Should never happen, but we'll log if it does so that we can // see this easily when debugging. - log.Printf("[WARN] no schema is attached to %s, so config references cannot be detected", n.Name()) + log.Printf("[WARN] no schema is attached to %s, so config references cannot be detected", addr) + } refs, _ := lang.ReferencesInExpr(addrs.ParseRef, c.Count) @@ -164,8 +169,8 @@ func (n *NodeAbstractResource) References() []*addrs.Reference { } // ReferencesInBlock() requires a schema - if n.Schema != nil { - refs, _ = lang.ReferencesInBlock(addrs.ParseRef, c.Config, n.Schema) + if schema != nil { + refs, _ = lang.ReferencesInBlock(addrs.ParseRef, c.Config, schema) result = append(result, refs...) } @@ -184,9 +189,9 @@ func (n *NodeAbstractResource) References() []*addrs.Reference { result = append(result, refs...) } - schema := n.ProvisionerSchemas[p.Type] + schema := provisionerSchemas[p.Type] if schema == nil { - log.Printf("[WARN] no schema for provisioner %q is attached to %s, so provisioner block references cannot be detected", p.Type, n.Name()) + log.Printf("[WARN] no schema for provisioner %q is attached to %s, so provisioner block references cannot be detected", p.Type, addr) } refs, _ = lang.ReferencesInBlock(addrs.ParseRef, p.Config, schema) result = append(result, refs...) @@ -227,16 +232,19 @@ func (n *NodeAbstractResource) ImportReferences() []*addrs.Reference { } func (n *NodeAbstractResource) DependsOn() []*addrs.Reference { - var result []*addrs.Reference - if c := n.Config; c != nil { + return resourceDependsOn(n.Addr, n.Config) +} - for _, traversal := range c.DependsOn { +func resourceDependsOn(addr addrs.ConfigResource, config *configs.Resource) []*addrs.Reference { + var result []*addrs.Reference + if config != nil { + for _, traversal := range config.DependsOn { ref, diags := addrs.ParseRef(traversal) if diags.HasErrors() { // We ignore this here, because this isn't a suitable place to return // errors. This situation should be caught and rejected during // validation. - log.Printf("[ERROR] Can't parse %#v from depends_on as reference: %s", traversal, diags.Err()) + log.Printf("[ERROR] Can't parse %#v from depends_on of %s as reference: %s", traversal, addr, diags.Err()) continue } @@ -404,17 +412,21 @@ func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.Ab switch { case n.Config != nil && n.Config.Count != nil: - count, countDiags := evaluateCountExpression(n.Config.Count, ctx) + count, known, countDiags := evaluateCountExpression(n.Config.Count, ctx) diags = diags.Append(countDiags) if countDiags.HasErrors() { return diags } state.SetResourceProvider(addr, n.ResolvedProvider) - expander.SetResourceCount(addr.Module, n.Addr.Resource, count) + if known { + expander.SetResourceCount(addr.Module, n.Addr.Resource, count) + } else { + expander.SetResourceCountUnknown(addr.Module, n.Addr.Resource) + } case n.Config != nil && n.Config.ForEach != nil: - forEach, forEachDiags := evaluateForEachExpression(n.Config.ForEach, ctx) + forEach, known, forEachDiags := evaluateForEachExpression(n.Config.ForEach, ctx) diags = diags.Append(forEachDiags) if forEachDiags.HasErrors() { return diags @@ -423,7 +435,11 @@ func (n *NodeAbstractResource) writeResourceState(ctx EvalContext, addr addrs.Ab // This method takes care of all of the business logic of updating this // while ensuring that any existing instances are preserved, etc. state.SetResourceProvider(addr, n.ResolvedProvider) - expander.SetResourceForEach(addr.Module, n.Addr.Resource, forEach) + if known { + expander.SetResourceForEach(addr.Module, n.Addr.Resource, forEach) + } else { + expander.SetResourceForEachUnknown(addr.Module, n.Addr.Resource) + } default: state.SetResourceProvider(addr, n.ResolvedProvider) diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index d3e969d6296e..7b93e91b47cb 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -643,6 +643,19 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state if n.Config != nil { resp.Diagnostics = resp.Diagnostics.InConfigBody(n.Config.Config, n.Addr.String()) } + if len(resp.Deferred) != 0 { + // We don't yet support deferrals really, so for now we'll just treat + // them as errors. This is only a temporary shortcut and should not + // ship in any stable Terraform release. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Not enough information to read", + Detail: fmt.Sprintf( + "The configuration of either %s or its provider contains unknown values that prevent planning.", + n.Addr.String(), + ), + }) + } diags = diags.Append(resp.Diagnostics) if diags.HasErrors() { @@ -760,10 +773,8 @@ func (n *NodeAbstractResourceInstance) plan( createBeforeDestroy = plannedChange.Action == plans.CreateThenDelete } - // Evaluate the configuration - forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx) - - keyData = EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach) + exp := ctx.InstanceExpander() + keyData = exp.GetResourceInstanceRepetitionData(n.Addr) checkDiags := evalCheckRules( addrs.ResourcePrecondition, @@ -898,6 +909,20 @@ func (n *NodeAbstractResourceInstance) plan( }) } diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config, n.Addr.String())) + if len(resp.Deferred) != 0 { + // We don't yet support deferrals really, so for now we'll just treat + // them as errors. This is only a temporary shortcut and should not + // ship in any stable Terraform release. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Not enough information to plan", + Detail: fmt.Sprintf( + "The configuration of either %s or its provider contains unknown values that prevent planning.", + n.Addr.String(), + ), + Subject: config.DeclRange.Ptr(), + }) + } if diags.HasErrors() { return nil, nil, keyData, diags } @@ -1566,6 +1591,20 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal }) } diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config, n.Addr.String())) + if len(resp.Deferred) != 0 { + // We don't yet support deferrals really, so for now we'll just treat + // them as errors. This is only a temporary shortcut and should not + // ship in any stable Terraform release. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Not enough information to read", + Detail: fmt.Sprintf( + "The configuration of either %s or its provider contains unknown values that prevent planning.", + n.Addr.String(), + ), + Subject: config.DeclRange.Ptr(), + }) + } if diags.HasErrors() { return newVal, diags } @@ -1689,8 +1728,8 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule objTy := schema.ImpliedType() priorVal := cty.NullVal(objTy) - forEach, _ := evaluateForEachExpression(config.ForEach, ctx) - keyData = EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach) + exp := ctx.InstanceExpander() + keyData = exp.GetResourceInstanceRepetitionData(n.Addr) checkDiags := evalCheckRules( addrs.ResourcePrecondition, @@ -1969,8 +2008,8 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned return nil, keyData, diags } - forEach, _ := evaluateForEachExpression(config.ForEach, ctx) - keyData = EvalDataForInstanceKey(n.Addr.Resource.Key, forEach) + exp := ctx.InstanceExpander() + keyData = exp.GetResourceInstanceRepetitionData(n.Addr) checkDiags := evalCheckRules( addrs.ResourcePrecondition, @@ -2273,10 +2312,8 @@ func (n *NodeAbstractResourceInstance) applyProvisioners(ctx EvalContext, state func (n *NodeAbstractResourceInstance) evalProvisionerConfig(ctx EvalContext, body hcl.Body, self cty.Value, schema *configschema.Block) (cty.Value, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics - forEach, forEachDiags := evaluateForEachExpression(n.Config.ForEach, ctx) - diags = diags.Append(forEachDiags) - - keyData := EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach) + exp := ctx.InstanceExpander() + keyData := exp.GetResourceInstanceRepetitionData(n.Addr) config, _, configDiags := ctx.EvaluateBlock(body, schema, n.ResourceInstanceAddr().Resource, keyData) diags = diags.Append(configDiags) diff --git a/internal/terraform/node_resource_import.go b/internal/terraform/node_resource_import.go index 608cbabee2f5..7222def22a7a 100644 --- a/internal/terraform/node_resource_import.go +++ b/internal/terraform/node_resource_import.go @@ -7,6 +7,7 @@ import ( "fmt" "log" + "github.com/hashicorp/hcl/v2" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/states" @@ -95,6 +96,19 @@ func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags ID: n.ID, }) diags = diags.Append(resp.Diagnostics) + if len(resp.Deferred) != 0 { + // We don't yet support deferrals really, so for now we'll just treat + // them as errors. This is only a temporary shortcut and should not + // ship in any stable Terraform release. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Not enough information to import", + Detail: fmt.Sprintf( + "The provider configuration for %s contains unknown values that prevent planning.", + n.Addr.String(), + ), + }) + } if diags.HasErrors() { return diags } diff --git a/internal/terraform/node_resource_plan.go b/internal/terraform/node_resource_plan.go index 041d414293bd..17bc2be7f05b 100644 --- a/internal/terraform/node_resource_plan.go +++ b/internal/terraform/node_resource_plan.go @@ -108,57 +108,6 @@ func (n *nodeExpandPlannableResource) DynamicExpand(ctx EvalContext) (*Graph, tf expander := ctx.InstanceExpander() moduleInstances := expander.ExpandModule(n.Addr.Module) - // Lock the state while we inspect it - state := ctx.State().Lock() - - var orphans []*states.Resource - for _, res := range state.Resources(n.Addr) { - found := false - for _, m := range moduleInstances { - if m.Equal(res.Addr.Module) { - found = true - break - } - } - // The module instance of the resource in the state doesn't exist - // in the current config, so this whole resource is orphaned. - if !found { - orphans = append(orphans, res) - } - } - - // We'll no longer use the state directly here, and the other functions - // we'll call below may use it so we'll release the lock. - state = nil - ctx.State().Unlock() - - // The concrete resource factory we'll use for orphans - concreteResourceOrphan := func(a *NodeAbstractResourceInstance) *NodePlannableResourceInstanceOrphan { - // Add the config and state since we don't do that via transforms - a.Config = n.Config - a.ResolvedProvider = n.ResolvedProvider - a.Schema = n.Schema - a.ProvisionerSchemas = n.ProvisionerSchemas - a.ProviderMetas = n.ProviderMetas - a.Dependencies = n.dependencies - - return &NodePlannableResourceInstanceOrphan{ - NodeAbstractResourceInstance: a, - skipRefresh: n.skipRefresh, - skipPlanChanges: n.skipPlanChanges, - } - } - - for _, res := range orphans { - for key := range res.Instances { - addr := res.Addr.Instance(key) - abs := NewNodeAbstractResourceInstance(addr) - abs.AttachResourceState(res) - n := concreteResourceOrphan(abs) - g.Add(n) - } - } - // The above dealt with the expansion of the containing module, so now // we need to deal with the expansion of the resource itself across all // instances of the module. @@ -189,6 +138,32 @@ func (n *nodeExpandPlannableResource) DynamicExpand(ctx EvalContext) (*Graph, tf checkState.ReportCheckableObjects(n.NodeAbstractResource.Addr, n.expandedInstances) } + // Any resources that belong to module prefixes that aren't expanded yet + // get placeholder nodes that we'll use to record that they are deferred + // and produce a placeholder object for continued downstream partial + // evaluation. + // (This must come after calling n.expandResourceInstances because + // otherwise we won't have registered the expansion for the resource + // itself yet.) + possibleInstances := expander.UnknownResourceInstances(n.Addr) + for _, possibleInsts := range possibleInstances { + log.Printf("[TRACE] nodeExpandPlannableResource: exact instances not yet known for %s", possibleInsts) + n := &nodePartialExpandedResource{ + Addr: possibleInsts, + Config: n.Config, + Schema: n.Schema, + SchemaVersion: n.SchemaVersion, + ProvisionerSchemas: n.ProvisionerSchemas, + Targets: n.Targets, + ResolvedProvider: n.ResolvedProvider, + skipRefresh: n.skipRefresh, + skipPlanChanges: n.skipPlanChanges, + } + g.Add(n) + } + + n.expandResourceInstanceOrphans(&g, ctx, moduleInstances, possibleInstances) + addRootNodeToGraph(&g) return &g, diags @@ -327,6 +302,74 @@ func (n *nodeExpandPlannableResource) expandResourceInstances(globalCtx EvalCont return diags } +func (n *nodeExpandPlannableResource) expandResourceInstanceOrphans(g *Graph, ctx EvalContext, moduleInstances []addrs.ModuleInstance, possibleInstances addrs.Set[addrs.PartialExpandedResource]) error { + var diags tfdiags.Diagnostics + + // Lock the state while we inspect it + state := ctx.State().Lock() + + var orphans []*states.Resource + for _, res := range state.Resources(n.Addr) { + found := false + for _, m := range moduleInstances { + if m.Equal(res.Addr.Module) { + found = true + break + } + } + // The existing instance might belong to a resource or module whose + // expansion isn't known yet, so we don't know yet if it will still + // exist in desired state once the expansion is known; we'll just + // treat it as a placeholder for this run. + deferred := false + for _, possibleInsts := range possibleInstances { + if possibleInsts.MatchesResource(res.Addr) { + deferred = true + break + } + } + // The module instance of the resource in the state doesn't exist + // in the current config, so this whole resource is orphaned. + if !found && !deferred { + orphans = append(orphans, res) + } + } + + // We'll no longer use the state directly here, and the other functions + // we'll call below may use it so we'll release the lock. + state = nil + ctx.State().Unlock() + + // The concrete resource factory we'll use for orphans + concreteResourceOrphan := func(a *NodeAbstractResourceInstance) *NodePlannableResourceInstanceOrphan { + // Add the config and state since we don't do that via transforms + a.Config = n.Config + a.ResolvedProvider = n.ResolvedProvider + a.Schema = n.Schema + a.ProvisionerSchemas = n.ProvisionerSchemas + a.ProviderMetas = n.ProviderMetas + a.Dependencies = n.dependencies + + return &NodePlannableResourceInstanceOrphan{ + NodeAbstractResourceInstance: a, + skipRefresh: n.skipRefresh, + skipPlanChanges: n.skipPlanChanges, + } + } + + for _, res := range orphans { + for key := range res.Instances { + addr := res.Addr.Instance(key) + abs := NewNodeAbstractResourceInstance(addr) + abs.AttachResourceState(res) + n := concreteResourceOrphan(abs) + g.Add(n) + } + } + + return diags.ErrWithWarnings() +} + // Import blocks are expanded in conjunction with their associated resource block. func (n nodeExpandPlannableResource) expandResourceImports(ctx EvalContext, addr addrs.AbsResource, instanceAddrs []addrs.AbsResourceInstance) (addrs.Map[addrs.AbsResourceInstance, string], tfdiags.Diagnostics) { // Imports maps the target address to an import ID. diff --git a/internal/terraform/node_resource_plan_instance.go b/internal/terraform/node_resource_plan_instance.go index 6322097d5ae4..5737a0496392 100644 --- a/internal/terraform/node_resource_plan_instance.go +++ b/internal/terraform/node_resource_plan_instance.go @@ -355,8 +355,8 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext) // values, which could result in a post-condition check relying on that // value being inaccurate. Unless we decide to store the value of the // for-each expression in state, this is unavoidable. - forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx) - repeatData := EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach) + exp := ctx.InstanceExpander() + repeatData := exp.GetResourceInstanceRepetitionData(n.Addr) checkDiags := evalCheckRules( addrs.ResourcePrecondition, @@ -463,8 +463,9 @@ func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs. return nil, diags } - forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx) - keyData := EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach) + exp := ctx.InstanceExpander() + keyData := exp.GetResourceInstanceRepetitionData(n.Addr) + configVal, _, configDiags := ctx.EvaluateBlock(n.Config.Config, schema, nil, keyData) if configDiags.HasErrors() { // We have an overridden resource so we're definitely in a test and diff --git a/internal/terraform/node_resource_plan_unexpanded.go b/internal/terraform/node_resource_plan_unexpanded.go new file mode 100644 index 000000000000..0de268d1c129 --- /dev/null +++ b/internal/terraform/node_resource_plan_unexpanded.go @@ -0,0 +1,175 @@ +package terraform + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/configs" + "github.com/hashicorp/terraform/internal/configs/configschema" + "github.com/hashicorp/terraform/internal/instances" + "github.com/hashicorp/terraform/internal/plans/objchange" + "github.com/hashicorp/terraform/internal/tfdiags" + "github.com/zclconf/go-cty/cty" +) + +// nodePartialExpandedResource represents an undetermined set of resource +// instances that all share the same [addrs.ConfigResource] address but +// may have certain module instance keys known. +// +// Terraform uses nodes of this type to produce "placeholder plans" that +// are not applyable but approximate the final state of all of the instances +// by using unknown values to stand in for any values that might vary between +// the instances. The goal here is just to help the operator get a sense of +// how their resource configurations will be interpreted even when we don't +// have enough information to plan individual instances fully. +type nodePartialExpandedResource struct { + Addr addrs.PartialExpandedResource + + Config *configs.Resource + Schema *configschema.Block + SchemaVersion uint64 // Schema version of "Schema", as decided by the provider + + ProvisionerSchemas map[string]*configschema.Block + + // Set from GraphNodeTargetable + Targets []addrs.Targetable + + // The address of the provider this resource will use + ResolvedProvider addrs.AbsProviderConfig + + // skipRefresh indicates that we should skip refreshing individual instances + skipRefresh bool + + // skipPlanChanges indicates we should skip trying to plan change actions + // for any instances. + skipPlanChanges bool +} + +func (n *nodePartialExpandedResource) Name() string { + return n.Addr.String() +} + +var ( + _ GraphNodeModuleEvalScope = (*nodePartialExpandedResource)(nil) + _ GraphNodeExecutable = (*nodePartialExpandedResource)(nil) + _ GraphNodeReferenceable = (*nodePartialExpandedResource)(nil) + _ GraphNodeReferencer = (*nodePartialExpandedResource)(nil) +) + +// ModuleEvalScope implements GraphNodeModuleEvalScope +func (n *nodePartialExpandedResource) ModuleEvalScope() addrs.ModuleEvalScope { + // This could either be an addrs.ModuleInstance or an + // addrs.PartialExpandedModule depending on whether it's just the + // resource's own expansion that isn't known, or if some or all of the + // module address is also unknown. + return n.Addr.ModuleEvalScope() +} + +// Execute implements GraphNodeExecutable +func (n *nodePartialExpandedResource) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics { + // The ctx we get here can perform expression evaluation but might do so + // in the "partial evaluation" mode if this node is representing instances + // of a resource in a module whose expansion isn't known yet either. + log.Printf("[TRACE] nodePartialExpandedResource: Generate placeholder object for all instances matching %s", n.Addr) + + configVal, schema, diags := n.evaluateConfig(ctx, op) + if diags.HasErrors() { + return diags + } + + switch mode := n.Addr.Resource().Mode; mode { + case addrs.ManagedResourceMode: + return n.executeManagedResource(ctx, op, configVal, schema) + case addrs.DataResourceMode: + return n.executeDataResource(ctx, op, configVal, schema) + default: + panic(fmt.Sprintf("unsupported resource mode %s", mode)) + } +} + +func (n *nodePartialExpandedResource) evaluateConfig(ctx EvalContext, op walkOperation) (cty.Value, *configschema.Block, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + + // TODO: Preconditions + + _, providerSchema, err := getProvider(ctx, n.ResolvedProvider) + diags = diags.Append(err) + if diags.HasErrors() { + return cty.DynamicVal, nil, diags + } + + config := n.Config + schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.Resource()) + if schema == nil { + // Should be caught during validation, so we don't bother with a pretty error here + diags = diags.Append(fmt.Errorf("provider does not support resource type %q", n.Addr.Resource().Type)) + return cty.DynamicVal, nil, diags + } + + var keyData instances.RepetitionData + switch { + case config.ForEach != nil: + // TODO: Somehow determine the for_each type here, ideally without + // re-evaluating it, so that the keyData can have a more specific + // type constraint for its each.value value. + keyData = instances.UnknownForEachRepetitionData(cty.DynamicPseudoType) + case config.Count != nil: + keyData = instances.UnknownCountRepetitionData + } + + configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) + diags = diags.Append(configDiags) + return configVal, schema, diags +} + +func (n *nodePartialExpandedResource) executeManagedResource(ctx EvalContext, op walkOperation, configVal cty.Value, schema *configschema.Block) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + + // TODO: Ask the provider to validate the configuration. + + proposedNewVal := objchange.ProposedNew(schema, cty.NullVal(schema.ImpliedType()), configVal) + + // TODO: Ask the provider to PlanResourceChange with the proposed new + // value so we can find out about any plan-time-checked problems early + // and to potentially generate a more complete placeholder value. + + log.Printf("[TRACE] nodePartialExpandedResource: all %s are %#v", n.Addr, proposedNewVal) + + // TODO: Postconditions + + return diags +} + +func (n *nodePartialExpandedResource) executeDataResource(ctx EvalContext, op walkOperation, configVal cty.Value, schema *configschema.Block) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + + // TODO: Ask the provider to validate the configuration. + + // TODO: If the configuration is fully known and the dependencies have no + // pending changes then we should proactively read the data source now + // and use its result as the placeholder for all instances of this + // resource. + + // TODO: If the configuration isn't fully known then we should put a plan + // to read all instances of this data resource into the bucket of deferred + // actions. + proposedNewVal := objchange.PlannedDataResourceObject(schema, configVal) + log.Printf("[TRACE] nodePartialExpandedResource: all %s are %#v", n.Addr, proposedNewVal) + + // TODO: Postconditions + + return diags +} + +// GraphNodeReferenceable +func (n *nodePartialExpandedResource) ReferenceableAddrs() []addrs.Referenceable { + return []addrs.Referenceable{ + n.Addr.ConfigResource().Resource, + } +} + +// GraphNodeReferencer +func (n *nodePartialExpandedResource) References() []*addrs.Reference { + return referencesForResource(n.Addr.ConfigResource(), n.Config, n.Schema, n.ProvisionerSchemas) +} diff --git a/internal/terraform/node_root_variable.go b/internal/terraform/node_root_variable.go index 3152d8427db0..29cc4b1aa2b2 100644 --- a/internal/terraform/node_root_variable.go +++ b/internal/terraform/node_root_variable.go @@ -111,7 +111,7 @@ func (n *NodeRootVariable) Execute(ctx EvalContext, op walkOperation) tfdiags.Di return diags } - ctx.SetRootModuleArgument(addr.Variable, finalVal) + ctx.NamedValues().SetInputVariableValue(addr, finalVal) if !n.DestroyApply { diags = diags.Append(evalVariableValidations( diff --git a/internal/terraform/node_root_variable_test.go b/internal/terraform/node_root_variable_test.go index d92bc9dbec61..696dee6be7e3 100644 --- a/internal/terraform/node_root_variable_test.go +++ b/internal/terraform/node_root_variable_test.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform/internal/checks" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/lang" + "github.com/hashicorp/terraform/internal/namedvals" ) func TestNodeRootVariableExecute(t *testing.T) { @@ -33,18 +34,18 @@ func TestNodeRootVariableExecute(t *testing.T) { }, } + ctx.NamedValuesState = namedvals.NewState() + diags := n.Execute(ctx, walkApply) if diags.HasErrors() { t.Fatalf("unexpected error: %s", diags.Err()) } - if !ctx.SetRootModuleArgumentCalled { - t.Fatalf("ctx.SetRootModuleArgument wasn't called") - } - if got, want := ctx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want { - t.Errorf("wrong address for ctx.SetRootModuleArgument\ngot: %s\nwant: %s", got, want) + absAddr := addrs.RootModuleInstance.InputVariable(n.Addr.Name) + if !ctx.NamedValues().HasInputVariableValue(absAddr) { + t.Fatalf("no result was registered") } - if got, want := ctx.SetRootModuleArgumentValue, cty.StringVal("true"); !want.RawEquals(got) { + if got, want := ctx.NamedValues().GetInputVariableValue(absAddr), cty.StringVal("true"); !want.RawEquals(got) { // NOTE: The given value was cty.Bool but the type constraint was // cty.String, so it was NodeRootVariable's responsibility to convert // as part of preparing the "final value". @@ -54,30 +55,13 @@ func TestNodeRootVariableExecute(t *testing.T) { t.Run("validation", func(t *testing.T) { ctx := new(MockEvalContext) + ctx.NamedValuesState = namedvals.NewState() + // The variable validation function gets called with Terraform's // built-in functions available, so we need a minimal scope just for // it to get the functions from. ctx.EvaluationScopeScope = &lang.Scope{} - // We need to reimplement a _little_ bit of EvalContextBuiltin logic - // here to get a similar effect with EvalContextMock just to get the - // value to flow through here in a realistic way that'll make this test - // useful. - var finalVal cty.Value - ctx.SetRootModuleArgumentFunc = func(addr addrs.InputVariable, v cty.Value) { - if addr.Name == "foo" { - t.Logf("set %s to %#v", addr.String(), v) - finalVal = v - } - } - ctx.GetVariableValueFunc = func(addr addrs.AbsInputVariableInstance) cty.Value { - if addr.String() != "var.foo" { - return cty.NilVal - } - t.Logf("reading final val for %s (%#v)", addr.String(), finalVal) - return finalVal - } - n := &NodeRootVariable{ Addr: addrs.InputVariable{Name: "foo"}, Config: &configs.Variable{ @@ -132,13 +116,11 @@ func TestNodeRootVariableExecute(t *testing.T) { t.Fatalf("unexpected error: %s", diags.Err()) } - if !ctx.SetRootModuleArgumentCalled { - t.Fatalf("ctx.SetRootModuleArgument wasn't called") - } - if got, want := ctx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want { - t.Errorf("wrong address for ctx.SetRootModuleArgument\ngot: %s\nwant: %s", got, want) + absAddr := addrs.RootModuleInstance.InputVariable(n.Addr.Name) + if !ctx.NamedValues().HasInputVariableValue(absAddr) { + t.Fatalf("no result value for input variable") } - if got, want := ctx.SetRootModuleArgumentValue, cty.NumberIntVal(5); !want.RawEquals(got) { + if got, want := ctx.NamedValues().GetInputVariableValue(absAddr), cty.NumberIntVal(5); !want.RawEquals(got) { // NOTE: The given value was cty.Bool but the type constraint was // cty.String, so it was NodeRootVariable's responsibility to convert // as part of preparing the "final value". diff --git a/internal/terraform/test_context.go b/internal/terraform/test_context.go index b9249892de36..c2933a50f297 100644 --- a/internal/terraform/test_context.go +++ b/internal/terraform/test_context.go @@ -5,7 +5,6 @@ package terraform import ( "fmt" - "sync" "github.com/hashicorp/hcl/v2" "github.com/zclconf/go-cty/cty" @@ -15,6 +14,7 @@ import ( "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/lang" "github.com/hashicorp/terraform/internal/moduletest" + "github.com/hashicorp/terraform/internal/namedvals" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/tfdiags" @@ -75,16 +75,15 @@ func (ctx *TestContext) evaluationStateData(alternateStates map[string]*evaluati return &evaluationStateData{ Evaluator: &Evaluator{ - Operation: operation, - Meta: ctx.meta, - Config: ctx.Config, - Plugins: ctx.plugins, - State: ctx.State.SyncWrapper(), - Changes: ctx.Plan.Changes.SyncWrapper(), - AlternateStates: alternateStates, - VariableValues: variableValues, - VariableValuesLock: new(sync.Mutex), - PlanTimestamp: ctx.Plan.Timestamp, + Operation: operation, + Meta: ctx.meta, + Config: ctx.Config, + Plugins: ctx.plugins, + State: ctx.State.SyncWrapper(), + Changes: ctx.Plan.Changes.SyncWrapper(), + AlternateStates: alternateStates, + NamedValues: namedvals.NewState(), + PlanTimestamp: ctx.Plan.Timestamp, }, ModulePath: nil, // nil for the root module InstanceKeyData: EvalDataForNoInstanceKey, diff --git a/internal/terraform/transform_orphan_output.go b/internal/terraform/transform_orphan_output.go index 7a8406e80fad..866d6e9dd999 100644 --- a/internal/terraform/transform_orphan_output.go +++ b/internal/terraform/transform_orphan_output.go @@ -26,37 +26,13 @@ func (t *OrphanOutputTransformer) Transform(g *Graph) error { return nil } - for _, ms := range t.State.Modules { - if err := t.transform(g, ms); err != nil { - return err - } - } - return nil -} - -func (t *OrphanOutputTransformer) transform(g *Graph, ms *states.Module) error { - if ms == nil { - return nil - } - - moduleAddr := ms.Addr - - // Get the config for this path, which is nil if the entire module has been - // removed. - var outputs map[string]*configs.Output - if c := t.Config.DescendentForInstance(moduleAddr); c != nil { - outputs = c.Module.Outputs - } - - // An output is "orphaned" if it's present in the state but not declared - // in the configuration. - for name := range ms.OutputValues { - if _, exists := outputs[name]; exists { + cfgs := t.Config.Module.Outputs + for name := range t.State.RootOutputValues { + if _, exists := cfgs[name]; exists { continue } - g.Add(&NodeDestroyableOutput{ - Addr: addrs.OutputValue{Name: name}.Absolute(moduleAddr), + Addr: addrs.OutputValue{Name: name}.Absolute(addrs.RootModuleInstance), Planning: t.Planning, }) } diff --git a/internal/terraform/transform_reference.go b/internal/terraform/transform_reference.go index a6f4a82ef0d5..86f79a827285 100644 --- a/internal/terraform/transform_reference.go +++ b/internal/terraform/transform_reference.go @@ -24,8 +24,6 @@ import ( // be referenced and other methods of referencing may still be possible (such // as by path!) type GraphNodeReferenceable interface { - GraphNodeModulePath - // ReferenceableAddrs returns a list of addresses through which this can be // referenced. ReferenceableAddrs() []addrs.Referenceable @@ -34,8 +32,6 @@ type GraphNodeReferenceable interface { // GraphNodeReferencer must be implemented by nodes that reference other // Terraform items and therefore depend on them. type GraphNodeReferencer interface { - GraphNodeModulePath - // References returns a list of references made by this node, which // include both a referenced address and source location information for // the reference. diff --git a/internal/terraform/update_state_hook_test.go b/internal/terraform/update_state_hook_test.go index efca41e82e98..c7e1b6f28c96 100644 --- a/internal/terraform/update_state_hook_test.go +++ b/internal/terraform/update_state_hook_test.go @@ -17,7 +17,10 @@ func TestUpdateStateHook(t *testing.T) { mockHook := new(MockHook) state := states.NewState() - state.Module(addrs.RootModuleInstance).SetLocalValue("foo", cty.StringVal("hello")) + state.SetOutputValue( + addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance), + cty.StringVal("hello"), false, + ) ctx := new(MockEvalContext) ctx.HookHook = mockHook @@ -30,7 +33,7 @@ func TestUpdateStateHook(t *testing.T) { if !mockHook.PostStateUpdateCalled { t.Fatal("should call PostStateUpdate") } - if mockHook.PostStateUpdateState.LocalValue(addrs.LocalValue{Name: "foo"}.Absolute(addrs.RootModuleInstance)) != cty.StringVal("hello") { + if os := mockHook.PostStateUpdateState.OutputValue(addrs.OutputValue{Name: "foo"}.Absolute(addrs.RootModuleInstance)); os != nil && os.Value != cty.StringVal("hello") { t.Fatalf("wrong state passed to hook: %s", spew.Sdump(mockHook.PostStateUpdateState)) } } diff --git a/internal/terraform/upgrade_resource_state.go b/internal/terraform/upgrade_resource_state.go index 659f991481e1..c81ed82130c4 100644 --- a/internal/terraform/upgrade_resource_state.go +++ b/internal/terraform/upgrade_resource_state.go @@ -8,6 +8,7 @@ import ( "fmt" "log" + "github.com/hashicorp/hcl/v2" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/providers" @@ -92,6 +93,19 @@ func upgradeResourceState(addr addrs.AbsResourceInstance, provider providers.Int resp := provider.UpgradeResourceState(req) diags := resp.Diagnostics + if len(resp.Deferred) != 0 { + // We don't yet support deferrals really, so for now we'll just treat + // them as errors. This is only a temporary shortcut and should not + // ship in any stable Terraform release. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Not enough information to upgrade", + Detail: fmt.Sprintf( + "The configuration of either %s or its provider contains unknown values that prevent planning.", + addr.String(), + ), + }) + } if diags.HasErrors() { return nil, diags } diff --git a/internal/tfplugin6/tfplugin6.pb.go b/internal/tfplugin6/tfplugin6.pb.go index 894a712a9eff..d30469896c27 100644 --- a/internal/tfplugin6/tfplugin6.pb.go +++ b/internal/tfplugin6/tfplugin6.pb.go @@ -1,9 +1,6 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -// Terraform Plugin RPC protocol version 6.4 +// Terraform Plugin RPC protocol version 6.5 // -// This file defines version 6.4 of the RPC protocol. To implement a plugin +// This file defines version 6.5 of the RPC protocol. To implement a plugin // against this protocol, copy this definition into your own codebase and // use protoc to generate stubs for your target language. // @@ -650,6 +647,116 @@ func (x *ServerCapabilities) GetGetProviderSchemaOptional() bool { return false } +// DeferredAction represents a reason why a particular action cannot be taken +// until Terraform can provide concrete values instead of unknown value +// placeholders. +type DeferredAction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Reason: + // + // *DeferredAction_OtherReason_ + // *DeferredAction_ProviderConfigUnknown + // *DeferredAction_ResourceConfigUnknown + Reason isDeferredAction_Reason `protobuf_oneof:"reason"` +} + +func (x *DeferredAction) Reset() { + *x = DeferredAction{} + if protoimpl.UnsafeEnabled { + mi := &file_tfplugin6_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeferredAction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeferredAction) ProtoMessage() {} + +func (x *DeferredAction) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeferredAction.ProtoReflect.Descriptor instead. +func (*DeferredAction) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{7} +} + +func (m *DeferredAction) GetReason() isDeferredAction_Reason { + if m != nil { + return m.Reason + } + return nil +} + +func (x *DeferredAction) GetOtherReason() *DeferredAction_OtherReason { + if x, ok := x.GetReason().(*DeferredAction_OtherReason_); ok { + return x.OtherReason + } + return nil +} + +func (x *DeferredAction) GetProviderConfigUnknown() *DeferredAction_ConfigUnknown { + if x, ok := x.GetReason().(*DeferredAction_ProviderConfigUnknown); ok { + return x.ProviderConfigUnknown + } + return nil +} + +func (x *DeferredAction) GetResourceConfigUnknown() *DeferredAction_ConfigUnknown { + if x, ok := x.GetReason().(*DeferredAction_ResourceConfigUnknown); ok { + return x.ResourceConfigUnknown + } + return nil +} + +type isDeferredAction_Reason interface { + isDeferredAction_Reason() +} + +type DeferredAction_OtherReason_ struct { + // other_reason is a fallback reason to use if none of the other + // specific reasons seem appropriate. Terraform will show a generic + // message in the UI in this case, acknowledging that the operation + // was deferred but with no specific reason why. Terraform Core will + // also treat any unrecognized reason type defined in later versions + // of this protocol as if they were other_reason. + OtherReason *DeferredAction_OtherReason `protobuf:"bytes,1,opt,name=other_reason,json=otherReason,proto3,oneof"` +} + +type DeferredAction_ProviderConfigUnknown struct { + // provider_config_unknown represents that the action was deferred + // because a necessary part of the corresponding provider configuration + // is not yet known enough to proceed. + ProviderConfigUnknown *DeferredAction_ConfigUnknown `protobuf:"bytes,2,opt,name=provider_config_unknown,json=providerConfigUnknown,proto3,oneof"` +} + +type DeferredAction_ResourceConfigUnknown struct { + // resource_config_unknown represents that the action was deferred + // because a necessary part of the resource configuration + // is not yet known enough to proceed. + ResourceConfigUnknown *DeferredAction_ConfigUnknown `protobuf:"bytes,3,opt,name=resource_config_unknown,json=resourceConfigUnknown,proto3,oneof"` +} + +func (*DeferredAction_OtherReason_) isDeferredAction_Reason() {} + +func (*DeferredAction_ProviderConfigUnknown) isDeferredAction_Reason() {} + +func (*DeferredAction_ResourceConfigUnknown) isDeferredAction_Reason() {} + type GetMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -659,7 +766,7 @@ type GetMetadata struct { func (x *GetMetadata) Reset() { *x = GetMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[7] + mi := &file_tfplugin6_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -672,7 +779,7 @@ func (x *GetMetadata) String() string { func (*GetMetadata) ProtoMessage() {} func (x *GetMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[7] + mi := &file_tfplugin6_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -685,7 +792,7 @@ func (x *GetMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMetadata.ProtoReflect.Descriptor instead. func (*GetMetadata) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{7} + return file_tfplugin6_proto_rawDescGZIP(), []int{8} } type GetProviderSchema struct { @@ -697,7 +804,7 @@ type GetProviderSchema struct { func (x *GetProviderSchema) Reset() { *x = GetProviderSchema{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[8] + mi := &file_tfplugin6_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -710,7 +817,7 @@ func (x *GetProviderSchema) String() string { func (*GetProviderSchema) ProtoMessage() {} func (x *GetProviderSchema) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[8] + mi := &file_tfplugin6_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -723,7 +830,7 @@ func (x *GetProviderSchema) ProtoReflect() protoreflect.Message { // Deprecated: Use GetProviderSchema.ProtoReflect.Descriptor instead. func (*GetProviderSchema) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{8} + return file_tfplugin6_proto_rawDescGZIP(), []int{9} } type ValidateProviderConfig struct { @@ -735,7 +842,7 @@ type ValidateProviderConfig struct { func (x *ValidateProviderConfig) Reset() { *x = ValidateProviderConfig{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[9] + mi := &file_tfplugin6_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -748,7 +855,7 @@ func (x *ValidateProviderConfig) String() string { func (*ValidateProviderConfig) ProtoMessage() {} func (x *ValidateProviderConfig) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[9] + mi := &file_tfplugin6_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -761,7 +868,7 @@ func (x *ValidateProviderConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateProviderConfig.ProtoReflect.Descriptor instead. func (*ValidateProviderConfig) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{9} + return file_tfplugin6_proto_rawDescGZIP(), []int{10} } type UpgradeResourceState struct { @@ -773,7 +880,7 @@ type UpgradeResourceState struct { func (x *UpgradeResourceState) Reset() { *x = UpgradeResourceState{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[10] + mi := &file_tfplugin6_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -786,7 +893,7 @@ func (x *UpgradeResourceState) String() string { func (*UpgradeResourceState) ProtoMessage() {} func (x *UpgradeResourceState) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[10] + mi := &file_tfplugin6_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -799,7 +906,7 @@ func (x *UpgradeResourceState) ProtoReflect() protoreflect.Message { // Deprecated: Use UpgradeResourceState.ProtoReflect.Descriptor instead. func (*UpgradeResourceState) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{10} + return file_tfplugin6_proto_rawDescGZIP(), []int{11} } type ValidateResourceConfig struct { @@ -811,7 +918,7 @@ type ValidateResourceConfig struct { func (x *ValidateResourceConfig) Reset() { *x = ValidateResourceConfig{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[11] + mi := &file_tfplugin6_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -824,7 +931,7 @@ func (x *ValidateResourceConfig) String() string { func (*ValidateResourceConfig) ProtoMessage() {} func (x *ValidateResourceConfig) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[11] + mi := &file_tfplugin6_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -837,7 +944,7 @@ func (x *ValidateResourceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateResourceConfig.ProtoReflect.Descriptor instead. func (*ValidateResourceConfig) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{11} + return file_tfplugin6_proto_rawDescGZIP(), []int{12} } type ValidateDataResourceConfig struct { @@ -849,7 +956,7 @@ type ValidateDataResourceConfig struct { func (x *ValidateDataResourceConfig) Reset() { *x = ValidateDataResourceConfig{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[12] + mi := &file_tfplugin6_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -862,7 +969,7 @@ func (x *ValidateDataResourceConfig) String() string { func (*ValidateDataResourceConfig) ProtoMessage() {} func (x *ValidateDataResourceConfig) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[12] + mi := &file_tfplugin6_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -875,7 +982,7 @@ func (x *ValidateDataResourceConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateDataResourceConfig.ProtoReflect.Descriptor instead. func (*ValidateDataResourceConfig) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{12} + return file_tfplugin6_proto_rawDescGZIP(), []int{13} } type ConfigureProvider struct { @@ -887,7 +994,7 @@ type ConfigureProvider struct { func (x *ConfigureProvider) Reset() { *x = ConfigureProvider{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[13] + mi := &file_tfplugin6_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -900,7 +1007,7 @@ func (x *ConfigureProvider) String() string { func (*ConfigureProvider) ProtoMessage() {} func (x *ConfigureProvider) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[13] + mi := &file_tfplugin6_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -913,7 +1020,7 @@ func (x *ConfigureProvider) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureProvider.ProtoReflect.Descriptor instead. func (*ConfigureProvider) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{13} + return file_tfplugin6_proto_rawDescGZIP(), []int{14} } type ReadResource struct { @@ -925,7 +1032,7 @@ type ReadResource struct { func (x *ReadResource) Reset() { *x = ReadResource{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[14] + mi := &file_tfplugin6_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -938,7 +1045,7 @@ func (x *ReadResource) String() string { func (*ReadResource) ProtoMessage() {} func (x *ReadResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[14] + mi := &file_tfplugin6_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -951,7 +1058,7 @@ func (x *ReadResource) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadResource.ProtoReflect.Descriptor instead. func (*ReadResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{14} + return file_tfplugin6_proto_rawDescGZIP(), []int{15} } type PlanResourceChange struct { @@ -963,7 +1070,7 @@ type PlanResourceChange struct { func (x *PlanResourceChange) Reset() { *x = PlanResourceChange{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[15] + mi := &file_tfplugin6_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -976,7 +1083,7 @@ func (x *PlanResourceChange) String() string { func (*PlanResourceChange) ProtoMessage() {} func (x *PlanResourceChange) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[15] + mi := &file_tfplugin6_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -989,7 +1096,7 @@ func (x *PlanResourceChange) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanResourceChange.ProtoReflect.Descriptor instead. func (*PlanResourceChange) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{15} + return file_tfplugin6_proto_rawDescGZIP(), []int{16} } type ApplyResourceChange struct { @@ -1001,7 +1108,7 @@ type ApplyResourceChange struct { func (x *ApplyResourceChange) Reset() { *x = ApplyResourceChange{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[16] + mi := &file_tfplugin6_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1014,7 +1121,7 @@ func (x *ApplyResourceChange) String() string { func (*ApplyResourceChange) ProtoMessage() {} func (x *ApplyResourceChange) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[16] + mi := &file_tfplugin6_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1027,7 +1134,7 @@ func (x *ApplyResourceChange) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyResourceChange.ProtoReflect.Descriptor instead. func (*ApplyResourceChange) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{16} + return file_tfplugin6_proto_rawDescGZIP(), []int{17} } type ImportResourceState struct { @@ -1039,7 +1146,7 @@ type ImportResourceState struct { func (x *ImportResourceState) Reset() { *x = ImportResourceState{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[17] + mi := &file_tfplugin6_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1052,7 +1159,7 @@ func (x *ImportResourceState) String() string { func (*ImportResourceState) ProtoMessage() {} func (x *ImportResourceState) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[17] + mi := &file_tfplugin6_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1065,7 +1172,7 @@ func (x *ImportResourceState) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportResourceState.ProtoReflect.Descriptor instead. func (*ImportResourceState) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{17} + return file_tfplugin6_proto_rawDescGZIP(), []int{18} } type ReadDataSource struct { @@ -1077,7 +1184,7 @@ type ReadDataSource struct { func (x *ReadDataSource) Reset() { *x = ReadDataSource{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[18] + mi := &file_tfplugin6_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1090,7 +1197,7 @@ func (x *ReadDataSource) String() string { func (*ReadDataSource) ProtoMessage() {} func (x *ReadDataSource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[18] + mi := &file_tfplugin6_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1103,7 +1210,7 @@ func (x *ReadDataSource) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadDataSource.ProtoReflect.Descriptor instead. func (*ReadDataSource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{18} + return file_tfplugin6_proto_rawDescGZIP(), []int{19} } type AttributePath_Step struct { @@ -1122,7 +1229,7 @@ type AttributePath_Step struct { func (x *AttributePath_Step) Reset() { *x = AttributePath_Step{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[19] + mi := &file_tfplugin6_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1135,7 +1242,7 @@ func (x *AttributePath_Step) String() string { func (*AttributePath_Step) ProtoMessage() {} func (x *AttributePath_Step) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[19] + mi := &file_tfplugin6_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1214,7 +1321,7 @@ type StopProvider_Request struct { func (x *StopProvider_Request) Reset() { *x = StopProvider_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[20] + mi := &file_tfplugin6_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1227,7 +1334,7 @@ func (x *StopProvider_Request) String() string { func (*StopProvider_Request) ProtoMessage() {} func (x *StopProvider_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[20] + mi := &file_tfplugin6_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1254,7 +1361,7 @@ type StopProvider_Response struct { func (x *StopProvider_Response) Reset() { *x = StopProvider_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[21] + mi := &file_tfplugin6_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1267,7 +1374,7 @@ func (x *StopProvider_Response) String() string { func (*StopProvider_Response) ProtoMessage() {} func (x *StopProvider_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[21] + mi := &file_tfplugin6_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1306,7 +1413,7 @@ type Schema_Block struct { func (x *Schema_Block) Reset() { *x = Schema_Block{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[23] + mi := &file_tfplugin6_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1319,7 +1426,7 @@ func (x *Schema_Block) String() string { func (*Schema_Block) ProtoMessage() {} func (x *Schema_Block) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[23] + mi := &file_tfplugin6_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1397,7 +1504,7 @@ type Schema_Attribute struct { func (x *Schema_Attribute) Reset() { *x = Schema_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[24] + mi := &file_tfplugin6_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1410,7 +1517,7 @@ func (x *Schema_Attribute) String() string { func (*Schema_Attribute) ProtoMessage() {} func (x *Schema_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[24] + mi := &file_tfplugin6_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1511,7 +1618,7 @@ type Schema_NestedBlock struct { func (x *Schema_NestedBlock) Reset() { *x = Schema_NestedBlock{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[25] + mi := &file_tfplugin6_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1524,7 +1631,7 @@ func (x *Schema_NestedBlock) String() string { func (*Schema_NestedBlock) ProtoMessage() {} func (x *Schema_NestedBlock) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[25] + mi := &file_tfplugin6_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1594,7 +1701,7 @@ type Schema_Object struct { func (x *Schema_Object) Reset() { *x = Schema_Object{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[26] + mi := &file_tfplugin6_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1607,7 +1714,7 @@ func (x *Schema_Object) String() string { func (*Schema_Object) ProtoMessage() {} func (x *Schema_Object) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[26] + mi := &file_tfplugin6_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1653,6 +1760,95 @@ func (x *Schema_Object) GetMaxItems() int64 { return 0 } +type DeferredAction_OtherReason struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeferredAction_OtherReason) Reset() { + *x = DeferredAction_OtherReason{} + if protoimpl.UnsafeEnabled { + mi := &file_tfplugin6_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeferredAction_OtherReason) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeferredAction_OtherReason) ProtoMessage() {} + +func (x *DeferredAction_OtherReason) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeferredAction_OtherReason.ProtoReflect.Descriptor instead. +func (*DeferredAction_OtherReason) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{7, 0} +} + +type DeferredAction_ConfigUnknown struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The path to the attribute whose unknown value caused the deferral. + // Provide as precise a path as possible, but it's okay to describe + // a shorter path if e.g. the problem is inside a set element and + // therefore not fully addressable as an AttributePath. + Attribute *AttributePath `protobuf:"bytes,1,opt,name=attribute,proto3" json:"attribute,omitempty"` +} + +func (x *DeferredAction_ConfigUnknown) Reset() { + *x = DeferredAction_ConfigUnknown{} + if protoimpl.UnsafeEnabled { + mi := &file_tfplugin6_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeferredAction_ConfigUnknown) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeferredAction_ConfigUnknown) ProtoMessage() {} + +func (x *DeferredAction_ConfigUnknown) ProtoReflect() protoreflect.Message { + mi := &file_tfplugin6_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeferredAction_ConfigUnknown.ProtoReflect.Descriptor instead. +func (*DeferredAction_ConfigUnknown) Descriptor() ([]byte, []int) { + return file_tfplugin6_proto_rawDescGZIP(), []int{7, 1} +} + +func (x *DeferredAction_ConfigUnknown) GetAttribute() *AttributePath { + if x != nil { + return x.Attribute + } + return nil +} + type GetMetadata_Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1662,7 +1858,7 @@ type GetMetadata_Request struct { func (x *GetMetadata_Request) Reset() { *x = GetMetadata_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[27] + mi := &file_tfplugin6_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1675,7 +1871,7 @@ func (x *GetMetadata_Request) String() string { func (*GetMetadata_Request) ProtoMessage() {} func (x *GetMetadata_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[27] + mi := &file_tfplugin6_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1688,7 +1884,7 @@ func (x *GetMetadata_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMetadata_Request.ProtoReflect.Descriptor instead. func (*GetMetadata_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{7, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{8, 0} } type GetMetadata_Response struct { @@ -1705,7 +1901,7 @@ type GetMetadata_Response struct { func (x *GetMetadata_Response) Reset() { *x = GetMetadata_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[28] + mi := &file_tfplugin6_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1718,7 +1914,7 @@ func (x *GetMetadata_Response) String() string { func (*GetMetadata_Response) ProtoMessage() {} func (x *GetMetadata_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[28] + mi := &file_tfplugin6_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1731,7 +1927,7 @@ func (x *GetMetadata_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMetadata_Response.ProtoReflect.Descriptor instead. func (*GetMetadata_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{7, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{8, 1} } func (x *GetMetadata_Response) GetServerCapabilities() *ServerCapabilities { @@ -1773,7 +1969,7 @@ type GetMetadata_DataSourceMetadata struct { func (x *GetMetadata_DataSourceMetadata) Reset() { *x = GetMetadata_DataSourceMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[29] + mi := &file_tfplugin6_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1786,7 +1982,7 @@ func (x *GetMetadata_DataSourceMetadata) String() string { func (*GetMetadata_DataSourceMetadata) ProtoMessage() {} func (x *GetMetadata_DataSourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[29] + mi := &file_tfplugin6_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1799,7 +1995,7 @@ func (x *GetMetadata_DataSourceMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMetadata_DataSourceMetadata.ProtoReflect.Descriptor instead. func (*GetMetadata_DataSourceMetadata) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{7, 2} + return file_tfplugin6_proto_rawDescGZIP(), []int{8, 2} } func (x *GetMetadata_DataSourceMetadata) GetTypeName() string { @@ -1820,7 +2016,7 @@ type GetMetadata_ResourceMetadata struct { func (x *GetMetadata_ResourceMetadata) Reset() { *x = GetMetadata_ResourceMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[30] + mi := &file_tfplugin6_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1833,7 +2029,7 @@ func (x *GetMetadata_ResourceMetadata) String() string { func (*GetMetadata_ResourceMetadata) ProtoMessage() {} func (x *GetMetadata_ResourceMetadata) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[30] + mi := &file_tfplugin6_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1846,7 +2042,7 @@ func (x *GetMetadata_ResourceMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMetadata_ResourceMetadata.ProtoReflect.Descriptor instead. func (*GetMetadata_ResourceMetadata) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{7, 3} + return file_tfplugin6_proto_rawDescGZIP(), []int{8, 3} } func (x *GetMetadata_ResourceMetadata) GetTypeName() string { @@ -1865,7 +2061,7 @@ type GetProviderSchema_Request struct { func (x *GetProviderSchema_Request) Reset() { *x = GetProviderSchema_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[31] + mi := &file_tfplugin6_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1878,7 +2074,7 @@ func (x *GetProviderSchema_Request) String() string { func (*GetProviderSchema_Request) ProtoMessage() {} func (x *GetProviderSchema_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[31] + mi := &file_tfplugin6_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1891,7 +2087,7 @@ func (x *GetProviderSchema_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use GetProviderSchema_Request.ProtoReflect.Descriptor instead. func (*GetProviderSchema_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{8, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{9, 0} } type GetProviderSchema_Response struct { @@ -1910,7 +2106,7 @@ type GetProviderSchema_Response struct { func (x *GetProviderSchema_Response) Reset() { *x = GetProviderSchema_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[32] + mi := &file_tfplugin6_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1923,7 +2119,7 @@ func (x *GetProviderSchema_Response) String() string { func (*GetProviderSchema_Response) ProtoMessage() {} func (x *GetProviderSchema_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[32] + mi := &file_tfplugin6_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1936,7 +2132,7 @@ func (x *GetProviderSchema_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use GetProviderSchema_Response.ProtoReflect.Descriptor instead. func (*GetProviderSchema_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{8, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{9, 1} } func (x *GetProviderSchema_Response) GetProvider() *Schema { @@ -1992,7 +2188,7 @@ type ValidateProviderConfig_Request struct { func (x *ValidateProviderConfig_Request) Reset() { *x = ValidateProviderConfig_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[35] + mi := &file_tfplugin6_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2005,7 +2201,7 @@ func (x *ValidateProviderConfig_Request) String() string { func (*ValidateProviderConfig_Request) ProtoMessage() {} func (x *ValidateProviderConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[35] + mi := &file_tfplugin6_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2018,7 +2214,7 @@ func (x *ValidateProviderConfig_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateProviderConfig_Request.ProtoReflect.Descriptor instead. func (*ValidateProviderConfig_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{9, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{10, 0} } func (x *ValidateProviderConfig_Request) GetConfig() *DynamicValue { @@ -2039,7 +2235,7 @@ type ValidateProviderConfig_Response struct { func (x *ValidateProviderConfig_Response) Reset() { *x = ValidateProviderConfig_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[36] + mi := &file_tfplugin6_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2052,7 +2248,7 @@ func (x *ValidateProviderConfig_Response) String() string { func (*ValidateProviderConfig_Response) ProtoMessage() {} func (x *ValidateProviderConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[36] + mi := &file_tfplugin6_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2065,7 +2261,7 @@ func (x *ValidateProviderConfig_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateProviderConfig_Response.ProtoReflect.Descriptor instead. func (*ValidateProviderConfig_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{9, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{10, 1} } func (x *ValidateProviderConfig_Response) GetDiagnostics() []*Diagnostic { @@ -2098,12 +2294,18 @@ type UpgradeResourceState_Request struct { // appropriate older schema. The raw_state will be the json encoded // state, or a legacy flat-mapped format. RawState *RawState `protobuf:"bytes,3,opt,name=raw_state,json=rawState,proto3" json:"raw_state,omitempty"` + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to upgrade the state date to the + // latest schema version. + DeferAllowed bool `protobuf:"varint,4,opt,name=defer_allowed,json=deferAllowed,proto3" json:"defer_allowed,omitempty"` } func (x *UpgradeResourceState_Request) Reset() { *x = UpgradeResourceState_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[37] + mi := &file_tfplugin6_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2116,7 +2318,7 @@ func (x *UpgradeResourceState_Request) String() string { func (*UpgradeResourceState_Request) ProtoMessage() {} func (x *UpgradeResourceState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[37] + mi := &file_tfplugin6_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2129,7 +2331,7 @@ func (x *UpgradeResourceState_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use UpgradeResourceState_Request.ProtoReflect.Descriptor instead. func (*UpgradeResourceState_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{10, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{11, 0} } func (x *UpgradeResourceState_Request) GetTypeName() string { @@ -2153,6 +2355,13 @@ func (x *UpgradeResourceState_Request) GetRawState() *RawState { return nil } +func (x *UpgradeResourceState_Request) GetDeferAllowed() bool { + if x != nil { + return x.DeferAllowed + } + return false +} + type UpgradeResourceState_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2166,12 +2375,22 @@ type UpgradeResourceState_Response struct { // be safely resolved, and warnings about any possibly-risky assumptions made // in the upgrade process. Diagnostics []*Diagnostic `protobuf:"bytes,2,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will treat the object as completely unknown + // while planning downstream actions. Providers should avoid deferring + // an upgrade if at all possible, by implementing upgrade logic entirely + // within the provider and not accessing any external system. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why upgrading is + // impossible. + Deferred []*DeferredAction `protobuf:"bytes,3,rep,name=deferred,proto3" json:"deferred,omitempty"` } func (x *UpgradeResourceState_Response) Reset() { *x = UpgradeResourceState_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[38] + mi := &file_tfplugin6_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2184,7 +2403,7 @@ func (x *UpgradeResourceState_Response) String() string { func (*UpgradeResourceState_Response) ProtoMessage() {} func (x *UpgradeResourceState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[38] + mi := &file_tfplugin6_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2197,7 +2416,7 @@ func (x *UpgradeResourceState_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use UpgradeResourceState_Response.ProtoReflect.Descriptor instead. func (*UpgradeResourceState_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{10, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{11, 1} } func (x *UpgradeResourceState_Response) GetUpgradedState() *DynamicValue { @@ -2214,6 +2433,13 @@ func (x *UpgradeResourceState_Response) GetDiagnostics() []*Diagnostic { return nil } +func (x *UpgradeResourceState_Response) GetDeferred() []*DeferredAction { + if x != nil { + return x.Deferred + } + return nil +} + type ValidateResourceConfig_Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2226,7 +2452,7 @@ type ValidateResourceConfig_Request struct { func (x *ValidateResourceConfig_Request) Reset() { *x = ValidateResourceConfig_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[39] + mi := &file_tfplugin6_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2239,7 +2465,7 @@ func (x *ValidateResourceConfig_Request) String() string { func (*ValidateResourceConfig_Request) ProtoMessage() {} func (x *ValidateResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[39] + mi := &file_tfplugin6_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2252,7 +2478,7 @@ func (x *ValidateResourceConfig_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateResourceConfig_Request.ProtoReflect.Descriptor instead. func (*ValidateResourceConfig_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{11, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{12, 0} } func (x *ValidateResourceConfig_Request) GetTypeName() string { @@ -2280,7 +2506,7 @@ type ValidateResourceConfig_Response struct { func (x *ValidateResourceConfig_Response) Reset() { *x = ValidateResourceConfig_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[40] + mi := &file_tfplugin6_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2293,7 +2519,7 @@ func (x *ValidateResourceConfig_Response) String() string { func (*ValidateResourceConfig_Response) ProtoMessage() {} func (x *ValidateResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[40] + mi := &file_tfplugin6_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2306,7 +2532,7 @@ func (x *ValidateResourceConfig_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidateResourceConfig_Response.ProtoReflect.Descriptor instead. func (*ValidateResourceConfig_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{11, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{12, 1} } func (x *ValidateResourceConfig_Response) GetDiagnostics() []*Diagnostic { @@ -2328,7 +2554,7 @@ type ValidateDataResourceConfig_Request struct { func (x *ValidateDataResourceConfig_Request) Reset() { *x = ValidateDataResourceConfig_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[41] + mi := &file_tfplugin6_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2341,7 +2567,7 @@ func (x *ValidateDataResourceConfig_Request) String() string { func (*ValidateDataResourceConfig_Request) ProtoMessage() {} func (x *ValidateDataResourceConfig_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[41] + mi := &file_tfplugin6_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2354,7 +2580,7 @@ func (x *ValidateDataResourceConfig_Request) ProtoReflect() protoreflect.Message // Deprecated: Use ValidateDataResourceConfig_Request.ProtoReflect.Descriptor instead. func (*ValidateDataResourceConfig_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{12, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{13, 0} } func (x *ValidateDataResourceConfig_Request) GetTypeName() string { @@ -2382,7 +2608,7 @@ type ValidateDataResourceConfig_Response struct { func (x *ValidateDataResourceConfig_Response) Reset() { *x = ValidateDataResourceConfig_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[42] + mi := &file_tfplugin6_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2395,7 +2621,7 @@ func (x *ValidateDataResourceConfig_Response) String() string { func (*ValidateDataResourceConfig_Response) ProtoMessage() {} func (x *ValidateDataResourceConfig_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[42] + mi := &file_tfplugin6_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2408,7 +2634,7 @@ func (x *ValidateDataResourceConfig_Response) ProtoReflect() protoreflect.Messag // Deprecated: Use ValidateDataResourceConfig_Response.ProtoReflect.Descriptor instead. func (*ValidateDataResourceConfig_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{12, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{13, 1} } func (x *ValidateDataResourceConfig_Response) GetDiagnostics() []*Diagnostic { @@ -2430,7 +2656,7 @@ type ConfigureProvider_Request struct { func (x *ConfigureProvider_Request) Reset() { *x = ConfigureProvider_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[43] + mi := &file_tfplugin6_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2443,7 +2669,7 @@ func (x *ConfigureProvider_Request) String() string { func (*ConfigureProvider_Request) ProtoMessage() {} func (x *ConfigureProvider_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[43] + mi := &file_tfplugin6_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2456,7 +2682,7 @@ func (x *ConfigureProvider_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureProvider_Request.ProtoReflect.Descriptor instead. func (*ConfigureProvider_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{13, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{14, 0} } func (x *ConfigureProvider_Request) GetTerraformVersion() string { @@ -2484,7 +2710,7 @@ type ConfigureProvider_Response struct { func (x *ConfigureProvider_Response) Reset() { *x = ConfigureProvider_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[44] + mi := &file_tfplugin6_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2497,7 +2723,7 @@ func (x *ConfigureProvider_Response) String() string { func (*ConfigureProvider_Response) ProtoMessage() {} func (x *ConfigureProvider_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[44] + mi := &file_tfplugin6_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2510,7 +2736,7 @@ func (x *ConfigureProvider_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureProvider_Response.ProtoReflect.Descriptor instead. func (*ConfigureProvider_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{13, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{14, 1} } func (x *ConfigureProvider_Response) GetDiagnostics() []*Diagnostic { @@ -2537,12 +2763,18 @@ type ReadResource_Request struct { CurrentState *DynamicValue `protobuf:"bytes,2,opt,name=current_state,json=currentState,proto3" json:"current_state,omitempty"` Private []byte `protobuf:"bytes,3,opt,name=private,proto3" json:"private,omitempty"` ProviderMeta *DynamicValue `protobuf:"bytes,4,opt,name=provider_meta,json=providerMeta,proto3" json:"provider_meta,omitempty"` + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to retrieve the current state + // of the object. + DeferAllowed bool `protobuf:"varint,5,opt,name=defer_allowed,json=deferAllowed,proto3" json:"defer_allowed,omitempty"` } func (x *ReadResource_Request) Reset() { *x = ReadResource_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[45] + mi := &file_tfplugin6_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2555,7 +2787,7 @@ func (x *ReadResource_Request) String() string { func (*ReadResource_Request) ProtoMessage() {} func (x *ReadResource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[45] + mi := &file_tfplugin6_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2568,7 +2800,7 @@ func (x *ReadResource_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadResource_Request.ProtoReflect.Descriptor instead. func (*ReadResource_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{14, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{15, 0} } func (x *ReadResource_Request) GetTypeName() string { @@ -2599,6 +2831,13 @@ func (x *ReadResource_Request) GetProviderMeta() *DynamicValue { return nil } +func (x *ReadResource_Request) GetDeferAllowed() bool { + if x != nil { + return x.DeferAllowed + } + return false +} + type ReadResource_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2607,12 +2846,22 @@ type ReadResource_Response struct { NewState *DynamicValue `protobuf:"bytes,1,opt,name=new_state,json=newState,proto3" json:"new_state,omitempty"` Diagnostics []*Diagnostic `protobuf:"bytes,2,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` Private []byte `protobuf:"bytes,3,opt,name=private,proto3" json:"private,omitempty"` + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still use the partial "new_state" value + // to plan downstream actions but will then defer them until a + // future run where a similar ReadResource request can return + // a complete result. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why reading is + // impossible. + Deferred []*DeferredAction `protobuf:"bytes,4,rep,name=deferred,proto3" json:"deferred,omitempty"` } func (x *ReadResource_Response) Reset() { *x = ReadResource_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[46] + mi := &file_tfplugin6_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2625,7 +2874,7 @@ func (x *ReadResource_Response) String() string { func (*ReadResource_Response) ProtoMessage() {} func (x *ReadResource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[46] + mi := &file_tfplugin6_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2638,7 +2887,7 @@ func (x *ReadResource_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadResource_Response.ProtoReflect.Descriptor instead. func (*ReadResource_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{14, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{15, 1} } func (x *ReadResource_Response) GetNewState() *DynamicValue { @@ -2662,6 +2911,13 @@ func (x *ReadResource_Response) GetPrivate() []byte { return nil } +func (x *ReadResource_Response) GetDeferred() []*DeferredAction { + if x != nil { + return x.Deferred + } + return nil +} + type PlanResourceChange_Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2673,12 +2929,17 @@ type PlanResourceChange_Request struct { Config *DynamicValue `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` PriorPrivate []byte `protobuf:"bytes,5,opt,name=prior_private,json=priorPrivate,proto3" json:"prior_private,omitempty"` ProviderMeta *DynamicValue `protobuf:"bytes,6,opt,name=provider_meta,json=providerMeta,proto3" json:"provider_meta,omitempty"` + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to fully plan the change. + DeferAllowed bool `protobuf:"varint,7,opt,name=defer_allowed,json=deferAllowed,proto3" json:"defer_allowed,omitempty"` } func (x *PlanResourceChange_Request) Reset() { *x = PlanResourceChange_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[47] + mi := &file_tfplugin6_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2691,7 +2952,7 @@ func (x *PlanResourceChange_Request) String() string { func (*PlanResourceChange_Request) ProtoMessage() {} func (x *PlanResourceChange_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[47] + mi := &file_tfplugin6_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2704,7 +2965,7 @@ func (x *PlanResourceChange_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanResourceChange_Request.ProtoReflect.Descriptor instead. func (*PlanResourceChange_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{15, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{16, 0} } func (x *PlanResourceChange_Request) GetTypeName() string { @@ -2749,6 +3010,13 @@ func (x *PlanResourceChange_Request) GetProviderMeta() *DynamicValue { return nil } +func (x *PlanResourceChange_Request) GetDeferAllowed() bool { + if x != nil { + return x.DeferAllowed + } + return false +} + type PlanResourceChange_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2758,6 +3026,15 @@ type PlanResourceChange_Response struct { RequiresReplace []*AttributePath `protobuf:"bytes,2,rep,name=requires_replace,json=requiresReplace,proto3" json:"requires_replace,omitempty"` PlannedPrivate []byte `protobuf:"bytes,3,opt,name=planned_private,json=plannedPrivate,proto3" json:"planned_private,omitempty"` Diagnostics []*Diagnostic `protobuf:"bytes,4,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still present the planned action to the + // user for review as a deferred action but will not actually apply + // the change without first asking for a new plan with more information. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why planning is + // impossible. + Deferred []*DeferredAction `protobuf:"bytes,6,rep,name=deferred,proto3" json:"deferred,omitempty"` // This may be set only by the helper/schema "SDK" in the main Terraform // repository, to request that Terraform Core >=0.12 permit additional // inconsistencies that can result from the legacy SDK type system @@ -2775,7 +3052,7 @@ type PlanResourceChange_Response struct { func (x *PlanResourceChange_Response) Reset() { *x = PlanResourceChange_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[48] + mi := &file_tfplugin6_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2788,7 +3065,7 @@ func (x *PlanResourceChange_Response) String() string { func (*PlanResourceChange_Response) ProtoMessage() {} func (x *PlanResourceChange_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[48] + mi := &file_tfplugin6_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2801,7 +3078,7 @@ func (x *PlanResourceChange_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanResourceChange_Response.ProtoReflect.Descriptor instead. func (*PlanResourceChange_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{15, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{16, 1} } func (x *PlanResourceChange_Response) GetPlannedState() *DynamicValue { @@ -2832,6 +3109,13 @@ func (x *PlanResourceChange_Response) GetDiagnostics() []*Diagnostic { return nil } +func (x *PlanResourceChange_Response) GetDeferred() []*DeferredAction { + if x != nil { + return x.Deferred + } + return nil +} + func (x *PlanResourceChange_Response) GetLegacyTypeSystem() bool { if x != nil { return x.LegacyTypeSystem @@ -2855,7 +3139,7 @@ type ApplyResourceChange_Request struct { func (x *ApplyResourceChange_Request) Reset() { *x = ApplyResourceChange_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[49] + mi := &file_tfplugin6_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2868,7 +3152,7 @@ func (x *ApplyResourceChange_Request) String() string { func (*ApplyResourceChange_Request) ProtoMessage() {} func (x *ApplyResourceChange_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[49] + mi := &file_tfplugin6_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2881,7 +3165,7 @@ func (x *ApplyResourceChange_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyResourceChange_Request.ProtoReflect.Descriptor instead. func (*ApplyResourceChange_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{16, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{17, 0} } func (x *ApplyResourceChange_Request) GetTypeName() string { @@ -2951,7 +3235,7 @@ type ApplyResourceChange_Response struct { func (x *ApplyResourceChange_Response) Reset() { *x = ApplyResourceChange_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[50] + mi := &file_tfplugin6_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2964,7 +3248,7 @@ func (x *ApplyResourceChange_Response) String() string { func (*ApplyResourceChange_Response) ProtoMessage() {} func (x *ApplyResourceChange_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[50] + mi := &file_tfplugin6_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2977,7 +3261,7 @@ func (x *ApplyResourceChange_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyResourceChange_Response.ProtoReflect.Descriptor instead. func (*ApplyResourceChange_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{16, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{17, 1} } func (x *ApplyResourceChange_Response) GetNewState() *DynamicValue { @@ -3015,12 +3299,17 @@ type ImportResourceState_Request struct { TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to import the requested object. + DeferAllowed bool `protobuf:"varint,4,opt,name=defer_allowed,json=deferAllowed,proto3" json:"defer_allowed,omitempty"` } func (x *ImportResourceState_Request) Reset() { *x = ImportResourceState_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[51] + mi := &file_tfplugin6_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3033,7 +3322,7 @@ func (x *ImportResourceState_Request) String() string { func (*ImportResourceState_Request) ProtoMessage() {} func (x *ImportResourceState_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[51] + mi := &file_tfplugin6_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3046,7 +3335,7 @@ func (x *ImportResourceState_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportResourceState_Request.ProtoReflect.Descriptor instead. func (*ImportResourceState_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{17, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{18, 0} } func (x *ImportResourceState_Request) GetTypeName() string { @@ -3063,6 +3352,13 @@ func (x *ImportResourceState_Request) GetId() string { return "" } +func (x *ImportResourceState_Request) GetDeferAllowed() bool { + if x != nil { + return x.DeferAllowed + } + return false +} + type ImportResourceState_ImportedResource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3076,7 +3372,7 @@ type ImportResourceState_ImportedResource struct { func (x *ImportResourceState_ImportedResource) Reset() { *x = ImportResourceState_ImportedResource{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[52] + mi := &file_tfplugin6_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3089,7 +3385,7 @@ func (x *ImportResourceState_ImportedResource) String() string { func (*ImportResourceState_ImportedResource) ProtoMessage() {} func (x *ImportResourceState_ImportedResource) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[52] + mi := &file_tfplugin6_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3102,7 +3398,7 @@ func (x *ImportResourceState_ImportedResource) ProtoReflect() protoreflect.Messa // Deprecated: Use ImportResourceState_ImportedResource.ProtoReflect.Descriptor instead. func (*ImportResourceState_ImportedResource) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{17, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{18, 1} } func (x *ImportResourceState_ImportedResource) GetTypeName() string { @@ -3133,12 +3429,22 @@ type ImportResourceState_Response struct { ImportedResources []*ImportResourceState_ImportedResource `protobuf:"bytes,1,rep,name=imported_resources,json=importedResources,proto3" json:"imported_resources,omitempty"` Diagnostics []*Diagnostic `protobuf:"bytes,2,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will treat this object as entirely unknown + // during downstream planning and defer the import until a later + // run when there's hopefully more information available. + // + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why importing is + // impossible. + Deferred []*DeferredAction `protobuf:"bytes,3,rep,name=deferred,proto3" json:"deferred,omitempty"` } func (x *ImportResourceState_Response) Reset() { *x = ImportResourceState_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[53] + mi := &file_tfplugin6_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3151,7 +3457,7 @@ func (x *ImportResourceState_Response) String() string { func (*ImportResourceState_Response) ProtoMessage() {} func (x *ImportResourceState_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[53] + mi := &file_tfplugin6_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3164,7 +3470,7 @@ func (x *ImportResourceState_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportResourceState_Response.ProtoReflect.Descriptor instead. func (*ImportResourceState_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{17, 2} + return file_tfplugin6_proto_rawDescGZIP(), []int{18, 2} } func (x *ImportResourceState_Response) GetImportedResources() []*ImportResourceState_ImportedResource { @@ -3181,6 +3487,13 @@ func (x *ImportResourceState_Response) GetDiagnostics() []*Diagnostic { return nil } +func (x *ImportResourceState_Response) GetDeferred() []*DeferredAction { + if x != nil { + return x.Deferred + } + return nil +} + type ReadDataSource_Request struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3189,12 +3502,17 @@ type ReadDataSource_Request struct { TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` Config *DynamicValue `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` ProviderMeta *DynamicValue `protobuf:"bytes,3,opt,name=provider_meta,json=providerMeta,proto3" json:"provider_meta,omitempty"` + // Terraform Core will set this if it will honor elements of + // "deferred" in the response. If this field is not set then + // a provider must return error diagnostics whenever it has + // insufficient information to fetch the requested remote object. + DeferAllowed bool `protobuf:"varint,4,opt,name=defer_allowed,json=deferAllowed,proto3" json:"defer_allowed,omitempty"` } func (x *ReadDataSource_Request) Reset() { *x = ReadDataSource_Request{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[54] + mi := &file_tfplugin6_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3207,7 +3525,7 @@ func (x *ReadDataSource_Request) String() string { func (*ReadDataSource_Request) ProtoMessage() {} func (x *ReadDataSource_Request) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[54] + mi := &file_tfplugin6_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3220,7 +3538,7 @@ func (x *ReadDataSource_Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadDataSource_Request.ProtoReflect.Descriptor instead. func (*ReadDataSource_Request) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{18, 0} + return file_tfplugin6_proto_rawDescGZIP(), []int{19, 0} } func (x *ReadDataSource_Request) GetTypeName() string { @@ -3244,6 +3562,13 @@ func (x *ReadDataSource_Request) GetProviderMeta() *DynamicValue { return nil } +func (x *ReadDataSource_Request) GetDeferAllowed() bool { + if x != nil { + return x.DeferAllowed + } + return false +} + type ReadDataSource_Response struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3251,12 +3576,22 @@ type ReadDataSource_Response struct { State *DynamicValue `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` Diagnostics []*Diagnostic `protobuf:"bytes,2,rep,name=diagnostics,proto3" json:"diagnostics,omitempty"` + // If the request set defer_allowed to true then the provider may + // annotate a response with one or more deferral reasons, in which + // case Terraform Core will still use the partial "state" value + // to plan downstream actions but will then defer them until a + // future run where a similar ReadDataSource request can return + // a complete result. + // Don't set this if the request did not have defer_allowed set; + // instead return error diagnostics explaining why reading is + // impossible. + Deferred []*DeferredAction `protobuf:"bytes,3,rep,name=deferred,proto3" json:"deferred,omitempty"` } func (x *ReadDataSource_Response) Reset() { *x = ReadDataSource_Response{} if protoimpl.UnsafeEnabled { - mi := &file_tfplugin6_proto_msgTypes[55] + mi := &file_tfplugin6_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3269,7 +3604,7 @@ func (x *ReadDataSource_Response) String() string { func (*ReadDataSource_Response) ProtoMessage() {} func (x *ReadDataSource_Response) ProtoReflect() protoreflect.Message { - mi := &file_tfplugin6_proto_msgTypes[55] + mi := &file_tfplugin6_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3282,7 +3617,7 @@ func (x *ReadDataSource_Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ReadDataSource_Response.ProtoReflect.Descriptor instead. func (*ReadDataSource_Response) Descriptor() ([]byte, []int) { - return file_tfplugin6_proto_rawDescGZIP(), []int{18, 1} + return file_tfplugin6_proto_rawDescGZIP(), []int{19, 1} } func (x *ReadDataSource_Response) GetState() *DynamicValue { @@ -3299,6 +3634,13 @@ func (x *ReadDataSource_Response) GetDiagnostics() []*Diagnostic { return nil } +func (x *ReadDataSource_Response) GetDeferred() []*DeferredAction { + if x != nil { + return x.Deferred + } + return nil +} + var File_tfplugin6_proto protoreflect.FileDescriptor var file_tfplugin6_proto_rawDesc = []byte{ @@ -3438,162 +3780,198 @@ var file_tfplugin6_proto_rawDesc = []byte{ 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x67, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xa7, 0x03, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0xa8, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, - 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x12, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, - 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, - 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, - 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, - 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x31, 0x0a, - 0x12, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x1a, 0x2f, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0xa0, 0x05, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x09, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0xff, 0x04, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2d, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x65, - 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x6c, 0x0a, 0x13, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, - 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x11, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, - 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x36, 0x0a, 0x0d, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x4d, 0x65, 0x74, 0x61, 0x12, 0x4e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, - 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x1a, 0x55, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0x84, 0x03, 0x0a, 0x0e, 0x44, 0x65, 0x66, 0x65, + 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x0c, 0x6f, 0x74, + 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x25, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, + 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x74, 0x68, 0x65, + 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0b, 0x6f, 0x74, 0x68, 0x65, 0x72, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x61, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, + 0x48, 0x00, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x61, 0x0a, 0x17, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x75, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x6e, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x1a, 0x0d, 0x0a, 0x0b, + 0x4f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x1a, 0x47, 0x0a, 0x0d, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x36, 0x0a, 0x09, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xa7, + 0x03, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x09, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0xa8, 0x02, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, + 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, + 0x4c, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x36, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, + 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x1a, 0x31, 0x0a, 0x12, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x2f, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xa0, 0x05, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x09, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0xff, 0x04, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x65, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x6c, 0x0a, 0x13, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, + 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, + 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, + 0x69, 0x63, 0x73, 0x12, 0x36, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0c, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x4e, 0x0a, 0x13, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x70, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, + 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x55, 0x0a, 0x14, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x57, 0x0a, 0x16, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x57, 0x0a, 0x16, 0x44, - 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 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, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x36, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x99, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, - 0x3a, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x99, 0x01, 0x0a, 0x16, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x3a, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, + 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, + 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0xed, 0x02, 0x0a, 0x14, 0x55, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x1a, 0x97, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x09, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x52, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x72, 0x61, 0x77, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x65, + 0x66, 0x65, 0x72, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x1a, 0xba, 0x01, 0x0a, 0x08, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0e, 0x75, 0x70, 0x67, 0x72, 0x61, + 0x64, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, + 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0d, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, + 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x12, 0x35, 0x0a, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, + 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, + 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x1a, 0x57, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, - 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, - 0x22, 0x90, 0x02, 0x0a, 0x14, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x72, 0x0a, 0x07, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x09, 0x72, - 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x61, 0x77, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x08, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x83, 0x01, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0e, 0x75, 0x70, - 0x67, 0x72, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0d, 0x75, 0x70, 0x67, - 0x72, 0x61, 0x64, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, - 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x57, - 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, - 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, - 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, - 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0xba, 0x01, 0x0a, - 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x57, 0x0a, 0x07, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, - 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x11, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x1a, - 0x67, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, - 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x22, 0xba, 0x01, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, + 0x57, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, - 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0xe3, 0x02, - 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0xbc, - 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, - 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x93, 0x01, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6e, 0x65, - 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, - 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, + 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0xc1, 0x01, + 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x1a, 0x67, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, + 0x0a, 0x11, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x72, 0x72, 0x61, + 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x43, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, + 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x73, 0x22, 0xbf, 0x03, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x1a, 0xe1, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, + 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, + 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, - 0x61, 0x74, 0x65, 0x22, 0xf2, 0x04, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xbb, 0x02, 0x0a, 0x07, 0x52, + 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, + 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x65, 0x72, 0x41, + 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x1a, 0xca, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x08, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, + 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, + 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x08, + 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, + 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, + 0x72, 0x65, 0x64, 0x22, 0xce, 0x05, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xe0, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, @@ -3613,187 +3991,205 @@ var file_tfplugin6_proto_rawDesc = []byte{ 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x9d, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, - 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x5f, - 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x6c, 0x61, 0x6e, - 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, - 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x54, 0x79, - 0x70, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x92, 0x04, 0x0a, 0x13, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x1a, 0xb6, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x70, 0x72, 0x69, - 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, - 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, + 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0c, 0x64, 0x65, 0x66, 0x65, 0x72, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x1a, 0xd4, 0x02, + 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x6c, + 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x61, - 0x6e, 0x6e, 0x65, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0xc1, 0x01, 0x0a, 0x08, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x6e, + 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x43, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0f, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x27, 0x0a, + 0x0f, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, - 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, - 0x2c, 0x0a, 0x12, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x65, 0x67, - 0x61, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0xed, 0x02, - 0x0a, 0x13, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x36, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, 0x78, 0x0a, - 0x10, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2d, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x35, 0x0a, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, + 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x65, + 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x10, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x54, 0x79, 0x70, 0x65, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x22, 0x92, 0x04, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0xb6, 0x02, 0x0a, + 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x3c, 0x0a, 0x0d, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x0c, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, - 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x1a, 0xa3, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x12, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x49, 0x6d, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x11, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, - 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, - 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x22, 0x9c, 0x02, - 0x0a, 0x0e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x1a, 0x95, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, + 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x27, + 0x0a, 0x0f, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x64, + 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0xc1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, + 0x6e, 0x65, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, + 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6c, + 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x54, + 0x79, 0x70, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0xc9, 0x03, 0x0a, 0x13, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x1a, 0x5b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, + 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, + 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x64, 0x65, 0x66, 0x65, 0x72, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x1a, 0x78, + 0x0a, 0x10, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x1a, 0xda, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x12, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x11, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, + 0x63, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x35, + 0x0a, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, + 0x65, 0x72, 0x72, 0x65, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x65, 0x66, + 0x65, 0x72, 0x72, 0x65, 0x64, 0x22, 0xf9, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, 0xba, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x0d, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x65, 0x72, 0x41, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x1a, 0xa9, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x72, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, - 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, - 0x63, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, - 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x2a, 0x25, 0x0a, 0x0a, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x4c, - 0x41, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x41, 0x52, 0x4b, 0x44, 0x4f, 0x57, - 0x4e, 0x10, 0x01, 0x32, 0x9c, 0x0a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x1e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, - 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x66, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, 0x74, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x0b, 0x64, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x64, 0x65, + 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x44, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, + 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, + 0x64, 0x2a, 0x25, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4b, 0x69, 0x6e, 0x64, 0x12, + 0x09, 0x0a, 0x05, 0x50, 0x4c, 0x41, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x41, + 0x52, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x01, 0x32, 0x9c, 0x0a, 0x0a, 0x08, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, + 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, + 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x24, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x29, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x29, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x2d, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x69, 0x0a, 0x14, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x1a, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x14, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x27, + 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x36, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x60, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, + 0x6e, 0x36, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, + 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, + 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x74, + 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, + 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x26, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x74, 0x66, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x55, - 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x11, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x12, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x36, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, - 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, 0x64, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x63, 0x0a, 0x12, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x25, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x36, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x36, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, - 0x0a, 0x13, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x26, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x36, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, - 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x74, 0x66, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, 0x74, 0x61, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x51, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, - 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 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, 0x74, 0x66, - 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0e, 0x52, + 0x65, 0x61, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x2e, + 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x44, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x2e, 0x52, 0x65, 0x61, + 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x36, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 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, 0x74, 0x66, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x36, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3809,7 +4205,7 @@ func file_tfplugin6_proto_rawDescGZIP() []byte { } var file_tfplugin6_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_tfplugin6_proto_msgTypes = make([]protoimpl.MessageInfo, 56) +var file_tfplugin6_proto_msgTypes = make([]protoimpl.MessageInfo, 59) var file_tfplugin6_proto_goTypes = []interface{}{ (StringKind)(0), // 0: tfplugin6.StringKind (Diagnostic_Severity)(0), // 1: tfplugin6.Diagnostic.Severity @@ -3822,149 +4218,161 @@ var file_tfplugin6_proto_goTypes = []interface{}{ (*RawState)(nil), // 8: tfplugin6.RawState (*Schema)(nil), // 9: tfplugin6.Schema (*ServerCapabilities)(nil), // 10: tfplugin6.ServerCapabilities - (*GetMetadata)(nil), // 11: tfplugin6.GetMetadata - (*GetProviderSchema)(nil), // 12: tfplugin6.GetProviderSchema - (*ValidateProviderConfig)(nil), // 13: tfplugin6.ValidateProviderConfig - (*UpgradeResourceState)(nil), // 14: tfplugin6.UpgradeResourceState - (*ValidateResourceConfig)(nil), // 15: tfplugin6.ValidateResourceConfig - (*ValidateDataResourceConfig)(nil), // 16: tfplugin6.ValidateDataResourceConfig - (*ConfigureProvider)(nil), // 17: tfplugin6.ConfigureProvider - (*ReadResource)(nil), // 18: tfplugin6.ReadResource - (*PlanResourceChange)(nil), // 19: tfplugin6.PlanResourceChange - (*ApplyResourceChange)(nil), // 20: tfplugin6.ApplyResourceChange - (*ImportResourceState)(nil), // 21: tfplugin6.ImportResourceState - (*ReadDataSource)(nil), // 22: tfplugin6.ReadDataSource - (*AttributePath_Step)(nil), // 23: tfplugin6.AttributePath.Step - (*StopProvider_Request)(nil), // 24: tfplugin6.StopProvider.Request - (*StopProvider_Response)(nil), // 25: tfplugin6.StopProvider.Response - nil, // 26: tfplugin6.RawState.FlatmapEntry - (*Schema_Block)(nil), // 27: tfplugin6.Schema.Block - (*Schema_Attribute)(nil), // 28: tfplugin6.Schema.Attribute - (*Schema_NestedBlock)(nil), // 29: tfplugin6.Schema.NestedBlock - (*Schema_Object)(nil), // 30: tfplugin6.Schema.Object - (*GetMetadata_Request)(nil), // 31: tfplugin6.GetMetadata.Request - (*GetMetadata_Response)(nil), // 32: tfplugin6.GetMetadata.Response - (*GetMetadata_DataSourceMetadata)(nil), // 33: tfplugin6.GetMetadata.DataSourceMetadata - (*GetMetadata_ResourceMetadata)(nil), // 34: tfplugin6.GetMetadata.ResourceMetadata - (*GetProviderSchema_Request)(nil), // 35: tfplugin6.GetProviderSchema.Request - (*GetProviderSchema_Response)(nil), // 36: tfplugin6.GetProviderSchema.Response - nil, // 37: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry - nil, // 38: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry - (*ValidateProviderConfig_Request)(nil), // 39: tfplugin6.ValidateProviderConfig.Request - (*ValidateProviderConfig_Response)(nil), // 40: tfplugin6.ValidateProviderConfig.Response - (*UpgradeResourceState_Request)(nil), // 41: tfplugin6.UpgradeResourceState.Request - (*UpgradeResourceState_Response)(nil), // 42: tfplugin6.UpgradeResourceState.Response - (*ValidateResourceConfig_Request)(nil), // 43: tfplugin6.ValidateResourceConfig.Request - (*ValidateResourceConfig_Response)(nil), // 44: tfplugin6.ValidateResourceConfig.Response - (*ValidateDataResourceConfig_Request)(nil), // 45: tfplugin6.ValidateDataResourceConfig.Request - (*ValidateDataResourceConfig_Response)(nil), // 46: tfplugin6.ValidateDataResourceConfig.Response - (*ConfigureProvider_Request)(nil), // 47: tfplugin6.ConfigureProvider.Request - (*ConfigureProvider_Response)(nil), // 48: tfplugin6.ConfigureProvider.Response - (*ReadResource_Request)(nil), // 49: tfplugin6.ReadResource.Request - (*ReadResource_Response)(nil), // 50: tfplugin6.ReadResource.Response - (*PlanResourceChange_Request)(nil), // 51: tfplugin6.PlanResourceChange.Request - (*PlanResourceChange_Response)(nil), // 52: tfplugin6.PlanResourceChange.Response - (*ApplyResourceChange_Request)(nil), // 53: tfplugin6.ApplyResourceChange.Request - (*ApplyResourceChange_Response)(nil), // 54: tfplugin6.ApplyResourceChange.Response - (*ImportResourceState_Request)(nil), // 55: tfplugin6.ImportResourceState.Request - (*ImportResourceState_ImportedResource)(nil), // 56: tfplugin6.ImportResourceState.ImportedResource - (*ImportResourceState_Response)(nil), // 57: tfplugin6.ImportResourceState.Response - (*ReadDataSource_Request)(nil), // 58: tfplugin6.ReadDataSource.Request - (*ReadDataSource_Response)(nil), // 59: tfplugin6.ReadDataSource.Response + (*DeferredAction)(nil), // 11: tfplugin6.DeferredAction + (*GetMetadata)(nil), // 12: tfplugin6.GetMetadata + (*GetProviderSchema)(nil), // 13: tfplugin6.GetProviderSchema + (*ValidateProviderConfig)(nil), // 14: tfplugin6.ValidateProviderConfig + (*UpgradeResourceState)(nil), // 15: tfplugin6.UpgradeResourceState + (*ValidateResourceConfig)(nil), // 16: tfplugin6.ValidateResourceConfig + (*ValidateDataResourceConfig)(nil), // 17: tfplugin6.ValidateDataResourceConfig + (*ConfigureProvider)(nil), // 18: tfplugin6.ConfigureProvider + (*ReadResource)(nil), // 19: tfplugin6.ReadResource + (*PlanResourceChange)(nil), // 20: tfplugin6.PlanResourceChange + (*ApplyResourceChange)(nil), // 21: tfplugin6.ApplyResourceChange + (*ImportResourceState)(nil), // 22: tfplugin6.ImportResourceState + (*ReadDataSource)(nil), // 23: tfplugin6.ReadDataSource + (*AttributePath_Step)(nil), // 24: tfplugin6.AttributePath.Step + (*StopProvider_Request)(nil), // 25: tfplugin6.StopProvider.Request + (*StopProvider_Response)(nil), // 26: tfplugin6.StopProvider.Response + nil, // 27: tfplugin6.RawState.FlatmapEntry + (*Schema_Block)(nil), // 28: tfplugin6.Schema.Block + (*Schema_Attribute)(nil), // 29: tfplugin6.Schema.Attribute + (*Schema_NestedBlock)(nil), // 30: tfplugin6.Schema.NestedBlock + (*Schema_Object)(nil), // 31: tfplugin6.Schema.Object + (*DeferredAction_OtherReason)(nil), // 32: tfplugin6.DeferredAction.OtherReason + (*DeferredAction_ConfigUnknown)(nil), // 33: tfplugin6.DeferredAction.ConfigUnknown + (*GetMetadata_Request)(nil), // 34: tfplugin6.GetMetadata.Request + (*GetMetadata_Response)(nil), // 35: tfplugin6.GetMetadata.Response + (*GetMetadata_DataSourceMetadata)(nil), // 36: tfplugin6.GetMetadata.DataSourceMetadata + (*GetMetadata_ResourceMetadata)(nil), // 37: tfplugin6.GetMetadata.ResourceMetadata + (*GetProviderSchema_Request)(nil), // 38: tfplugin6.GetProviderSchema.Request + (*GetProviderSchema_Response)(nil), // 39: tfplugin6.GetProviderSchema.Response + nil, // 40: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry + nil, // 41: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry + (*ValidateProviderConfig_Request)(nil), // 42: tfplugin6.ValidateProviderConfig.Request + (*ValidateProviderConfig_Response)(nil), // 43: tfplugin6.ValidateProviderConfig.Response + (*UpgradeResourceState_Request)(nil), // 44: tfplugin6.UpgradeResourceState.Request + (*UpgradeResourceState_Response)(nil), // 45: tfplugin6.UpgradeResourceState.Response + (*ValidateResourceConfig_Request)(nil), // 46: tfplugin6.ValidateResourceConfig.Request + (*ValidateResourceConfig_Response)(nil), // 47: tfplugin6.ValidateResourceConfig.Response + (*ValidateDataResourceConfig_Request)(nil), // 48: tfplugin6.ValidateDataResourceConfig.Request + (*ValidateDataResourceConfig_Response)(nil), // 49: tfplugin6.ValidateDataResourceConfig.Response + (*ConfigureProvider_Request)(nil), // 50: tfplugin6.ConfigureProvider.Request + (*ConfigureProvider_Response)(nil), // 51: tfplugin6.ConfigureProvider.Response + (*ReadResource_Request)(nil), // 52: tfplugin6.ReadResource.Request + (*ReadResource_Response)(nil), // 53: tfplugin6.ReadResource.Response + (*PlanResourceChange_Request)(nil), // 54: tfplugin6.PlanResourceChange.Request + (*PlanResourceChange_Response)(nil), // 55: tfplugin6.PlanResourceChange.Response + (*ApplyResourceChange_Request)(nil), // 56: tfplugin6.ApplyResourceChange.Request + (*ApplyResourceChange_Response)(nil), // 57: tfplugin6.ApplyResourceChange.Response + (*ImportResourceState_Request)(nil), // 58: tfplugin6.ImportResourceState.Request + (*ImportResourceState_ImportedResource)(nil), // 59: tfplugin6.ImportResourceState.ImportedResource + (*ImportResourceState_Response)(nil), // 60: tfplugin6.ImportResourceState.Response + (*ReadDataSource_Request)(nil), // 61: tfplugin6.ReadDataSource.Request + (*ReadDataSource_Response)(nil), // 62: tfplugin6.ReadDataSource.Response } var file_tfplugin6_proto_depIdxs = []int32{ 1, // 0: tfplugin6.Diagnostic.severity:type_name -> tfplugin6.Diagnostic.Severity 6, // 1: tfplugin6.Diagnostic.attribute:type_name -> tfplugin6.AttributePath - 23, // 2: tfplugin6.AttributePath.steps:type_name -> tfplugin6.AttributePath.Step - 26, // 3: tfplugin6.RawState.flatmap:type_name -> tfplugin6.RawState.FlatmapEntry - 27, // 4: tfplugin6.Schema.block:type_name -> tfplugin6.Schema.Block - 28, // 5: tfplugin6.Schema.Block.attributes:type_name -> tfplugin6.Schema.Attribute - 29, // 6: tfplugin6.Schema.Block.block_types:type_name -> tfplugin6.Schema.NestedBlock - 0, // 7: tfplugin6.Schema.Block.description_kind:type_name -> tfplugin6.StringKind - 30, // 8: tfplugin6.Schema.Attribute.nested_type:type_name -> tfplugin6.Schema.Object - 0, // 9: tfplugin6.Schema.Attribute.description_kind:type_name -> tfplugin6.StringKind - 27, // 10: tfplugin6.Schema.NestedBlock.block:type_name -> tfplugin6.Schema.Block - 2, // 11: tfplugin6.Schema.NestedBlock.nesting:type_name -> tfplugin6.Schema.NestedBlock.NestingMode - 28, // 12: tfplugin6.Schema.Object.attributes:type_name -> tfplugin6.Schema.Attribute - 3, // 13: tfplugin6.Schema.Object.nesting:type_name -> tfplugin6.Schema.Object.NestingMode - 10, // 14: tfplugin6.GetMetadata.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities - 5, // 15: tfplugin6.GetMetadata.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 33, // 16: tfplugin6.GetMetadata.Response.data_sources:type_name -> tfplugin6.GetMetadata.DataSourceMetadata - 34, // 17: tfplugin6.GetMetadata.Response.resources:type_name -> tfplugin6.GetMetadata.ResourceMetadata - 9, // 18: tfplugin6.GetProviderSchema.Response.provider:type_name -> tfplugin6.Schema - 37, // 19: tfplugin6.GetProviderSchema.Response.resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry - 38, // 20: tfplugin6.GetProviderSchema.Response.data_source_schemas:type_name -> tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry - 5, // 21: tfplugin6.GetProviderSchema.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 9, // 22: tfplugin6.GetProviderSchema.Response.provider_meta:type_name -> tfplugin6.Schema - 10, // 23: tfplugin6.GetProviderSchema.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities - 9, // 24: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry.value:type_name -> tfplugin6.Schema - 9, // 25: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry.value:type_name -> tfplugin6.Schema - 4, // 26: tfplugin6.ValidateProviderConfig.Request.config:type_name -> tfplugin6.DynamicValue - 5, // 27: tfplugin6.ValidateProviderConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 8, // 28: tfplugin6.UpgradeResourceState.Request.raw_state:type_name -> tfplugin6.RawState - 4, // 29: tfplugin6.UpgradeResourceState.Response.upgraded_state:type_name -> tfplugin6.DynamicValue - 5, // 30: tfplugin6.UpgradeResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 31: tfplugin6.ValidateResourceConfig.Request.config:type_name -> tfplugin6.DynamicValue - 5, // 32: tfplugin6.ValidateResourceConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 33: tfplugin6.ValidateDataResourceConfig.Request.config:type_name -> tfplugin6.DynamicValue - 5, // 34: tfplugin6.ValidateDataResourceConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 35: tfplugin6.ConfigureProvider.Request.config:type_name -> tfplugin6.DynamicValue - 5, // 36: tfplugin6.ConfigureProvider.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 37: tfplugin6.ReadResource.Request.current_state:type_name -> tfplugin6.DynamicValue - 4, // 38: tfplugin6.ReadResource.Request.provider_meta:type_name -> tfplugin6.DynamicValue - 4, // 39: tfplugin6.ReadResource.Response.new_state:type_name -> tfplugin6.DynamicValue - 5, // 40: tfplugin6.ReadResource.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 41: tfplugin6.PlanResourceChange.Request.prior_state:type_name -> tfplugin6.DynamicValue - 4, // 42: tfplugin6.PlanResourceChange.Request.proposed_new_state:type_name -> tfplugin6.DynamicValue - 4, // 43: tfplugin6.PlanResourceChange.Request.config:type_name -> tfplugin6.DynamicValue - 4, // 44: tfplugin6.PlanResourceChange.Request.provider_meta:type_name -> tfplugin6.DynamicValue - 4, // 45: tfplugin6.PlanResourceChange.Response.planned_state:type_name -> tfplugin6.DynamicValue - 6, // 46: tfplugin6.PlanResourceChange.Response.requires_replace:type_name -> tfplugin6.AttributePath - 5, // 47: tfplugin6.PlanResourceChange.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 48: tfplugin6.ApplyResourceChange.Request.prior_state:type_name -> tfplugin6.DynamicValue - 4, // 49: tfplugin6.ApplyResourceChange.Request.planned_state:type_name -> tfplugin6.DynamicValue - 4, // 50: tfplugin6.ApplyResourceChange.Request.config:type_name -> tfplugin6.DynamicValue - 4, // 51: tfplugin6.ApplyResourceChange.Request.provider_meta:type_name -> tfplugin6.DynamicValue - 4, // 52: tfplugin6.ApplyResourceChange.Response.new_state:type_name -> tfplugin6.DynamicValue - 5, // 53: tfplugin6.ApplyResourceChange.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 54: tfplugin6.ImportResourceState.ImportedResource.state:type_name -> tfplugin6.DynamicValue - 56, // 55: tfplugin6.ImportResourceState.Response.imported_resources:type_name -> tfplugin6.ImportResourceState.ImportedResource - 5, // 56: tfplugin6.ImportResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 4, // 57: tfplugin6.ReadDataSource.Request.config:type_name -> tfplugin6.DynamicValue - 4, // 58: tfplugin6.ReadDataSource.Request.provider_meta:type_name -> tfplugin6.DynamicValue - 4, // 59: tfplugin6.ReadDataSource.Response.state:type_name -> tfplugin6.DynamicValue - 5, // 60: tfplugin6.ReadDataSource.Response.diagnostics:type_name -> tfplugin6.Diagnostic - 31, // 61: tfplugin6.Provider.GetMetadata:input_type -> tfplugin6.GetMetadata.Request - 35, // 62: tfplugin6.Provider.GetProviderSchema:input_type -> tfplugin6.GetProviderSchema.Request - 39, // 63: tfplugin6.Provider.ValidateProviderConfig:input_type -> tfplugin6.ValidateProviderConfig.Request - 43, // 64: tfplugin6.Provider.ValidateResourceConfig:input_type -> tfplugin6.ValidateResourceConfig.Request - 45, // 65: tfplugin6.Provider.ValidateDataResourceConfig:input_type -> tfplugin6.ValidateDataResourceConfig.Request - 41, // 66: tfplugin6.Provider.UpgradeResourceState:input_type -> tfplugin6.UpgradeResourceState.Request - 47, // 67: tfplugin6.Provider.ConfigureProvider:input_type -> tfplugin6.ConfigureProvider.Request - 49, // 68: tfplugin6.Provider.ReadResource:input_type -> tfplugin6.ReadResource.Request - 51, // 69: tfplugin6.Provider.PlanResourceChange:input_type -> tfplugin6.PlanResourceChange.Request - 53, // 70: tfplugin6.Provider.ApplyResourceChange:input_type -> tfplugin6.ApplyResourceChange.Request - 55, // 71: tfplugin6.Provider.ImportResourceState:input_type -> tfplugin6.ImportResourceState.Request - 58, // 72: tfplugin6.Provider.ReadDataSource:input_type -> tfplugin6.ReadDataSource.Request - 24, // 73: tfplugin6.Provider.StopProvider:input_type -> tfplugin6.StopProvider.Request - 32, // 74: tfplugin6.Provider.GetMetadata:output_type -> tfplugin6.GetMetadata.Response - 36, // 75: tfplugin6.Provider.GetProviderSchema:output_type -> tfplugin6.GetProviderSchema.Response - 40, // 76: tfplugin6.Provider.ValidateProviderConfig:output_type -> tfplugin6.ValidateProviderConfig.Response - 44, // 77: tfplugin6.Provider.ValidateResourceConfig:output_type -> tfplugin6.ValidateResourceConfig.Response - 46, // 78: tfplugin6.Provider.ValidateDataResourceConfig:output_type -> tfplugin6.ValidateDataResourceConfig.Response - 42, // 79: tfplugin6.Provider.UpgradeResourceState:output_type -> tfplugin6.UpgradeResourceState.Response - 48, // 80: tfplugin6.Provider.ConfigureProvider:output_type -> tfplugin6.ConfigureProvider.Response - 50, // 81: tfplugin6.Provider.ReadResource:output_type -> tfplugin6.ReadResource.Response - 52, // 82: tfplugin6.Provider.PlanResourceChange:output_type -> tfplugin6.PlanResourceChange.Response - 54, // 83: tfplugin6.Provider.ApplyResourceChange:output_type -> tfplugin6.ApplyResourceChange.Response - 57, // 84: tfplugin6.Provider.ImportResourceState:output_type -> tfplugin6.ImportResourceState.Response - 59, // 85: tfplugin6.Provider.ReadDataSource:output_type -> tfplugin6.ReadDataSource.Response - 25, // 86: tfplugin6.Provider.StopProvider:output_type -> tfplugin6.StopProvider.Response - 74, // [74:87] is the sub-list for method output_type - 61, // [61:74] is the sub-list for method input_type - 61, // [61:61] is the sub-list for extension type_name - 61, // [61:61] is the sub-list for extension extendee - 0, // [0:61] is the sub-list for field type_name + 24, // 2: tfplugin6.AttributePath.steps:type_name -> tfplugin6.AttributePath.Step + 27, // 3: tfplugin6.RawState.flatmap:type_name -> tfplugin6.RawState.FlatmapEntry + 28, // 4: tfplugin6.Schema.block:type_name -> tfplugin6.Schema.Block + 32, // 5: tfplugin6.DeferredAction.other_reason:type_name -> tfplugin6.DeferredAction.OtherReason + 33, // 6: tfplugin6.DeferredAction.provider_config_unknown:type_name -> tfplugin6.DeferredAction.ConfigUnknown + 33, // 7: tfplugin6.DeferredAction.resource_config_unknown:type_name -> tfplugin6.DeferredAction.ConfigUnknown + 29, // 8: tfplugin6.Schema.Block.attributes:type_name -> tfplugin6.Schema.Attribute + 30, // 9: tfplugin6.Schema.Block.block_types:type_name -> tfplugin6.Schema.NestedBlock + 0, // 10: tfplugin6.Schema.Block.description_kind:type_name -> tfplugin6.StringKind + 31, // 11: tfplugin6.Schema.Attribute.nested_type:type_name -> tfplugin6.Schema.Object + 0, // 12: tfplugin6.Schema.Attribute.description_kind:type_name -> tfplugin6.StringKind + 28, // 13: tfplugin6.Schema.NestedBlock.block:type_name -> tfplugin6.Schema.Block + 2, // 14: tfplugin6.Schema.NestedBlock.nesting:type_name -> tfplugin6.Schema.NestedBlock.NestingMode + 29, // 15: tfplugin6.Schema.Object.attributes:type_name -> tfplugin6.Schema.Attribute + 3, // 16: tfplugin6.Schema.Object.nesting:type_name -> tfplugin6.Schema.Object.NestingMode + 6, // 17: tfplugin6.DeferredAction.ConfigUnknown.attribute:type_name -> tfplugin6.AttributePath + 10, // 18: tfplugin6.GetMetadata.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities + 5, // 19: tfplugin6.GetMetadata.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 36, // 20: tfplugin6.GetMetadata.Response.data_sources:type_name -> tfplugin6.GetMetadata.DataSourceMetadata + 37, // 21: tfplugin6.GetMetadata.Response.resources:type_name -> tfplugin6.GetMetadata.ResourceMetadata + 9, // 22: tfplugin6.GetProviderSchema.Response.provider:type_name -> tfplugin6.Schema + 40, // 23: tfplugin6.GetProviderSchema.Response.resource_schemas:type_name -> tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry + 41, // 24: tfplugin6.GetProviderSchema.Response.data_source_schemas:type_name -> tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry + 5, // 25: tfplugin6.GetProviderSchema.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 9, // 26: tfplugin6.GetProviderSchema.Response.provider_meta:type_name -> tfplugin6.Schema + 10, // 27: tfplugin6.GetProviderSchema.Response.server_capabilities:type_name -> tfplugin6.ServerCapabilities + 9, // 28: tfplugin6.GetProviderSchema.Response.ResourceSchemasEntry.value:type_name -> tfplugin6.Schema + 9, // 29: tfplugin6.GetProviderSchema.Response.DataSourceSchemasEntry.value:type_name -> tfplugin6.Schema + 4, // 30: tfplugin6.ValidateProviderConfig.Request.config:type_name -> tfplugin6.DynamicValue + 5, // 31: tfplugin6.ValidateProviderConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 8, // 32: tfplugin6.UpgradeResourceState.Request.raw_state:type_name -> tfplugin6.RawState + 4, // 33: tfplugin6.UpgradeResourceState.Response.upgraded_state:type_name -> tfplugin6.DynamicValue + 5, // 34: tfplugin6.UpgradeResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 11, // 35: tfplugin6.UpgradeResourceState.Response.deferred:type_name -> tfplugin6.DeferredAction + 4, // 36: tfplugin6.ValidateResourceConfig.Request.config:type_name -> tfplugin6.DynamicValue + 5, // 37: tfplugin6.ValidateResourceConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 4, // 38: tfplugin6.ValidateDataResourceConfig.Request.config:type_name -> tfplugin6.DynamicValue + 5, // 39: tfplugin6.ValidateDataResourceConfig.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 4, // 40: tfplugin6.ConfigureProvider.Request.config:type_name -> tfplugin6.DynamicValue + 5, // 41: tfplugin6.ConfigureProvider.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 4, // 42: tfplugin6.ReadResource.Request.current_state:type_name -> tfplugin6.DynamicValue + 4, // 43: tfplugin6.ReadResource.Request.provider_meta:type_name -> tfplugin6.DynamicValue + 4, // 44: tfplugin6.ReadResource.Response.new_state:type_name -> tfplugin6.DynamicValue + 5, // 45: tfplugin6.ReadResource.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 11, // 46: tfplugin6.ReadResource.Response.deferred:type_name -> tfplugin6.DeferredAction + 4, // 47: tfplugin6.PlanResourceChange.Request.prior_state:type_name -> tfplugin6.DynamicValue + 4, // 48: tfplugin6.PlanResourceChange.Request.proposed_new_state:type_name -> tfplugin6.DynamicValue + 4, // 49: tfplugin6.PlanResourceChange.Request.config:type_name -> tfplugin6.DynamicValue + 4, // 50: tfplugin6.PlanResourceChange.Request.provider_meta:type_name -> tfplugin6.DynamicValue + 4, // 51: tfplugin6.PlanResourceChange.Response.planned_state:type_name -> tfplugin6.DynamicValue + 6, // 52: tfplugin6.PlanResourceChange.Response.requires_replace:type_name -> tfplugin6.AttributePath + 5, // 53: tfplugin6.PlanResourceChange.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 11, // 54: tfplugin6.PlanResourceChange.Response.deferred:type_name -> tfplugin6.DeferredAction + 4, // 55: tfplugin6.ApplyResourceChange.Request.prior_state:type_name -> tfplugin6.DynamicValue + 4, // 56: tfplugin6.ApplyResourceChange.Request.planned_state:type_name -> tfplugin6.DynamicValue + 4, // 57: tfplugin6.ApplyResourceChange.Request.config:type_name -> tfplugin6.DynamicValue + 4, // 58: tfplugin6.ApplyResourceChange.Request.provider_meta:type_name -> tfplugin6.DynamicValue + 4, // 59: tfplugin6.ApplyResourceChange.Response.new_state:type_name -> tfplugin6.DynamicValue + 5, // 60: tfplugin6.ApplyResourceChange.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 4, // 61: tfplugin6.ImportResourceState.ImportedResource.state:type_name -> tfplugin6.DynamicValue + 59, // 62: tfplugin6.ImportResourceState.Response.imported_resources:type_name -> tfplugin6.ImportResourceState.ImportedResource + 5, // 63: tfplugin6.ImportResourceState.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 11, // 64: tfplugin6.ImportResourceState.Response.deferred:type_name -> tfplugin6.DeferredAction + 4, // 65: tfplugin6.ReadDataSource.Request.config:type_name -> tfplugin6.DynamicValue + 4, // 66: tfplugin6.ReadDataSource.Request.provider_meta:type_name -> tfplugin6.DynamicValue + 4, // 67: tfplugin6.ReadDataSource.Response.state:type_name -> tfplugin6.DynamicValue + 5, // 68: tfplugin6.ReadDataSource.Response.diagnostics:type_name -> tfplugin6.Diagnostic + 11, // 69: tfplugin6.ReadDataSource.Response.deferred:type_name -> tfplugin6.DeferredAction + 34, // 70: tfplugin6.Provider.GetMetadata:input_type -> tfplugin6.GetMetadata.Request + 38, // 71: tfplugin6.Provider.GetProviderSchema:input_type -> tfplugin6.GetProviderSchema.Request + 42, // 72: tfplugin6.Provider.ValidateProviderConfig:input_type -> tfplugin6.ValidateProviderConfig.Request + 46, // 73: tfplugin6.Provider.ValidateResourceConfig:input_type -> tfplugin6.ValidateResourceConfig.Request + 48, // 74: tfplugin6.Provider.ValidateDataResourceConfig:input_type -> tfplugin6.ValidateDataResourceConfig.Request + 44, // 75: tfplugin6.Provider.UpgradeResourceState:input_type -> tfplugin6.UpgradeResourceState.Request + 50, // 76: tfplugin6.Provider.ConfigureProvider:input_type -> tfplugin6.ConfigureProvider.Request + 52, // 77: tfplugin6.Provider.ReadResource:input_type -> tfplugin6.ReadResource.Request + 54, // 78: tfplugin6.Provider.PlanResourceChange:input_type -> tfplugin6.PlanResourceChange.Request + 56, // 79: tfplugin6.Provider.ApplyResourceChange:input_type -> tfplugin6.ApplyResourceChange.Request + 58, // 80: tfplugin6.Provider.ImportResourceState:input_type -> tfplugin6.ImportResourceState.Request + 61, // 81: tfplugin6.Provider.ReadDataSource:input_type -> tfplugin6.ReadDataSource.Request + 25, // 82: tfplugin6.Provider.StopProvider:input_type -> tfplugin6.StopProvider.Request + 35, // 83: tfplugin6.Provider.GetMetadata:output_type -> tfplugin6.GetMetadata.Response + 39, // 84: tfplugin6.Provider.GetProviderSchema:output_type -> tfplugin6.GetProviderSchema.Response + 43, // 85: tfplugin6.Provider.ValidateProviderConfig:output_type -> tfplugin6.ValidateProviderConfig.Response + 47, // 86: tfplugin6.Provider.ValidateResourceConfig:output_type -> tfplugin6.ValidateResourceConfig.Response + 49, // 87: tfplugin6.Provider.ValidateDataResourceConfig:output_type -> tfplugin6.ValidateDataResourceConfig.Response + 45, // 88: tfplugin6.Provider.UpgradeResourceState:output_type -> tfplugin6.UpgradeResourceState.Response + 51, // 89: tfplugin6.Provider.ConfigureProvider:output_type -> tfplugin6.ConfigureProvider.Response + 53, // 90: tfplugin6.Provider.ReadResource:output_type -> tfplugin6.ReadResource.Response + 55, // 91: tfplugin6.Provider.PlanResourceChange:output_type -> tfplugin6.PlanResourceChange.Response + 57, // 92: tfplugin6.Provider.ApplyResourceChange:output_type -> tfplugin6.ApplyResourceChange.Response + 60, // 93: tfplugin6.Provider.ImportResourceState:output_type -> tfplugin6.ImportResourceState.Response + 62, // 94: tfplugin6.Provider.ReadDataSource:output_type -> tfplugin6.ReadDataSource.Response + 26, // 95: tfplugin6.Provider.StopProvider:output_type -> tfplugin6.StopProvider.Response + 83, // [83:96] is the sub-list for method output_type + 70, // [70:83] is the sub-list for method input_type + 70, // [70:70] is the sub-list for extension type_name + 70, // [70:70] is the sub-list for extension extendee + 0, // [0:70] is the sub-list for field type_name } func init() { file_tfplugin6_proto_init() } @@ -4058,7 +4466,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMetadata); i { + switch v := v.(*DeferredAction); i { case 0: return &v.state case 1: @@ -4070,7 +4478,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProviderSchema); i { + switch v := v.(*GetMetadata); i { case 0: return &v.state case 1: @@ -4082,7 +4490,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidateProviderConfig); i { + switch v := v.(*GetProviderSchema); i { case 0: return &v.state case 1: @@ -4094,7 +4502,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpgradeResourceState); i { + switch v := v.(*ValidateProviderConfig); i { case 0: return &v.state case 1: @@ -4106,7 +4514,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidateResourceConfig); i { + switch v := v.(*UpgradeResourceState); i { case 0: return &v.state case 1: @@ -4118,7 +4526,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ValidateDataResourceConfig); i { + switch v := v.(*ValidateResourceConfig); i { case 0: return &v.state case 1: @@ -4130,7 +4538,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigureProvider); i { + switch v := v.(*ValidateDataResourceConfig); i { case 0: return &v.state case 1: @@ -4142,7 +4550,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReadResource); i { + switch v := v.(*ConfigureProvider); i { case 0: return &v.state case 1: @@ -4154,7 +4562,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PlanResourceChange); i { + switch v := v.(*ReadResource); i { case 0: return &v.state case 1: @@ -4166,7 +4574,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyResourceChange); i { + switch v := v.(*PlanResourceChange); i { case 0: return &v.state case 1: @@ -4178,7 +4586,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ImportResourceState); i { + switch v := v.(*ApplyResourceChange); i { case 0: return &v.state case 1: @@ -4190,7 +4598,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReadDataSource); i { + switch v := v.(*ImportResourceState); i { case 0: return &v.state case 1: @@ -4202,7 +4610,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AttributePath_Step); i { + switch v := v.(*ReadDataSource); i { case 0: return &v.state case 1: @@ -4214,7 +4622,7 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopProvider_Request); i { + switch v := v.(*AttributePath_Step); i { case 0: return &v.state case 1: @@ -4226,6 +4634,18 @@ func file_tfplugin6_proto_init() { } } file_tfplugin6_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StopProvider_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tfplugin6_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StopProvider_Response); i { case 0: return &v.state @@ -4237,7 +4657,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Schema_Block); i { case 0: return &v.state @@ -4249,7 +4669,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Schema_Attribute); i { case 0: return &v.state @@ -4261,7 +4681,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Schema_NestedBlock); i { case 0: return &v.state @@ -4273,7 +4693,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Schema_Object); i { case 0: return &v.state @@ -4285,7 +4705,31 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeferredAction_OtherReason); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tfplugin6_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeferredAction_ConfigUnknown); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_tfplugin6_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetMetadata_Request); i { case 0: return &v.state @@ -4297,7 +4741,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetMetadata_Response); i { case 0: return &v.state @@ -4309,7 +4753,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetMetadata_DataSourceMetadata); i { case 0: return &v.state @@ -4321,7 +4765,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetMetadata_ResourceMetadata); i { case 0: return &v.state @@ -4333,7 +4777,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetProviderSchema_Request); i { case 0: return &v.state @@ -4345,7 +4789,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetProviderSchema_Response); i { case 0: return &v.state @@ -4357,7 +4801,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateProviderConfig_Request); i { case 0: return &v.state @@ -4369,7 +4813,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateProviderConfig_Response); i { case 0: return &v.state @@ -4381,7 +4825,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpgradeResourceState_Request); i { case 0: return &v.state @@ -4393,7 +4837,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UpgradeResourceState_Response); i { case 0: return &v.state @@ -4405,7 +4849,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateResourceConfig_Request); i { case 0: return &v.state @@ -4417,7 +4861,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateResourceConfig_Response); i { case 0: return &v.state @@ -4429,7 +4873,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateDataResourceConfig_Request); i { case 0: return &v.state @@ -4441,7 +4885,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ValidateDataResourceConfig_Response); i { case 0: return &v.state @@ -4453,7 +4897,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConfigureProvider_Request); i { case 0: return &v.state @@ -4465,7 +4909,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConfigureProvider_Response); i { case 0: return &v.state @@ -4477,7 +4921,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReadResource_Request); i { case 0: return &v.state @@ -4489,7 +4933,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReadResource_Response); i { case 0: return &v.state @@ -4501,7 +4945,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PlanResourceChange_Request); i { case 0: return &v.state @@ -4513,7 +4957,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PlanResourceChange_Response); i { case 0: return &v.state @@ -4525,7 +4969,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplyResourceChange_Request); i { case 0: return &v.state @@ -4537,7 +4981,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ApplyResourceChange_Response); i { case 0: return &v.state @@ -4549,7 +4993,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportResourceState_Request); i { case 0: return &v.state @@ -4561,7 +5005,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportResourceState_ImportedResource); i { case 0: return &v.state @@ -4573,7 +5017,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImportResourceState_Response); i { case 0: return &v.state @@ -4585,7 +5029,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReadDataSource_Request); i { case 0: return &v.state @@ -4597,7 +5041,7 @@ func file_tfplugin6_proto_init() { return nil } } - file_tfplugin6_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + file_tfplugin6_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReadDataSource_Response); i { case 0: return &v.state @@ -4610,7 +5054,12 @@ func file_tfplugin6_proto_init() { } } } - file_tfplugin6_proto_msgTypes[19].OneofWrappers = []interface{}{ + file_tfplugin6_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*DeferredAction_OtherReason_)(nil), + (*DeferredAction_ProviderConfigUnknown)(nil), + (*DeferredAction_ResourceConfigUnknown)(nil), + } + file_tfplugin6_proto_msgTypes[20].OneofWrappers = []interface{}{ (*AttributePath_Step_AttributeName)(nil), (*AttributePath_Step_ElementKeyString)(nil), (*AttributePath_Step_ElementKeyInt)(nil), @@ -4621,7 +5070,7 @@ func file_tfplugin6_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tfplugin6_proto_rawDesc, NumEnums: 4, - NumMessages: 56, + NumMessages: 59, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/tfplugin6/tfplugin6.proto b/internal/tfplugin6/tfplugin6.proto index a5f8d0903f8a..cb60ee615ab4 120000 --- a/internal/tfplugin6/tfplugin6.proto +++ b/internal/tfplugin6/tfplugin6.proto @@ -1 +1 @@ -../../docs/plugin-protocol/tfplugin6.4.proto \ No newline at end of file +../../docs/plugin-protocol/tfplugin6.5.proto \ No newline at end of file